0

我有一个包含 NSTableView 的 NSScrollView,它有 3 列,其中 1 列通过 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;

}
4

2 回答 2

0

有几件事浮现在脑海:

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

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];
于 2013-07-31T21:25:57.223 回答
0

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

所以看起来一个 fetch 请求真的很昂贵!

干杯

加雷斯

于 2013-08-01T13:48:48.040 回答