Blocksの活用法

Hidetoshi Mori
Hidetoshi MoriSelf-Employed Consultant at home
Blocksの活用
                   iOS版 

            Hidetoshi Mori
自己紹介

森 英寿

Facebook hidetoshi.mori
Twitter: @h_mori
フリーランスプログラマ
自己紹介

主開発言語

Java/.net/Objective-C/Ruby/PHP

アプリ開発実績

SOICHA iPhone (TweetMe)
ATND暦
Blocks?                 ?



iOS4, MacOSX 10.6から導入
無名関数、クロージャ、 Lambda
Blocksの利点
メソッド定義なく関数を記述できる

関数を変数のように扱える

performedSelectorの代わりに使える

別のソースから処理の差込が行える

まとまった処理の記述が可能
Blocksの構文
^戻り値の型(引数リスト){処理} (実装)
 ^NSInteger(NSInteger i){ return i++; }
 ^{ NSLog(@”block”); }
  ※戻り値の型voidと(引数無し)は省略可

戻り値の型 (^Block変数名)(引数リスト); (宣言)
 id (^block)(NSArray *array, NSUInteger index);
 void (^block)(void);
Block内の自動変数
int val = 1;
void (^block)(void) = ^{NSLog(@”val=%d”, val)};
val = 2;
block(); //blockの実行

> val=1

 Block定義時点のローカル変数がコピーされる
__block指定子
__block int val = 1;
void (^block)(void) = ^{val=2)};
block();
NSLog(@”val=%d”, val);

> val=2

  Blockスコープを超えるには__blockを使う
Blockの格納領域
グローバル(データ)領域 (グローバル変数領域)
  _NSConcreteGlobalBlock

ヒープ領域 (オブジェクト変数領域)
  _NSConcreteMallocBlock

スタック領域 (ローカル変数領域)
  _NSConcreteStackBlock
Blockのコピー
Blockはプリミティブ変数らしきもの
 スタック領域Blockはスコープ終了後、破棄される

Blockを維持するためヒープ領域に手動コピーが必要
 Blockのpropertyは基本 copy で宣言する
Block内変数のコピー
BlockコピーでBlock内変数は浅いコピーになる

ARC時
 BlockはBlock内変数の__strong参照を保持

非ARC時
 Blockは__blockがないBlock内変数をretainする
Blockによる循環参照
BlockのBlock内変数への強参照による循環参照
@property (retain) NSMutableArray array;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-(void)addBlock {
  id block = ^{
     [self method];             self         array
  };
  [array addObject block];
}
                                       block
Blockによる循環参照回避
BlockのBlock内変数への参照を弱参照にする
@property (retain) NSMutableArray array;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-(void)addBlock {
  __block __weak MyClass *weakSelf = self;
  id block = ^{
                                 self          array
     [weakSelf method];
  };
  [array addObject block];
}                                        block
循環参照の予防策
deallocにサウンドBreakPointを設定
BlocksKitの紹介
BSD, MITライセンス

iOS4、MacOSX 10.6以上

A2DynamicDelegateが必要
A2DynamicDelegateの紹介
AssociatedObjectを利用した動的な読込を可能にする
 動的なインスタンス変数の差し込み
 動的なプロトコルの差し込み

カテゴリでインスタンス変数のような仕組みを作れる
BlocksKitの導入手順
BlocksKit/A2DynamicDelegate/に2クラスをコピー
  A2BlockDelegaete、A2DynamicDelegate
自分のプロジェクトにBlocksKit.xcodeprojを追加
libBlocksKit.a、MessageUI.frameworkを追加
その他リンカフラグに「-ObjC -all_load」を追加
ヘッダ検索パスに/BlocksKit**を設定
pchにBlocksKit/BlocksKit.hをimport
BlocksKitの便利メソッド
UIActionSheet#addButtonWithTitle:handler:
- (void)showSheet1 {
    UIActionSheet *sheet1 = [UIActionSheet actionSheetWithTitle:@"Sheet"];
    if (condition1) {
         [sheet1 addButtonWithTitle:@"Action1" handler:^(void) {
            //Action1の処理
       }];
    }
    [sheet1 setCancelButtonIndex:[sheet addButtonWithTitle:@"Close"]];
    [sheet1 showInView:self.view];
}
BlocksKitの便利メソッド
UIAlertView#addButtonWithTitle:handler:
UIAlertView *alert =
[UIAlertView alertViewWithTitle:@"Alert" message:@"UIAlertView Test"];
[alert addButtonWithTitle:@"Action" handler:^(void) {
    NSLog(@"Action");
}];
[alert addButtonWithTitle:@"Close"];
[alert show];
BlocksKitの便利メソッド
NSURLConnection#startConnectionWithRequest:successHandler:

