Grand Central Dispatchã§æ¥½ã ãã«ãã¹ã¬ãã iPhoneããã°ã©ãã³ã°
iPhoneã§ãiOS4以éãµãã¼ããããGrand Central Dispatchã使ãã¨ããã«ãã¹ã¬ããã使ã£ãããã°ã©ã ãç°¡åã«ä½ãã¾ããWWDC 2010のビデオ(#206, #211) ãè¦ã¦ä½ã¨ãªãå¤ã£ãæ°ã«ãªã£ãã®ã§ãããã¾ã ã¯ãªã¢ã§ãªãç¹ããã£ãã®ã§èªåã§ã³ã¼ããæ¸ãã¦ã¿ã¾ããã
ç§ã®ç解ã§ã¯ãGrand Central Dispatch(GCD)ã¯ã«ã¯
- ãã«ãããã»ããµãæå¹ã«ä½¿ããã並åããã°ã©ã ãç°¡åã«æ¸ãã
- æä½æ§ãé«ããã並è¡å¦çãç°¡åã«æ¸ãã
ã®2ã¤ã®ç®çãããã¨æãã¾ããããã§ã¯ 2. ã«ä»ãã¦æ¸ãã¾ãã 1.ã«ã¤ãã¦ã¯ Wikipediaの The second exampleãåèã«ãªãã¨æãã¾ãã
ä»åã®ãµã³ãã«
ããã§ã¯ãTwitterã®public timelineãåå¾ããã¤ã¶ããã¨ã¢ã¤ã³ã³ã表示ããããã°ã©ã ããã¹ã¬ãããã¾ã£ãã使ããªãã³ã¼ãã¨GCDã使ã£ãã³ã¼ããæ¯è¼ãã¦ã¿ããã¨æãã¾ãã
.
ã¹ã¬ãããã¾ã£ãã使ããªãã³ã¼ã
å¦ç㯠ç»é¢ã表示ãããæã«ãpublic timelineã®JSONãã¼ã¿ãåå¾ãTableViewã®è¡¨ç¤ºã1ã¤ã®ã»ã«è¡¨ç¤ºã®ä¸ã§ã®ã¢ã¤ã³ã³ã®åå¾ãå ¨ã¦åæå¦çãã¦ãã¾ããJSONã®ãã¼ã¹ã¯JSON Frameworkã使ã£ã¦ãã¾ãã
ãããã£ã¦timelineã表示ãããã¾ã§ã¯ã3Géä¿¡ã®å®æ©ã§ã¯5ç§ãããçã£é»ãªç»é¢ã表示ãããã¾ã¾ã§ãããã¹ã¯ãã¼ã«æã«ã¢ã¤ã³ã³ãåå¾ããã®ã§ã¹ã¯ãã¼ã«ã®åå¿ã¯ææªã§ã ^^);
(Wifiçã§ãããã«ç¹ãã£ãMacä¸ã®ã·ãã¥ã¬ã¼ã¿ã§ã¯åä½ãæ©ãã§ãããネットワークの通信速度を制限する Preference Pane "SpeedLimit" - 24/7 twenty-four seven ãåèã«ãéä¿¡é度ãè½ã¨ãã¦ã¿ãã¨å¤ãã¾ã)
- (NSData *)getData:(NSString *)url; { NSURLRequest *request = [NSURLRequest requestWithURL: [NSURL URLWithString:[url stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:30.0]; NSURLResponse *response; NSError *error; NSData *result = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error]; if (result == nil) { NSLog(@"NSURLConnection error %@", error); } return result; } - (UIImage *)getImage:(NSString *)url { return [UIImage imageWithData:[self getData:url]]; } - (void)getPublicTimeline { NSString *jsonString = [[[NSString alloc] initWithData:[self getData:TWITTER_URL_PUBLIC_TIMELINE] encoding:NSUTF8StringEncoding] autorelease]; NSArray *entries = [jsonString JSONValue]; self.tweetMessages = [[NSMutableArray alloc] init]; self.tweetIconURLs = [[NSMutableArray alloc] init]; for (NSDictionary *entry in entries) { [tweetMessages addObject:[entry objectForKey:@"text"]]; [tweetIconURLs addObject:[[entry objectForKey:@"user"] objectForKey:@"profile_image_url"]]; } } - (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; [self getPublicTimeline]; [self.tableView reloadData]; } - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { return 66.0; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return tweetMessages ? [tweetMessages count] : 0; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *CellIdentifier = @"SampleTable"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (cell == nil) { cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease]; } cell.textLabel.text = [tweetMessages objectAtIndex:[indexPath row]]; cell.textLabel.adjustsFontSizeToFitWidth = YES; cell.textLabel.numberOfLines = 3; cell.textLabel.font = [UIFont boldSystemFontOfSize:12]; cell.imageView.image = [self getImage:[tweetIconURLs objectAtIndex:[indexPath row]]]; return cell; }
Grand Central Dispatchã使ã£ãã³ã¼ã
ã¾ããGCDã®ãã¥ã¼ç¨ã®å¤æ°ãæºåãã¾ãã
GCDã§ã¯ãã¥ã¼ã«ç»é²ãããå¦ç(ãããã¯)ã¯é çªã«å®è¡ããã¾ããããããã¥ã¼ãè¤æ°ä½æããå ´åããã¥ã¼ã¯å¥ã¹ã¬ããã§å®è¡ãããã®ã§ä¸¦è¡å¦çãå®ç¾ã§ãã¾ãããããã£ã¦ãã¢ããªã§ä¸¦è¡ã«å¦çãããé¨åç¨ã®ãã¥ã¼ãç¨æãã¾ãã
ä»åã¯ãã¡ã¤ã³(GUI)ç¨ãtimelineåå¾ç¨ãã¢ã¤ã³ã³ç»ååå¾ç¨ã®ï¼ã¤ã®ãã¥ã¼ãç¨æãã¾ããã
dispatch_queue_t main_queue; dispatch_queue_t timeline_queue; dispatch_queue_t image_queue;
ç»é¢ã表示ãããã¨ããã§ãã¡ã¤ã³ã¹ã¬ãã以å¤ã®ã¹ã¬ãããä½æãã¦ãã¾ããã¡ã¤ã³(GUI)ç¨ãã¥ã¼ã¯ dispatch_get_main_queue() ã§åå¾ãã¾ãã
ãã¦ãtimelineåå¾ã§ãã timeline_queue ä¸ã§
- getPublicTimelineã§timelineåå¾
- tableViewã®å表示å¦çãmain_queueã«ç»é²
ã®é ã«å®è¡ãããããã«ãtimeline_queueã«ç»é²ãã¾ãããã㧠timelineåå¾ãå¥ã¹ã¬ããã§å®è¡ããããã®å¾ã¡ã¤ã³ã¹ã¬ããã§å表示ãå®è¡ããã¾ããä¸ã® ãã¹ã¬ãããã¾ã£ãã使ããªãã³ã¼ãã ã«ã»ãã®å°ãã®GCDã³ã¼ãã追å ããã ãã®äºãå¤ãã¨æãã¾ãã
ã¾ãããã®å¦çã¯ãã¥ã¼ã«ãããã¯ãç»é²ããã ããªã®ã§ç´ãã«çµäºãã¾ãã®ã§ãç´ãã«ç©ºã®tableViewã表示ããã¾ãã
- (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; main_queue = dispatch_get_main_queue(); timeline_queue = dispatch_queue_create("com.ey-office.gcd-sample.timeline", NULL); image_queue = dispatch_queue_create("com.ey-office.gcd-sample.image", NULL); dispatch_async(timeline_queue, ^{ [self getPublicTimeline]; dispatch_async(main_queue, ^{ [self.tableView reloadData]; }); }); }
次㫠tableViewã®è¡¨ç¤ºã§ãããæåã«è¡¨ç¤ºãããæã« tableView ã« loading... ã¨è¡¨ç¤ºãããããã«ãã¦ãã¾ãã
ãã¦ãtimelineåå¾å¾ã®å表示ã§ã¯ã¢ã¤ã³ã³ç»åã®åå¾ã»è¡¨ç¤ºãGCDã§å®è¡ãã¦ãã¾ããããã§ã¯ image_queueãã¥ã¼ä¸ã§
- getImageã§ã¢ã¤ã³ã³ç»åã®åå¾
- tableViewã®Cellã«ç»åãè¨å®ããå¦çã main_queueã«ç»é²
ãè¡ããã¢ã¤ã³ã³ç»åã®åå¾ã»è¡¨ç¤ºãå¥ã¹ã¬ããã§è¡ãã¾ãããã¯ãããã§ããã¥ã¼ã«ãããã¯ãç»é²ããã ããªã®ã§ç´ãã«tableViewã«ã¤ã¶ããã¨blankã¢ã¤ã³ã³ã表示ããã¾ãã
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return tweetMessages ? [tweetMessages count] : 1; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *CellIdentifier = @"SampleTable"; if (!tweetMessages) { UITableViewCell *cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease]; cell.textLabel.text = @"loading..."; cell.textLabel.textColor = [UIColor grayColor]; return cell; } UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (cell == nil) { cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease]; } cell.textLabel.text = [tweetMessages objectAtIndex:[indexPath row]]; cell.textLabel.adjustsFontSizeToFitWidth = YES; cell.textLabel.numberOfLines = 3; cell.textLabel.font = [UIFont boldSystemFontOfSize:12]; cell.textLabel.textColor = [UIColor darkGrayColor]; cell.imageView.image = [UIImage imageNamed:@"blank.png"]; dispatch_async(image_queue, ^{ UIImage *icon = [self getImage:[tweetIconURLs objectAtIndex:[indexPath row]]]; dispatch_async(main_queue, ^{ UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath]; cell.imageView.image = icon; }); }); return cell; }
æå¾ã«ç»é¢çµäºæã«ãã¥ã¼ãåé¤ãã¦ãã¾ãã
- (void)viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated]; dispatch_release(timeline_queue); dispatch_release(image_queue); }
ã¾ã¨ã
GCDã使ã£ãã³ã¼ãã§ã¯èµ·åå¾ç´ãã« ãã¼ãã«ã« Loading...ã表示ãããå°ãå¾ ã¤ã¨ã¤ã¶ããã表示ãããã¢ã¤ã³ã³ãé çªã«è¡¨ç¤ºããã¦ããã¾ãããããããã¼ãã«ããã¤ã§ãã¹ã¯ãã¼ã«åºæ¥ã¾ãã
é常ãã¹ã¬ããããã°ã©ã ã§ã¯åã¹ã¬ããã®åæããå
±æãªã½ã¼ã¹(å¤æ°)ã®æä»å¶å¾¡ã¯ããã¸ãã§ããã©ã®ãã大å¤ãªã®ã㯠Java並è¡å¦çããã°ã©ãã³ã° âãã®ãåºç¤ãã¨ãææ°APIãã究ããâ ãçºããã¨è§£ãã¾ã ^^;
iOSã§ã¯NSOperationã使ãããªã楽ã«æ¸ããããã«ãªãã¾ãããã¹ã¬ããã使ããªãã³ã¼ãããã®æ¸ãæãéã¯ããªãããã¾ãã
ããããGCDã使ãã¨å©ç¨è
ã«ã¹ãã¬ã¹ãä¸ããªãåå¿ã®è¯ãã¢ããªããç°¡åã«å®å
¨ã«ä½ãäºãã§ãã¾ãï¼ iOS3ã«å¯¾å¿ããªãã¦ãè¯ãã¢ããªã§ã¯ãã©ãã©ãGCDã使ãã¹ãã ã¨æãã¾ãã
GCDã®è©³ç´°ã¯ WWDC 2010のビデオ ã®#206, #211ã大å¤åèã«ãªãã¾ãã
ä»åã®ã³ã¼ãã¯GitHubã«ã¢ãããã¦ããã¾ããno_thread ãã©ã³ãã ãã¹ã¬ãããã¾ã£ãã使ããªãã³ã¼ãã㧠gcd ãã©ã³ãã ãGrand Central Dispatchã使ã£ãã³ã¼ããã§ãã