2013-07-31 46 views
0

我有一个NSScrollView包含一个NSTableView,它有3列,其中1个通过TableCellView有一个自定义视图。非常生涩的滚动NSTableView

要通过后台进程加载图像到这个单元格,我已经使用下面的代码子类化了单元格。然而,滚动是真的生涩,我想知道是否有任何方法来优化,图像不是很大,48x48,并显示在51x51。

我怀疑为每一行使用提取请求可能不是非常有效,我需要找到一种方法来设置一个NSArray,每次视图改变是当前的,并用它来代替。但是我想先让这个尽可能高效。

- (NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row { 

// Get a new ViewCell 
NSTableCellView *cellView = [tableView makeViewWithIdentifier:tableColumn.identifier owner:self]; 

//Identify the correct column 
if([tableColumn.identifier isEqualToString:@"userLogo"]) 
{ 

    NSFetchRequest *request = [[NSFetchRequest alloc] init]; 


    //Set predicate and filter for New tweets page 
    if ([self.currentTwitterView isEqualToString:@"new"]) { 
     NSPredicate *testForTrue = [NSPredicate predicateWithFormat:@"(approved == NO) AND (tweetDeleted == NO) AND (scheduledTweet == NO)"]; 
     NSSortDescriptor *sortDescriptor1 = [[NSSortDescriptor alloc] initWithKey:@"postDate" ascending:NO]; 
     NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor1, nil]; 
     [request setPredicate:testForTrue]; 
     [request setSortDescriptors:sortDescriptors]; 

    //Set filter and predicate for the Approved tweets page 
    } else if ([self.currentTwitterView isEqualToString:@"approved"]){ 
     NSPredicate *testForTrue = [NSPredicate predicateWithFormat:@"(approved == YES) AND (tweetDeleted == NO) AND (scheduledTweet == NO)"]; 
     NSSortDescriptor *sortDescriptor1 = [[NSSortDescriptor alloc] initWithKey:@"approvedDate" ascending:NO]; 
     NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor1, nil]; 
     [request setPredicate:testForTrue]; 
     [request setSortDescriptors:sortDescriptors]; 

    //Set filter and preicate for the Deleted tweets page 
    } else if ([self.currentTwitterView isEqualToString:@"deleted"]){ 
     NSPredicate *testForTrue = [NSPredicate predicateWithFormat:@"tweetDeleted == YES"]; 
     NSSortDescriptor *sortDescriptor1 = [[NSSortDescriptor alloc] initWithKey:@"deletedDate" ascending:NO]; 
     NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor1, nil]; 
     [request setPredicate:testForTrue]; 
     [request setSortDescriptors:sortDescriptors]; 

    //Set filter and preicate for the Deleted tweets page 
    } else if ([self.currentTwitterView isEqualToString:@"scheduled"]){ 
    NSPredicate *testForTrue = [NSPredicate predicateWithFormat:@"scheduledTweet == YES"]; 
    NSSortDescriptor *sortDescriptor1 = [[NSSortDescriptor alloc] initWithKey:@"scheduledDate" ascending:NO]; 
    NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor1, nil]; 
    [request setPredicate:testForTrue]; 
    [request setSortDescriptors:sortDescriptors]; 
    } 


    //Setup the Request 
    [request setEntity:[NSEntityDescription entityForName:@"Tweet" inManagedObjectContext:_managedObjectContext]]; 

    //Assign the predicate to the fetch request 
    NSError *error = nil; 

    //Create an array from the returned objects 
    NSArray *fetchedObjects = [_managedObjectContext executeFetchRequest:request error:&error]; 

    Tweet *selectedTweet = [fetchedObjects objectAtIndex:row]; 

    cellView.imageView.image = nil; 
    dispatch_async(dispatch_queue_create("getAsynchronIconsGDQueue", NULL), 
        ^{ 
         NSURL *url = [NSURL URLWithString:selectedTweet.avatarUrl]; 
         NSImage *image = [[NSImage alloc] initWithContentsOfURL:url]; 
         cellView.imageView.image = image; 
        }); 
    [cellView setWantsLayer:YES]; 
    return cellView; 
    } 

    [cellView setWantsLayer:YES]; 
    return cellView; 
} 

感谢

加雷思

编辑1

好的尝试实施AFImageRequest和性能是最糟糕的,也是我似乎得到得到相同图像的多个拷贝/各行中错误的图像。

这是我使用的代码。

@synthesize profileImage = _profileImage; 