NSURLRequest *req =
[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://d.hatena.ne.jp/h_mori/"]];

[NSURLConnection startConnectionWithRequest:req
               successHandler:^(NSURLConnection *con, NSURLResponse *res, NSData *data){
                   NSString *html =
                   [[[NSString alloc] initWithData:data encoding:NSJapaneseEUCStringEncoding] autorelease];
                   NSLog(@"html=%@", html);
               }
               failureHandler:^(NSURLConnection *con, NSError *err){
                    NSLog(@"NSURLConnection failed : %@", [err localizedDescription]);
               }];
BlocksKitの便利メソッド
UIWebView#didFinishLoadBlock
UIWebView#didFinishWithErrorBlock
UIWebView *webView = [[[UIWebView alloc] init] autorelease];
webView.didFinishLoadBlock = ^(UIWebView *v) {
   NSLog(@"didFinishLoadBlock");
};
webView.didFinishWithErrorBlock = ^(UIWebView *v, NSError *err) {
   NSLog(@"didFinishWithErrorBlock");
};
[webView.dynamicDelegate webViewDidFinishLoad:webView];
[webView loadRequest:[NSURLRequest requestWithURL:[NSURL
URLWithString:@"http://d.hatena.ne.jp/h_mori/"]]];
BlocksKitの便利メソッド
MFMailComposeViewController#completionBlock
MFMailComposeViewController *ctl =
[[[MFMailComposeViewController alloc] init] autorelease];
ctl.mailComposeDelegate = self;
ctl.completionBlock = ^(MFMailComposeViewController *controller,
MFMailComposeResult result, NSError *err){
   if (result == MFMailComposeResultSent) {
        //成功時の処理
  }
};
[self presentModalViewController:ctl animated:YES];
BlocksKitの便利メソッド
UIControl#addEventHandler:forControlEvents:
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
button.frame = CGRectMake(40, 20, 240, 44);
[button setTitle:@"Caption" forState:UIControlStateNormal];
[button addEventHandler:^(id sender) {
    //Action
} forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:button];
BlocksKitの便利メソッド
UIBarButtonItem#initWithBarButtonSystemItem:handler:
self.navigationItem.leftBarButtonItem =
[[[UIBarButtonItem alloc]
    initWithBarButtonSystemItem:UIBarButtonSystemItemCancel
    handler:^(id sender) {
        //Cancel Action
    }] autorelease];
BlocksKitの便利メソッド
UIGestureRecognizer#initWithHandler:
UISwipeGestureRecognizer *swipe =
[[UISwipeGestureRecognizer alloc]
    initWithHandler:^(UIGestureRecognizer *sender, UIGestureRecognizerState state,
CGPoint location){
        //Swipe Action
    }];
[self.view addGestureRecognizer:swipe];
BlocksKitの便利メソッド
NSObject#performBlock:
[NSObject performBlock:^(void) {
   NSLog(@"fire");
} afterDelay:1];
BlocksKitの便利メソッド
NSTimer#scheduledTimerWithTimeInterval:block:
[NSTimer scheduledTimerWithTimeInterval:1
 block:^(NSTimeInterval time) {
    //action every 1 sec.
 }
 repeats:YES];
UITableViewのカテゴリ拡張
UITableViewはDelegate, DataSourceを利用する

カテゴリはインスタンス変数を保持できない
 A2DynamicDelegateを使って動的に保持
UITableViewの拡張
  A2DynamicUITableViewDelegateの実装
- (void)tableView:(UITableView *)tableView
    didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
	     id realDelegate = self.realDelegate;
	     if (realDelegate && [realDelegate
respondsToSelector:@selector(tableView:didSelectRowAtIndexPath:)]) {
	     	     [realDelegate tableView:tableView didSelectRowAtIndexPath:indexPath];
   }
   NSString *key = [NSString stringWithFormat:@”%@_%@_%@”,
        kHandlerDidSelectRow, indexPath.section, indexPath.row];
   BKTableViewBlock block = [self.handlers objectForKey:key];
   if (block) {
        ((BKTableViewBlock)block)(tableView, indexPath);
   }
}
UITableViewの拡張
    UITableView (BlocksKitExtends)
- (id)initWithFrame:(CGRect)frame
    style:(UITableViewStyle)style
    delegate:(id)delegate
    dataSource:(id)dataSource {
    UITableView *tableView = [self initWithFrame:frame style:style];
    tableView.delegate = self.dynamicDelegate;
    ((A2DynamicDelegate *)self.dynamicDelegate).realDelegate = delegate;

    tableView.dataSource = self.dynamicDataSource;
    ((A2DynamicDelegate *)self.dynamicDataSource).realDelegate = dataSource;

    return tableView;
}
UITableViewの拡張
  UITableView (BlocksKitExtends)
