2012-03-08 21 views
2

私のテーブルには、信じられないほど遅いスクロールしている、と私はそれが私のcellForRowAtIndexPath内のコアデータの方法によって引き起こさだと思います。以下は私のcellForRowAtIndexPathメソッドです:のUITableView cellForRowAtIndexPath遅いスクロールに原因

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 

static NSString *CellIdentifier = @"Cell"; 

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 
if (cell == nil) { 
    cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; 
} 

NSManagedObject *info = [buildingArray objectAtIndex: [indexPath row]]; 
// all rooms have been scanned for building 
if([self allRoomsScanned: [[info valueForKey:@"buildingid"] intValue]]) { 
    cell.accessoryType = UITableViewCellAccessoryCheckmark; 
    [cell.textLabel setTextColor: [UIColor lightGrayColor]]; 
} 
else { 
    cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; 
    [cell.textLabel setTextColor: [UIColor blackColor]]; 
} 
[cell.textLabel setFont:[UIFont fontWithName:@"Helvetica-Bold" size:16.0]]; 
[cell.textLabel setText:[info valueForKey:@"buildingname"]]; 

return cell; 
} 

そしてここallRoomsScanned方法とallDevicesScanned方法である:

- (BOOL) allRoomsScanned: (int) buildingID { 
NSMutableArray *scannedRoomArray = [[NSMutableArray alloc] init]; 
// Get all user_device 
NSManagedObjectContext *context = [self managedObjectContext]; 
NSError *error; 
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; 
NSEntityDescription *entity = [NSEntityDescription 
           entityForName:@"user_device" inManagedObjectContext:context]; 
[fetchRequest setEntity:entity]; 
NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&error]; 
NSNumber *deviceid = [NSNumber numberWithInt: 0]; 
NSNumber *roomid = [NSNumber numberWithInt: 0]; 
//int lastRoomID = 0; 

for (NSManagedObject *info in fetchedObjects) { 
    // Get all device 
    deviceid = [info valueForKey:@"deviceid"]; 
    fetchRequest = [[NSFetchRequest alloc] init]; 
    entity = [NSEntityDescription 
       entityForName:@"device" inManagedObjectContext:context]; 
    [fetchRequest setEntity:entity]; 

    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(deviceid = %d)", [deviceid intValue]]; 
    [fetchRequest setPredicate:predicate]; 
    NSArray *fetchedDevices = [context executeFetchRequest:fetchRequest error:&error]; 
    for (NSManagedObject *infod in fetchedDevices) { 
     // Get all room 
     roomid = [infod valueForKey:@"roomid"]; 
     fetchRequest = [[NSFetchRequest alloc] init]; 
     entity = [NSEntityDescription 
        entityForName:@"room" inManagedObjectContext:context]; 
     [fetchRequest setEntity:entity]; 

     NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(roomid = %d) AND (buildingid = %d)", [roomid intValue], buildingID]; 
     [fetchRequest setPredicate:predicate]; 
     NSMutableArray *fetchedRoom = [[context executeFetchRequest:fetchRequest error:&error] mutableCopy]; 

     // add room to array if room belongs to selected building and room not already added 
     if([fetchedRoom count] > 0) { //&& lastRoomID != [roomid intValue]) { 
      for (NSManagedObject *info in fetchedRoom) { 
       NSLog(@"room id: %@", [info valueForKey:@"roomid"]); 
       // add room ids to array if not already there 
       if (![scannedRoomArray containsObject:[info valueForKey:@"roomid"]] && [self allDevicesScanned:[[info valueForKey:@"roomid"] intValue]]) 
        [scannedRoomArray addObject: [info valueForKey:@"roomid"]]; 
      } 
      //lastRoomID = [roomid intValue]; 
     } 
    } 
} 

fetchRequest = [[NSFetchRequest alloc] init]; 
entity = [NSEntityDescription 
      entityForName:@"room" inManagedObjectContext:context]; 
[fetchRequest setEntity:entity]; 

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(buildingid = %d)", buildingID]; 
[fetchRequest setPredicate:predicate]; 
NSArray *fetchedRoomTotal = [context executeFetchRequest:fetchRequest error:&error]; 
//NSLog(@"Total Rooms for Building: %d", [fetchedRoomTotal count]); 
//NSLog(@"Scanned Rooms for Building: %d", [scannedRoomArray count]); 
//NSLog(@"Scanned rooms: %@", scannedRoomArray); 
if([fetchedRoomTotal count] == [scannedRoomArray count] && [fetchedRoomTotal count] > 0) { 
    return YES; 
} 
else { 
    return NO; 
} 
} 

