非常生涩的滚动NSTableView

时间:2013-07-31 20:35:28

标签: objective-c macos interface-builder

我有一个NSScrollView,它包含一个NSTableView,它有3列,其中一列通过TableCellView在其中有一个自定义视图。

要通过后台进程将图像加载到此单元格中,我已使用以下代码对单元格进行了子类化。然而,滚动是真的生涩,我想知道是否有任何方法来优化它,图像不是很大,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;

}

2 个答案:

答案 0 :(得分:0)

有些事情让人想起:

  1. 目前,你正在捣乱网络 - 没有缓存,每次加载一个单元格时,它都会执行网络检索它可能已经拥有的文件
  2. 您是否尝试AFNetworking进行图像检索?有一个特别令人愉快的'UIImageView + AFNetworking.h'类别,它可以完全满足您的需求,非常好。
  3. 您是否尝试过以下主线程?
  4.   

    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];
    

答案 1 :(得分:0)

好的,所以经过一些更多的故障排除后,我完全删除了图像,桌子仍然很慢。所以,我现在编写了一个新函数,它维护当前选择对象的数组,以保存表格绘制函数,为每一行调用它。这完全解决了这个问题,现在一切都变得柔和而可爱。

所以看来抓取请求真的很贵!

干杯

加雷