typedef void (^BKTableViewBlock)(UITableView *tableView, NSIndexPath *indexPath);

- (void)setHandler:(BKTableViewBlock)block
    forDidSelectRowAtIndexPath:(NSIndexPath *)indexPath {
   NSString *key = [NSString stringWithFormat:@”%@_%@_%@”,
        kHandlerDidSelectRow, indexPath.section, indexPath.row];
   if (block) {
	     	    [[self.dynamicDelegate handlers] setObject:block forKey:key];
   } else {
	     	    [[self.dynamicDelegate handlers] removeObjectForKey:key];
   }
   [self setHandler:block forKey:key target:self.dynamicDelegate];
}
UITableViewの拡張
    使い方
- (UITableViewCell *)tableView:(UITableView *)tableView
   cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@”Cell”];
	    if (cell == nil) {
	    	     cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1
              reuseIdentifier:@”Cell”] autorelease];
	    }
	    if (indexPath.section == 0) {
   	       cell.textLabel.text = [_rows objectAtIndex:indexPath.row];
   	       [tableView setHandler:^(UITableView *tv, NSIndexPath *ip){
   
       
     //Cell選択時の処理
    	        } forDidSelectRowAtIndexPath:indexPath];
	       }
	       return cell;
}
UIViewControllerの基底拡張
UIViewControllerのView LifesycleでBlock差込を行う
  loadView:
  viewDidLoad:
  viewWillAppear:
  viewDidAppear:
  viewWillDisappear:
  viewDidDisappear:
UIViewControllerの基底拡張
BaseViewController

 void (^_viewWillAppearBlock)(BOOL);

 - (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    if (_viewWillAppearBlock) {
        _viewWillAppearBlock(animated);
    }
 }
UIViewControllerの基底拡張
画面の遷移管理に使える
     callback block for B


       viewWillAppear:
                            B
     execute block from B


           A
     callback block for C


       viewWillAppear:
                            C
     execute block from C




利点:B,CはAを意識する必要がない(疎結合になる)
まとめ
Blockの活用により疎結合な構成が組みやすくなる

Delegateパターンを使わなくてよくなる

performedSelectorを使わなくてよくなる

循環参照に注意
ご清聴ありがとうございました
     m(_ _)m
1 of 37

More Related Content

What's hot(20)

iOSビヘイビア駆動開発iOSビヘイビア駆動開発
iOSビヘイビア駆動開発
Brian Gesiak11.7K views
jQuery超入門編jQuery超入門編
jQuery超入門編
Yasuhito Yabe1.4K views
Try JetpackTry Jetpack
Try Jetpack
Hideaki Miyake1.1K views
JavaScript/CSS 2015 AutumnJavaScript/CSS 2015 Autumn
JavaScript/CSS 2015 Autumn
Koji Ishimoto18.3K views
FxUG in Toyama - ASphalt2 container -FxUG in Toyama - ASphalt2 container -
FxUG in Toyama - ASphalt2 container -
Akio Katayama716 views
Pro aspnetmvc3framework chap19Pro aspnetmvc3framework chap19
Pro aspnetmvc3framework chap19
Hideki Hashizume671 views
はじめてのVue.jsはじめてのVue.js
はじめてのVue.js
Kei Yagi2.4K views
ゲンバのSwiftゲンバのSwift
ゲンバのSwift
Yuichi Adachi8.2K views
CoreData 非同期データ処理CoreData 非同期データ処理
CoreData 非同期データ処理
次朗 永島16.3K views
はじめてのCouch dbはじめてのCouch db
はじめてのCouch db
Eiji Kuroda3.8K views
Vue Router + VuexVue Router + Vuex
Vue Router + Vuex
Kei Yagi2.5K views
T90 きっと怖くないmvvm & mvpvmT90 きっと怖くないmvvm & mvpvm
T90 きっと怖くないmvvm & mvpvm
伸男 伊藤8.2K views
Type Safe Assets Handling in SwiftType Safe Assets Handling in Swift
Type Safe Assets Handling in Swift
Kazunobu Tasaka2.9K views
swooleを試してみたswooleを試してみた
swooleを試してみた
Yukihiro Katsumi535 views

Viewers also liked(12)

Facebook api for iOSFacebook api for iOS
Facebook api for iOS
Hidetoshi Mori7.8K views
20130216 小ネタ集20130216 小ネタ集
20130216 小ネタ集
Hidetoshi Mori3.4K views
20130216 magical record20130216 magical record
20130216 magical record
Hidetoshi Mori3.8K views
StoryboardStoryboard
Storyboard
Hidetoshi Mori4.7K views
Evernote連携Evernote連携
Evernote連携
Hidetoshi Mori4.6K views
Photo mosaic 検証Photo mosaic 検証
Photo mosaic 検証
Hidetoshi Mori430 views
最適化超入門最適化超入門
最適化超入門
Takami Sato174.6K views
Getting Started With SlideShareGetting Started With SlideShare
Getting Started With SlideShare
SlideShare4M views