+ (NSOperationQueue *)sharedProfileImageRequestOperationQueue { 
static NSOperationQueue *_sharedProfileImageRequestOperationQueue = nil; 
static dispatch_once_t onceToken; 
dispatch_once(&onceToken, ^{ 
    _sharedProfileImageRequestOperationQueue = [[NSOperationQueue alloc] init]; 
    [_sharedProfileImageRequestOperationQueue setMaxConcurrentOperationCount:8]; 
}); 

return _sharedProfileImageRequestOperationQueue; 
} 

//Load the image into the table 

- (NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row { 

// Get a new ViewCell 
NSTableCellView *cellView = [tableView makeViewWithIdentifier:tableColumn.identifier owner:self]; 

//Identify the correct column 
if([tableColumn.identifier isEqualToString:@"userLogo"]) 
{ 

    NSFetchRequest *request = [[NSFetchRequest alloc] init]; 


    //Set predicate and filter for New tweets page 
    if ([self.currentTwitterView isEqualToString:@"new"]) { 
     NSPredicate *testForTrue = [NSPredicate predicateWithFormat:@"(approved == NO) AND (tweetDeleted == NO) AND (scheduledTweet == NO)"]; 
     NSSortDescriptor *sortDescriptor1 = [[NSSortDescriptor alloc] initWithKey:@"postDate" ascending:NO]; 
     NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor1, nil]; 
     [request setPredicate:testForTrue]; 
     [request setSortDescriptors:sortDescriptors]; 

    //Set filter and predicate for the Approved tweets page 
    } else if ([self.currentTwitterView isEqualToString:@"approved"]){ 
     NSPredicate *testForTrue = [NSPredicate predicateWithFormat:@"(approved == YES) AND (tweetDeleted == NO) AND (scheduledTweet == NO)"]; 
     NSSortDescriptor *sortDescriptor1 = [[NSSortDescriptor alloc] initWithKey:@"approvedDate" ascending:NO]; 
     NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor1, nil]; 
     [request setPredicate:testForTrue]; 
     [request setSortDescriptors:sortDescriptors]; 

    //Set filter and preicate for the Deleted tweets page 
    } else if ([self.currentTwitterView isEqualToString:@"deleted"]){ 
     NSPredicate *testForTrue = [NSPredicate predicateWithFormat:@"tweetDeleted == YES"]; 
     NSSortDescriptor *sortDescriptor1 = [[NSSortDescriptor alloc] initWithKey:@"deletedDate" ascending:NO]; 
     NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor1, nil]; 
     [request setPredicate:testForTrue]; 
     [request setSortDescriptors:sortDescriptors]; 

    //Set filter and preicate for the Deleted tweets page 
    } else if ([self.currentTwitterView isEqualToString:@"scheduled"]){ 
    NSPredicate *testForTrue = [NSPredicate predicateWithFormat:@"scheduledTweet == YES"]; 
    NSSortDescriptor *sortDescriptor1 = [[NSSortDescriptor alloc] initWithKey:@"scheduledDate" ascending:NO]; 
    NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor1, nil]; 
    [request setPredicate:testForTrue]; 
    [request setSortDescriptors:sortDescriptors]; 
    } 


    //Setup the Request 
    [request setEntity:[NSEntityDescription entityForName:@"Tweet" inManagedObjectContext:_managedObjectContext]]; 

    //Assign the predicate to the fetch request 
    NSError *error = nil; 

    //Create an array from the returned objects 
    NSArray *fetchedObjects = [_managedObjectContext executeFetchRequest:request error:&error]; 

    Tweet *selectedTweet = [fetchedObjects objectAtIndex:row]; 

    NSURL *url = [NSURL URLWithString:selectedTweet.avatarUrl]; 

    /*cellView.imageView.image = nil; 
    dispatch_async(dispatch_queue_create("getAsynchronIconsGDQueue", NULL), 
        ^{ 
         NSURL *url = [NSURL URLWithString:selectedTweet.avatarUrl]; 
         NSImage *image = [[NSImage alloc] initWithContentsOfURL:url]; 
         cellView.imageView.image = image; 
        }); 

    */ 

    _avatarImageRequestOperation = [AFImageRequestOperation imageRequestOperationWithRequest:[NSURLRequest requestWithURL:url] success:^(NSImage *image) { 
    cellView.imageView.image = self.profileImage; 

    _avatarImageRequestOperation = nil; 

    [[NSNotificationCenter defaultCenter] postNotificationName:kUserProfileImageDidLoadNotification object:self userInfo:nil]; 
    }]; 

    [_avatarImageRequestOperation setCacheResponseBlock:^NSCachedURLResponse *(NSURLConnection *connection, NSCachedURLResponse *cachedResponse) { 
    return [[NSCachedURLResponse alloc] initWithResponse:cachedResponse.response data:cachedResponse.data userInfo:cachedResponse.userInfo storagePolicy:NSURLCacheStorageAllowed]; 
    }]; 

    [[[self class] sharedProfileImageRequestOperationQueue] addOperation:_avatarImageRequestOperation]; 

    //cellView.imageView.image = self.profileImage; 

    //[cellView setWantsLayer:YES]; 
    return cellView; 

} 
+0

