2013-07-31 42 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來源的演示應用程序有最可愛的黃油順利滾動! –