Upgrade to Pro — share decks privately, control downloads, hide ads and more …

ARC & Blocks 時代の ベストプラクティスを考える

ARC & Blocks 時代の ベストプラクティスを考える

ARC & Blocks を使ったときの循環参照を避けるための現実的なサンプル。

Kishikawa Katsumi

May 27, 2012
Tweet

More Decks by Kishikawa Katsumi

Other Decks in Technology

Transcript

  1. Apple ެࣜυΩϡϝϯτ Transitioning to ARC Release Notes http://developer.apple.com/library/ios/#releasenotes/ObjectiveC/RN-TransitioningToARC/Introduction/Introduction.html ϒϩοΫϓϩάϥϛϯάτϐοΫ https://developer.apple.com/jp/devcenter/ios/library/documentation/Blocks.pdf%2FBlocks.pdf&ei=5ua_T_PnAa6CmQWB-dyiCg&usg=AFQjCNEB7EtpLn4Qt4N22nDrqs33gy1orA

    Clang ެࣜυΩϡϝϯτ Automatic Reference Counting http://clang.llvm.org/docs/AutomaticReferenceCounting.html ninjinkun ͷεϥΠυ iOSͱAutomatic Reference Countingʹ͍ͭͯൃද͠·ͨ͠ http://ninjinkun.hatenablog.com/entry/2011/11/19/171246
  2. - (void)grabURLInBackground { NSURL *url = [NSURL URLWithString:@"http://allseeing-i.com"]; ASIHTTPRequest *request

    = [ASIHTTPRequest requestWithURL:url]; [request setCompletionBlock:^ { NSString *responseString = [request responseString]; // ŋŋŋ }]; [request setFailedBlock:^ { NSError *error = [request error]; // ŋŋŋ }]; [request startAsynchronous]; } ARC Non ARC request ΦϒδΣΫτ͕॥؀ࢀর
  3. - (void)grabURLInBackground { NSURL *url = [NSURL URLWithString:@"http://allseeing-i.com"]; __block ASIHTTPRequest

    *request = [ASIHTTPRequest requestWithURL:url]; [request setCompletionBlock:^ { NSString *responseString = [request responseString]; // ŋŋŋ }]; [request setFailedBlock:^ { NSError *error = [request error]; // ŋŋŋ }]; [request startAsynchronous]; } http://allseeing-i.com/ASIHTTPRequest/How-to-use ARC Non ARC ARC͕ແޮͷ৔߹͸ __block ͕ࢦఆ͞Εͨ ΦϒδΣΫτ͸ retain ͞Εͳ͍
  4. - (void)grabURLInBackground { NSURL *url = [NSURL URLWithString:@"http://allseeing-i.com"]; __block ASIHTTPRequest

    *request = [ASIHTTPRequest requestWithURL:url]; [request setCompletionBlock:^ { // Use when fetching text data NSString *responseString = [request responseString]; // ŋŋŋ request = nil; }]; [request setFailedBlock:^ { NSError *error = [request error]; // ŋŋŋ request = nil; }]; [request startAsynchronous]; } ARC Non ARC
  5. - (void)grabURLInBackground { NSURL *url = [NSURL URLWithString:@"http://allseeing-i.com"]; __weak ASIHTTPRequest

    *request = [ASIHTTPRequest requestWithURL:url]; [request setCompletionBlock:^ { // Use when fetching text data NSString *responseString = [request responseString]; // ŋŋŋ }]; [request setFailedBlock:^ { NSError *error = [request error]; // ŋŋŋ }]; [request startAsynchronous]; } ARC Non ARC
  6. - (void)grabURLInBackground { NSURL *url = [NSURL URLWithString:@"http://allseeing-i.com"]; __unsafe_unretained ASIHTTPRequest

    *request = [ASIHTTPRequest requestWithURL:url]; [request setCompletionBlock:^ { // Use when fetching text data NSString *responseString = [request responseString]; // ŋŋŋ }]; [request setFailedBlock:^ { NSError *error = [request error]; // ŋŋŋ }]; [request startAsynchronous]; } ARC Non ARC
  7. ATService *service = [[ATService alloc] init]; service.completionBlock = ^(NSString *results,

    NSError *error) { if (!error) { self.tweets = results; [tableView reloadData]; } }; [service grabURLInBackground]; ݁ՌΛϒϩοΫͷҾ਺Ͱฦ͢ ARC Non ARC
  8. @implementation ATService @synthesize completionBlock; - (void)grabURLInBackground { NSURL *url =

    [NSURL URLWithString:@"http://allseeing-i.com"]; __weak ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url]; [request setCompletionBlock:^{ NSArray *results = [request.responseData objectFromJSONData]; if (completionBlock) { completionBlock(responseString, nil); } }]; [request setFailedBlock:^{ NSError *error = [request error]; if (completionBlock) { completionBlock(nil, error); } }]; [request startAsynchronous]; } ʢࢀߟʣϥούʔଆͷ࣮૷
  9. - (void)grabURLInBackground { NSURL *url = [NSURL URLWithString:@"http://allseeing-i.com"]; __weak ASIHTTPRequest

    *request = [ASIHTTPRequest requestWithURL:url]; [request setCompletionBlock:^ { // Use when fetching text data NSString *responseString = [request responseString]; // ŋŋŋ }]; [request setFailedBlock:^ { NSError *error = [request error]; // ŋŋŋ }]; [request startAsynchronous]; } ARC ϒϩοΫΛίϐʔ͍ͯ͠Δ Non ARC
  10. ATService *service = [[ATService alloc] init]; service.completionBlock = ^(NSString *results,

    NSError *error) { if (!error) { self.tweets = results; [tableView reloadData]; } }; [service grabURLInBackground]; ϒϩοΫΛίϐʔ͍ͯ͠Δ ARC Non ARC
  11. ATService *service = [[ATService alloc] init]; [service grabURLWithCompletionBlock:^(NSArray *results, NSError

    *error) { self.tweets = results; [self.tableView reloadData]; [service log]; }]; ϒϩοΫΛίϐʔ͠ͳ͍ ARC Non ARC
  12. - (void)grabURLInBackgroundWithCompletionBlock:(ATServiceResultsBlock)block { NSURL *url = [NSURL URLWithString:@"http://allseeing-i.com"]; __weak ASIHTTPRequest

    *request = [ASIHTTPRequest requestWithURL:url]; [request setCompletionBlock:^{ NSString *responseString = [request responseString]; if (block) { block(responseString, nil); } }]; [request setFailedBlock:^{ NSError *error = [request error]; if (block) { block(nil, error); } }]; [request startAsynchronous]; } ʢࢀߟʣϥούʔଆͷ࣮૷
  13. [service grabURLInBackgroundWithCompletionBlock:^(NSArray *results, NSError *error) { self.tweets = results; [self.tableView

    reloadData]; [service log]; }]; ARC Non ARC @interface ATDetailViewController () { ATService *service; } @end ϒϩοΫͷݺͼग़͠ݩΛอ͍࣋ͯͯ͠΋ϒϩοΫ͕ ίϐʔ͞Εͳ͍ͳΒΩϟϓνϟ͞Εͨࣗಈม਺͸ ϒϩοΫͷείʔϓΛൈ͚ͨͱ͖ʹղ์͞ΕΔ
  14. service.completionBlock = ^(NSArray *results, NSError *error) { self.tweets = results;

    [self.tableView reloadData]; [service log]; }; [service grabURLInBackground]; ARC Non ARC @interface ATDetailViewController () { ATService *service; } @end ϒϩοΫͷݺͼग़͠ݩΛอ͍࣋ͯͯ͠ɺϒϩοΫ͕ ίϐʔ͞ΕΔ৔߹͸॥؀ࢀরͱͳΔ
  15. __weak ATDetailViewController *me = self; service.completionBlock = ^(NSArray *results, NSError

    *error) { me.tweets = results; [me.tableView reloadData]; [me.service log]; }; [service grabURLInBackground]; ARC Non ARC @interface ATDetailViewController () { ATService *service; } @end ॥؀ࢀরΛආ͚ΔͨΊʹ self ΛϩʔΧϧม਺ʹ୅ೖͯ͠ ϩʔΧϧม਺Λ௨ͯ͠ΞΫηε͢Δ
  16. UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect]; [button setTitle:@"Show ActionSheet" forState:UIControlStateNormal]; [button

    addEventHandler:^(id sender) { UIActionSheet *actionSheet = [UIActionSheet actionSheetWithTitle:@"Title"]; [actionSheet setCancelButtonIndex:[actionSheet addButtonWithTitle:@"Close"]]; [actionSheet showInView:self.view]; } forControlEvents:UIControlEventTouchUpInside]; [self.view addSubview:button]; ARC Non ARC BlocksKit ͷ UIKit ֦ுͳͲ ίʔϧόοΫͰUIΛߋ৽͢Δ৔߹ʹ ॥؀ࢀরΛ࡞Γ͕ͪ
  17. ATDetailViewController __weak *me = self; UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];

    [button setTitle:@"Show ActionSheet" forState:UIControlStateNormal]; [button addEventHandler:^(id sender) { UIActionSheet *actionSheet = [UIActionSheet actionSheetWithTitle:@"Title"]; [actionSheet setCancelButtonIndex:[actionSheet addButtonWithTitle:@"Close"]]; [actionSheet showInView:self.view]; } forControlEvents:UIControlEventTouchUpInside]; [self.view addSubview:button]; ARC Non ARC self Λ͍ͬͨΜ weak ͳϩʔΧϧม਺ʹ୅ೖ͢Δɻ ӈล΍Ҿ਺ʹग़ݱ͢Δ self ͸ݟམͱ͠΍͍͢
  18. - (void)settingsButtonClicked:(id)sender { __unsafe_unretained TTTickerWindowController *me = self; settingsViewController =

    [[TTSettingsWindowController alloc] init]; settingsViewController.settings = settings; [settingsViewController sheetModalForWindow:self.window completionHandler:^(TTTickerSettings *result) { me.settings = result; me.tickerViewController.settings = result; if (me.settings.floatingWindow) { [me.window setLevel:CGShieldingWindowLevel() + 1]; } else { [me.window setLevel:NSNormalWindowLevel]; } }]; } ARC Non ARC Mac ͷ৔߹ɺLionҎ্Ͱ΋ __weak ࢦఆͷͰ͖ͳ͍ Ϋϥε͕͚ͬ͜͏͋Δ (__unsafe_unretained Λ࢖͏)
  19. [EPATNDAPIClient eventsWithKeyword:keyword completionBlock:^(NSArray *results, NSError *error) { if (!error) {

    NSArray *events = [self saveEvents:results]; [[EPCoreDataManager sharedManager] saveContext]; } }]; Ϋϥεϝιουʹ͢Δͱ ࢖͏΄͏͸͍Ζ͍Ζߟ͑ͳͯ͘ϥΫ ARC Non ARC