我没有在这个看上去很仔细地(今冲),但想暗示什么。在这种情况下,我倾向于使用后台线程来加载前几个(例如10个左右)图像并将它们添加到表格视图单元格中。然后我使用NSTimer每秒钟加载几次。这样可以使起搏更多地展开。加载图像后,我将它们缓存起来,以便将来可以更快地使用它们。你可能想考虑做类似的事情。如果有很多单元格,我也会最大限度地发挥它的功能。 – Josiah

回答

0

好了,经过一番详细的故障排除我完全删除的图像和表格还是狗缓慢。所以,我现在写了一个新的函数,它维护当前选定对象的数组,以保存表格绘制函数为每一行调用它。这已经完全解决了这个问题,现在一切都变得流畅而可爱。

所以看起来一个提取请求真的很贵!

干杯

加雷思

0

有几件事情映入脑海:

  1. 目前,你在颠簸的网络 - 没有缓存,每一个细胞被加载时,它会执行网络检索文件它可能已经有
  2. 您是否尝试过AFNetworking进行图像检索?有一个特别令人愉快的'UIImageView + AFNetworking.h'类别,它完全符合你的需求,非常好。
  3. 您是否试过将下列内容从主线程移出?

NSFetchRequest *请求= [[NSFetchRequest的alloc] INIT];

//Set predicate and filter for New tweets page 
if ([self.currentTwitterView isEqualToString:@"new"]) { 
    NSPredicate *testForTrue = [NSPredicate predicateWithFormat:@"(approved == NO) AND (tweetDeleted == NO) AND (scheduledTweet == NO)"]; 
    NSSortDescriptor *sortDescriptor1 = [[NSSortDescriptor alloc] initWithKey:@"postDate" ascending:NO]; 
    NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor1, nil]; 
    [request setPredicate:testForTrue]; 
    [request setSortDescriptors:sortDescriptors]; 

//Set filter and predicate for the Approved tweets page 
} else if ([self.currentTwitterView isEqualToString:@"approved"]){ 
    NSPredicate *testForTrue = [NSPredicate predicateWithFormat:@"(approved == YES) AND (tweetDeleted == NO) AND (scheduledTweet == NO)"]; 
    NSSortDescriptor *sortDescriptor1 = [[NSSortDescriptor alloc] initWithKey:@"approvedDate" ascending:NO]; 
    NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor1, nil]; 
    [request setPredicate:testForTrue]; 
    [request setSortDescriptors:sortDescriptors]; 

//Set filter and preicate for the Deleted tweets page 
} else if ([self.currentTwitterView isEqualToString:@"deleted"]){ 
    NSPredicate *testForTrue = [NSPredicate predicateWithFormat:@"tweetDeleted == YES"]; 
    NSSortDescriptor *sortDescriptor1 = [[NSSortDescriptor alloc] initWithKey:@"deletedDate" ascending:NO]; 
    NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor1, nil]; 
    [request setPredicate:testForTrue]; 
    [request setSortDescriptors:sortDescriptors]; 

//Set filter and preicate for the Deleted tweets page 
} else if ([self.currentTwitterView isEqualToString:@"scheduled"]){ 
NSPredicate *testForTrue = [NSPredicate predicateWithFormat:@"scheduledTweet == YES"]; 
NSSortDescriptor *sortDescriptor1 = [[NSSortDescriptor alloc] initWithKey:@"scheduledDate" ascending:NO]; 
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor1, nil]; 
[request setPredicate:testForTrue]; 
[request setSortDescriptors:sortDescriptors]; 
} 


//Setup the Request 
[request setEntity:[NSEntityDescription entityForName:@"Tweet" inManagedObjectContext:_managedObjectContext]]; 

//Assign the predicate to the fetch request 
NSError *error = nil; 

//Create an array from the returned objects 
NSArray *fetchedObjects = [_managedObjectContext executeFetchRequest:request error:&error]; 

Tweet *selectedTweet = [fetchedObjects objectAtIndex:row]; 
+0

将提取移到第二个线程似乎没有任何区别,我尝试过实现AFNetworking,但是我显然不太明白它,我使用上面的代码,并且最终导致丢失和重复的图像。 。 。会喜欢让它工作,因为在AFNetworking来源的演示应用程序有最可爱的黄油顺利滚动! –