Similar to Blocksの活用法

Ll xcodeLl xcode
Ll xcodeNet Kanayan
1.1K views34 slides
Swiftyを試すSwiftyを試す
Swiftyを試す幸雄 村上
303 views22 slides
2011060720110607
20110607小野 修司
511 views25 slides
Spring mvcSpring mvc
Spring mvcRyo Asai
6.4K views25 slides

Similar to Blocksの活用法(20)

Ll xcodeLl xcode
Ll xcode
Net Kanayan1.1K views
Swiftyを試すSwiftyを試す
Swiftyを試す
幸雄 村上303 views
Mvc conf session_4_onoMvc conf session_4_ono
Mvc conf session_4_ono
Hiroshi Okunushi729 views
2011060720110607
20110607
小野 修司511 views
Spring mvcSpring mvc
Spring mvc
Ryo Asai6.4K views
iOS WebView AppiOS WebView App
iOS WebView App
hagino 300014.5K views
20130924 Picomon CRH勉強会20130924 Picomon CRH勉強会
20130924 Picomon CRH勉強会
Yukihiro Kitazawa538 views
FxUG in Toyama - ASphalt2 container -FxUG in Toyama - ASphalt2 container -
FxUG in Toyama - ASphalt2 container -
Akio Katayama349 views
Wicket勉強会2Wicket勉強会2
Wicket勉強会2
Yoichiro Tanaka1.4K views
OpenGLプログラミングOpenGLプログラミング
OpenGLプログラミング
幸雄 村上442 views
Google App Engine for JavaGoogle App Engine for Java
Google App Engine for Java
Takuya Tsuchida5.5K views
LabVIEW NXG Web Module Training SlideLabVIEW NXG Web Module Training Slide
LabVIEW NXG Web Module Training Slide
Yusuke Tochigi653 views
Cakephp2.1 ViewBlock view-inheritanceCakephp2.1 ViewBlock view-inheritance
Cakephp2.1 ViewBlock view-inheritance
Kohji Tanaka2.4K views
20120422i phonedeveloperworkshoppublished20120422i phonedeveloperworkshoppublished
20120422i phonedeveloperworkshoppublished
Yoichiro Sakurai762 views
WKWebViewとUIWebViewWKWebViewとUIWebView
WKWebViewとUIWebView
Yuki Hirai48.2K views

More from Hidetoshi Mori(15)

Git超入門Git超入門
Git超入門
Hidetoshi Mori2.5K views
20130515 diary euglena_en20130515 diary euglena_en
20130515 diary euglena_en
Hidetoshi Mori1.2K views
mongodbの簡易ストレージ化mongodbの簡易ストレージ化
mongodbの簡易ストレージ化
Hidetoshi Mori828 views
汎用apiサーバの構築汎用apiサーバの構築
汎用apiサーバの構築
Hidetoshi Mori2K views
モバイルビジネスの動向モバイルビジネスの動向
モバイルビジネスの動向
Hidetoshi Mori2.6K views
モバイルビジネスの動向モバイルビジネスの動向
モバイルビジネスの動向
Hidetoshi Mori614 views
サービス開発における工程サービス開発における工程
サービス開発における工程
Hidetoshi Mori1.4K views
ゲリラ的サービスの育て方ゲリラ的サービスの育て方
ゲリラ的サービスの育て方
Hidetoshi Mori898 views
Presentation of TapkuLibraryPresentation of TapkuLibrary
Presentation of TapkuLibrary
Hidetoshi Mori1.9K views
Facebook API for iOSFacebook API for iOS
Facebook API for iOS
Hidetoshi Mori6.6K views
FacebookAPI for iOSFacebookAPI for iOS
FacebookAPI for iOS
Hidetoshi Mori705 views

Blocksの活用法

Editor's Notes

  1. \n
  2. \n
  3. \n
  4. \n
  5. \n
  6. \n
  7. \n
  8. \n
  9. \n
  10. \n
  11. \n
  12. \n
  13. \n
  14. \n
  15. \n
  16. \n
  17. \n
  18. \n
  19. \n
  20. \n
  21. \n
  22. \n
  23. \n
  24. \n
  25. \n
  26. \n
  27. \n
  28. \n
  29. \n
  30. \n
  31. \n
  32. \n
  33. \n
  34. \n
  35. \n
  36. \n
  37. \n