- (BOOL) allDevicesScanned: (int) roomID { 
NSMutableArray *scannedDeviceArray = [[NSMutableArray alloc] init]; 
// Get all user_device 
NSManagedObjectContext *context = [self managedObjectContext]; 
NSError *error; 
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; 
NSEntityDescription *entity = [NSEntityDescription 
           entityForName:@"user_device" inManagedObjectContext:context]; 
[fetchRequest setEntity:entity]; 
NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&error]; 
NSNumber *deviceid = [NSNumber numberWithInt: 0]; 
//NSNumber *roomid = [NSNumber numberWithInt: 0]; 

for (NSManagedObject *info in fetchedObjects) { 
    // Get all device 
    deviceid = [info valueForKey:@"deviceid"]; 
    fetchRequest = [[NSFetchRequest alloc] init]; 
    entity = [NSEntityDescription 
       entityForName:@"device" inManagedObjectContext:context]; 
    [fetchRequest setEntity:entity]; 

    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(deviceid = %d) AND (roomid = %d)", [deviceid intValue], roomID]; 
    [fetchRequest setPredicate:predicate]; 
    NSArray *fetchedDevices = [context executeFetchRequest:fetchRequest error:&error]; 
    for (NSManagedObject *infod in fetchedDevices) { 

     // add device to array 
     if([fetchedDevices count] > 0) { 
      NSLog(@"room id: %d", roomID); 
      // add device ids to array if not already there 
      if (![scannedDeviceArray containsObject:deviceid]) 
       [scannedDeviceArray addObject: deviceid]; 
     } 
    } 
} 

fetchRequest = [[NSFetchRequest alloc] init]; 
entity = [NSEntityDescription 
      entityForName:@"device" inManagedObjectContext:context]; 
[fetchRequest setEntity:entity]; 

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(roomid = %d)", roomID]; 
[fetchRequest setPredicate:predicate]; 
NSArray *fetchedDeviceTotal = [context executeFetchRequest:fetchRequest error:&error]; 
//NSLog(@"Total Devices for Room: %d", [fetchedDeviceTotal count]); 
//NSLog(@"Scanned Devices for Room: %d", [scannedDeviceArray count]); 
//NSLog(@"Scanned Devices: %@", scannedDeviceArray); 
if([fetchedDeviceTotal count] == [scannedDeviceArray count] && [fetchedDeviceTotal count] > 0) { 
    return YES; 
} 
else { 
    return NO; 
} 
} 

スクロール時の待ち時間を取り除く方法上の任意のアイデア?私は、コアデータ呼び出しまたはcellForRowAtIndexPathのメソッドを呼び出す方法で、非効率的に何かをしている可能性があると仮定しています。

ありがとうございました。大変感謝しています。

答えて

2

あなたは本当にテーブルビューをスクロールしながら、メインスレッド上でそのような要求と処理を取得させるべきではありません。 rokjarcが言ったように、あなたは(非常に重い)allRoomsScannedメソッドの結果を間違いなく保存する必要があります。新しいスタイル、つまりアクティビティインジケータを追加して、その入力の結果がまだない場合にセルを取得することをおすすめします。ロードが完了すると、すぐに表ビューのセルが更新されます。

注意:デフォルトのNSManagedObjectContextをallRoomsScannedallDevicesScannedに使用することはできません。 バックグラウンドスレッドで新しいコンテキストを初期化する必要があります。ブロックの先頭で新しいコンテキストを初期化し、メソッドのパラメータとして渡すか、メソッド内で新しいコンテキストを作成します。

NSManagedObject *info = [buildingArray objectAtIndex: [indexPath row]]; 

NSNumber *cachedResult = [self.scanResults objectForKey:info.objectID]; 
if (cachedResult == nil) { 
    // style loading state 

    int scanInfo = [[info valueForKey:@"buildingid"] intValue]; 
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 
     BOOL result = [self allRoomsScanned: scanInfo]; 
     [self.scanResults setObject:[NSNumber numberWithBool:result] forKey:info.objectID]; 
     [self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationAutomatic] 
    }); 

} else if (cachedResult.boolValue == YES) { 
    cell.accessoryType = UITableViewCellAccessoryCheckmark; 
    [cell.textLabel setTextColor: [UIColor lightGrayColor]]; 
} else if (cachedResult.boolValue == NO) { 
    cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; 
    [cell.textLabel setTextColor: [UIColor blackColor]]; 
} 

[cell.textLabel setFont:[UIFont fontWithName:@"Helvetica-Bold" size:16.0]]; 
[cell.textLabel setText:[info valueForKey:@"buildingname"]]; 

return cell; 
+0

こんにちはティム、答えてくれてありがとう。私はコードを試みたが、スクロールからテーブルをロックするようだ。何か案は? – codeman

+0

scanResultsを正しく初期化していて、バックグラウンドタスクに新しいNSManagedObjectContextを使用している限り、問題はないはずです。私はそれを自分でテストしなかった。 – tim

+0

scanResultsは単なるNSMutableDictionaryですが、正しいですか?私はそのように初期化しています:scanResults = [NSMutableDictionary dictionary]; – codeman

関連する問題