2012-07-28 77 views
0

我正在嘗試製作一個基本的照片網格,即一個小的「縮略圖」圖像的「網格」,點擊時會轉到大圖像。我正在使用UITableView來完成此操作。我的問題是,當我嘗試添加旋轉支持時,我不能讓表格重新繪製一排額外的圖像。現有的UITableView照片網格不能正確旋轉?

下面是我的一些代碼,請隨時問任何問題,因爲我在我無計可施這一> :(

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

    if(self.interfaceOrientation==UIInterfaceOrientationPortrait || self.interfaceOrientation==UIInterfaceOrientationPortraitUpsideDown){ 
     NSLog(@"portrait"); 
     for (int i=0; i < self.numberOfColumns; i++) { 
      if (self.photoIndex < [self.photosArray count] || self.shouldReload==TRUE) { 
       UIButton *imageButton = [[UIButton alloc]init]; 

       UIActivityIndicatorView *loadingActivityIndicator = [[UIActivityIndicatorView alloc]initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite]; 

       [imageButton addTarget:self action:@selector(imageClicked:) forControlEvents:UIControlEventTouchDown]; 
       switch (self.buttonNumber) { 
        case 1: 
         self.xCord=35.0f; 
         self.buttonNumber++; 
         break; 
        case 2: 
         self.xCord=213.25f; 
         self.buttonNumber++; 
         break; 
        case 3: 
         self.xCord=391.5f; 
         self.buttonNumber++; 
         break; 
        case 4: 
         self.xCord=569.75f; 
         self.buttonNumber=1; 
         break; 
       } 
       imageButton.frame = CGRectMake(self.xCord, 35.0f, 163.25f, 163.25f); 
       imageButton.tag = self.photoIndex; 
       imageButton.enabled=FALSE; 
       imageButton.imageView.contentMode = UIViewContentModeScaleAspectFit; 

       if(self.buttonsArray.count < self.photosArray.count)[self.buttonsArray addObject:imageButton]; 

       if([self.isInternetAvailableClass isInternetAvailable]==YES)[self downloadImages:self.photoIndex]; 
       cell.selectionStyle=UITableViewCellSelectionStyleNone; 
       [cell addSubview:imageButton]; 

       if(self.photoIndex < self.buttonsArray.count){ 
       if(![[self.buttonsArray objectAtIndex:self.photoIndex] currentImage]){ 

       loadingActivityIndicator.center = imageButton.center; 
       loadingActivityIndicator.hidesWhenStopped=TRUE; 

       } 
       } 
       if(self.activityIndicatorArray.count < self.photosArray.count){ 

        [self.activityIndicatorArray addObject:loadingActivityIndicator]; 
        if([self.isInternetAvailableClass isInternetAvailable]==YES){ 

         [loadingActivityIndicator startAnimating]; 

        } 

       }else{ 
        if(self.photoIndex < self.buttonsArray.count){ 
        [self.activityIndicatorArray replaceObjectAtIndex:self.photoIndex withObject:loadingActivityIndicator]; 

        } 
       } 


       [cell addSubview:loadingActivityIndicator]; 
       self.photoIndex++; 
      } 
     } 

    return cell; 
    }else{ 
     NSLog(@"landscape called!"); 
     for (int i=0; i < self.numberOfColumns; i++) { 
      if (self.photoIndex < [self.photosArray count] || self.shouldReload==TRUE){ 
       NSLog(@"inside landscape called!"); 
       UIButton *imageButton = [[UIButton alloc]init]; 

       UIActivityIndicatorView *loadingActivityIndicator = [[UIActivityIndicatorView alloc]initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite]; 

       [imageButton addTarget:self action:@selector(imageClicked:) forControlEvents:UIControlEventTouchDown]; 
       switch (self.buttonNumber) { 
        case 1: 
         self.xCord=37; 
         self.buttonNumber++; 
         break; 
        case 2: 
         self.xCord=230; 
         self.buttonNumber++; 
         break; 
        case 3: 
         self.xCord=423; 
         self.buttonNumber++; 
         break; 
        case 4: 
         self.xCord=616; 
         self.buttonNumber++; 
         break; 
        case 5: 
         self.xCord=809; 
         self.buttonNumber=1; 
         break; 
       } 
       imageButton.frame = CGRectMake(self.xCord, 35.0f, 163.25f, 163.25f); 
       imageButton.tag = self.photoIndex; 
       imageButton.enabled=FALSE; 
       imageButton.imageView.contentMode = UIViewContentModeScaleAspectFit; 

       if(self.buttonsArray.count < self.photosArray.count){ 

        [self.buttonsArray addObject:imageButton]; 
       } 

       if([self.isInternetAvailableClass isInternetAvailable]==YES){ 

       [self downloadImages:self.photoIndex]; 
       } 
       cell.selectionStyle=UITableViewCellSelectionStyleNone; 
       [cell addSubview:imageButton]; 

       if(self.photoIndex < self.buttonsArray.count){ 
       if(![[self.buttonsArray objectAtIndex:self.photoIndex] currentImage]){ 

        loadingActivityIndicator.center = imageButton.center; 
        loadingActivityIndicator.hidesWhenStopped=TRUE; 
       } 
      } 
       if(self.activityIndicatorArray.count < self.photosArray.count){ 

        [self.activityIndicatorArray addObject:loadingActivityIndicator]; 
        if([self.isInternetAvailableClass isInternetAvailable]==YES){ 

         [loadingActivityIndicator startAnimating]; 

        } 

       }else{ 
        if(self.photoIndex < self.activityIndicatorArray.count){ 
        [self.activityIndicatorArray replaceObjectAtIndex:self.photoIndex withObject:loadingActivityIndicator]; 
        } 
       } 


       [cell addSubview:loadingActivityIndicator]; 
       self.photoIndex++; 
      } 
     } 

     return cell; 

    } 
    if (self.shouldReload==TRUE)self.shouldReload=FALSE; 
} 


#pragma mark - Table view delegate 
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{ 
    return 205.0f; 
} 

#pragma mark - View Lifecycle 
- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 
    self.photosTableView = [[UITableView alloc]init]; 
    self.photosTableView.delegate=self; 
    self.photosTableView.dataSource=self; 
    self.photosTableView.separatorStyle = UITableViewCellSeparatorStyleNone; 
    self.photosTableView.backgroundColor = [UIColor clearColor]; 
    [self.view addSubview:self.photosTableView]; 

    self.isInternetAvailableClass = [[IsInternetAvailable alloc]init]; 
    self.buttonNumber=1; 
    self.xCord=0.0f; 
    self.downloadedImageNumber=0; 
    self.buttonsArray = [[NSMutableArray alloc]init]; 
    self.dataDictionary = [[NSMutableDictionary alloc]init]; 
    self.downloadedImagesArray = [[NSMutableArray alloc]init]; 
    self.activityIndicatorArray = [[NSMutableArray alloc]init]; 
    self.photosArray = [[NSMutableArray alloc]init]; 
    self.largePhotosArray = [[NSMutableArray alloc]init]; 
    self.imageOrderDictionary = [[NSMutableDictionary alloc]init]; 
    self.refToDownloadedImage = [[UIImage alloc]init]; 
    self.unformattedPhotosArray = [[NSMutableArray alloc]init]; 
    self.appDelegate = (StereophotoAppDelegate *)[[UIApplication sharedApplication]delegate]; 
    self.shouldReload=FALSE; 

    if(self.interfaceOrientation==UIInterfaceOrientationPortrait || self.interfaceOrientation==UIInterfaceOrientationPortraitUpsideDown){ 
     self.numberOfColumns=4; 
    }else{ 
     self.numberOfColumns=5; 
    } 

    self.photoIndex=0; 
    self.errorImageArray = [[NSMutableArray alloc]init]; 

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(viewWillAppear:) name:UIApplicationDidBecomeActiveNotification object:nil]; 
    [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(deviceDidRotate) name:UIDeviceOrientationDidChangeNotification object:nil]; 

    [self loadImages]; 
    } 
-(void)viewWillAppear:(BOOL)animated{ 
    self.appDelegate.isSlideshowRunning=NO; 
    self.appDelegate.PhotosPopoverSlideshowText = @"Start Slideshow"; 

    if([self.isInternetAvailableClass isInternetAvailable]==YES){ 

     if(self.isCommingFromNoNetworkConnectivity==YES){ 
      [self viewDidLoad]; 
     } 
     if(self.photosTableView.isHidden==YES)[self.photosTableView setHidden:NO]; 
     self.isCommingFromNoNetworkConnectivity=NO; 
    }else{ 

     if(self.photosTableView.isHidden==NO){ 

      [self.photosTableView setHidden:YES]; 

      self.isCommingFromNoNetworkConnectivity=YES; 
     } 
     UIAlertView *errorAlert = [[UIAlertView alloc]initWithTitle:@"Oops!" message:@"No Internet connection was detected! Please connect to the Internet and try again!" delegate:self cancelButtonTitle:@"Ok" otherButtonTitles:nil, nil]; 
     [errorAlert show]; 
    } 
} 
-(void)viewWillDisappear:(BOOL)animated{ 
    for(NSURLConnection *connection in self.connectionsArray){ 
     [connection cancel]; 
    } 
} 
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation{ 
    return TRUE; 
} 
-(void)deviceDidRotate{ 
    self.photosTableView.frame=CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.height); 

    if(self.interfaceOrientation==UIInterfaceOrientationPortrait || self.interfaceOrientation==UIInterfaceOrientationPortraitUpsideDown){ 
     self.numberOfColumns=4; 
    }else{ 
     self.numberOfColumns=5; 
    } 
    self.shouldReload=TRUE; 
    [self.photosTableView reloadData]; 
} 
-(void)viewDidAppear:(BOOL)animated{ 
    self.photosTableView.frame = CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.height); 

} 

任何幫助的感謝吧!

碎紙機

+0

我還沒有經歷代碼,但我正確的假設它在橫向模式下工作,如果你在橫向模式下啓動,它只是方向的變化是有問題的?如果是這樣,只需在'willAnimateRotationToInterfaceOrientation'中調用'[self.tableview reloadData]'。 – Rob 2012-07-28 01:34:19

+0

就我個人而言,我使用UIScrollView作爲我的畫廊網格,然後在'viewWillLayoutSubviews'上,我只是相應地調整框架。但這是一個更重大的重寫。 – Rob 2012-07-28 01:35:59

+0

是的,如果你在lanscape模式下開始,它只有在以肖像開始然後旋轉時才能正常工作。問題是如果你調用'[self.tableview reloadData]; '在載入cellForRowAtIndexPath中的if語句後,doesent調用函數的其餘部分,除非您將self.photoIndex設置回0,從而混淆了活動指示符。 – Shredder2794 2012-07-28 03:20:19

回答

2

我認爲表格視圖是一個畫廊的錯誤工具,你總是會經歷一些愚蠢的情況,把多個圖像放在一個單獨的表格視圖單元格中,你可能不會使用邏輯邏輯等等didSelectRowAtIndexPath我會建議UIScrollView inste廣告(請參閱下面的示例)。

但是,如果您決定使用表格視圖,那麼[self.tableView reloadData]是正確的解決方案。但是,你的cellForRowAtIndexPath有不少問題:

  1. 您應該只創建UIButtons如果你創建你的。儘管如此,您必須小心謹慎,因爲您的風景和人物肖像方向正確。不難,但要小心。

  2. 您應該將加載單元格的圖像緩存解耦。他們真的是兩回事,即使它們覺得他們非常相似。無論如何,您絕對不應該根據圖像是否緩存來更改cellForRowAtIndexPath中單元格的基本填充內容;它只是改變你獲得圖像的位置。

  3. 無關手頭的問題,但我不會硬編碼屏幕座標。在接下來的幾個月/幾年裏,我將不會驚訝地發現具有不同分辨率的新iOS設備。就我個人而言,根據我可以放入多少個縮略圖self.view.frame.width(您可能使用cell.contentView.frame.width),計算出我可以在屏幕上放入多少圖像。

  4. 也可能與這裏的問題無關,我絕不會建議從viewWillAppear呼叫viewDidLoad。如果你想有一些他們都使用的常見初始化程序,那麼也許你可以做到這一點(但即使這樣做有點sl)),但是假設viewDidLoad調用的是[super viewDidLoad],那麼你最終會調用super方法兩次,並且你不知道iOS是否很酷。可能不會造成災難,但我無法想象這是個好主意。

  5. 最後,也無關你的問題,但你並不需要使用通知中心UIDeviceOrientationDidChangeNotification因爲標準willAnimateRotationToInterfaceOrientationviewWillLayoutSubviews會替我們。

如果你想做一個UIScrollView版本從遠程服務器的圖像延遲加載一個畫廊,撬動了縮略圖的緩存,檢測的圖像等敲擊它可能看起來像以下。我將注意力放在絕對不存在任何縱向/橫向邏輯(因爲它只是查看滾動視圖的尺寸),但它能很好地處理方向的變化。不過,我沒有包含我的代碼,因爲它對於特定的應用程序來說顯然是完全獨一無二的,但是您可能還是會明白這一點。並且可以進行各種優化(例如,使用Reachability),但這是可能爲您完成這項工作的圖庫的外殼。

// GalleryViewController.m 

#import "GalleryViewController.h" 
#import "ThumbnailCache.h" 

#define IMAGE_WIDTH 76.0 
#define IMAGE_HEIGHT 76.0 

@interface MyImage : NSObject 

@property (nonatomic, strong) NSString *urlString; 
@property (nonatomic, strong) UIImageView *imageView; 
@property (nonatomic, strong) UIActivityIndicatorView *activityIndicator; 
@property (nonatomic, strong) UIView *view; 
@property BOOL loading; 
@property BOOL loaded; 

@end 

@implementation MyImage 

// I find that I generally can get away with loading images in main queue using Documents 
// cache, too, but if your images are not optimized (e.g. are large), or if you're supporting 
// older, slower devices, you might not want to use the Documents cache in the main queue if 
// you want a smooth UI. If this is the case, change kUseDocumentsCacheInMainQueue to NO and 
// then use the Documents cache only in the background thread. 

#define kUseDocumentsCacheInMainQueue YES 

- (id)init 
{ 
    self = [super init]; 
    if (self) 
    { 
     _view = [[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, IMAGE_WIDTH, IMAGE_HEIGHT)]; 
     _imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0.0, 0.0, IMAGE_WIDTH, IMAGE_HEIGHT)]; 
     _imageView.contentMode = UIViewContentModeScaleAspectFill; 
     _imageView.clipsToBounds = YES; 
     [_view addSubview:_imageView]; 
     _loading = NO; 
     _loaded = NO; 
    } 
    return self; 
} 

- (void)loadImage:(dispatch_queue_t)queue 
{ 
    if (self.loading) 
     return; 

    self.loading = YES; 

    ThumbnailCache *cache = [ThumbnailCache sharedManager]; 

    if (self.imageView.image == nil) 
    { 
     UIImage *imageFromCache = [cache objectForKey:self.urlString useDocumentsCache:kUseDocumentsCacheInMainQueue]; 
     if (imageFromCache) 
     { 
      if (self.activityIndicator) 
      { 
       [self.activityIndicator stopAnimating]; 
       self.activityIndicator = nil; 
      } 

      self.imageView.image = imageFromCache; 
      self.loading = NO; 
      self.loaded = YES; 
      return; 
     } 

     if (self.activityIndicator == nil) 
     { 
      self.activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray]; 
      self.activityIndicator.center = CGPointMake(self.view.frame.size.width/2.0, self.view.frame.size.height/2.0); 
      [self.view addSubview:self.activityIndicator]; 
     } 
     [self.activityIndicator startAnimating]; 

     dispatch_async(queue, ^{ 
      if (self.loading) 
      { 
       UIImage *image = nil; 

       // only requery cache for Documents cache if we didn't do so in the main queue 

       if (!kUseDocumentsCacheInMainQueue) 
        image = [cache objectForKey:self.urlString useDocumentsCache:YES]; 

       // if we haven't gotten the image yet, retrieve it from the remote server 

       if (!image) 
       { 
        NSData *data = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:self.urlString]]; 

        if (data) 
        { 
         image = [UIImage imageWithData:data]; 
         [cache setObject:image forKey:self.urlString data:data]; 
        } 
       } 

       // now update the UI in the main queue 

       dispatch_async(dispatch_get_main_queue(), ^{ 
        if (self.loading) 
        { 
         [self.activityIndicator stopAnimating]; 
         self.activityIndicator = nil; 
         self.imageView.image = image; 
         self.loading = NO; 
         self.loaded = YES; 
        } 
       }); 
      } 
     }); 
    } 
} 

- (void)unloadImage 
{ 
    NSLog(@"%s %@", __FUNCTION__, self.urlString); 

    // remove from imageview, but not cache 

    self.imageView.image = nil; 

    self.loaded = NO; 
    self.loading = NO; 
} 

@end 


@interface GalleryViewController() 
{ 
    NSMutableArray *_myImages; 
    dispatch_queue_t _queue; 
} 
@end 

@implementation GalleryViewController 

- (void)dealloc 
{ 
    if (_queue) 
     dispatch_release(_queue); 

    [[NSNotificationCenter defaultCenter] removeObserver:self 
                name:UIApplicationDidBecomeActiveNotification 
                object:nil]; 
} 

- (void)didReceiveMemoryWarning 
{ 
    [super didReceiveMemoryWarning]; 

    // this is not strictly necessary because `NSCache` will automatically 
    // evict objects in low memory situations; it will not, though 
    // remove items when you try to simulate a low memory situation 
    // in the simulator, but it really will empty the cache when 
    // memory really runs low 
    // 
    // ThumbnailCache *cache = [ThumbnailCache sharedManager]; 
    // [cache removeAllObjects]; 
} 

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 

    self.scrollView.delegate = self; 

    _queue = dispatch_queue_create("com.robertmryan.imageloader", NULL); 

    [self loadImages]; 

    UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapHandler:)]; 
    [self.scrollView addGestureRecognizer:tap]; 

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(appDidBecomeActive) name:UIApplicationDidBecomeActiveNotification object:nil]; 
} 

- (void)viewWillLayoutSubviews 
{ 
    NSUInteger imagesPerRow = (self.view.frame.size.width/IMAGE_WIDTH); 
    CGFloat imageMargin = (self.view.frame.size.width - (IMAGE_WIDTH * imagesPerRow))/(imagesPerRow + 1.0); 

    NSUInteger row = 0; 
    NSUInteger col = -1; 

    for (NSUInteger i = 0; i < [_myImages count]; i++) 
    { 
     col++; 
     if (col >= imagesPerRow) 
     { 
      col = 0; 
      row++; 
     } 

     MyImage *myImage = [_myImages objectAtIndex:i]; 
     CGRect frame = myImage.view.frame; 
     frame.origin.x = imageMargin + (imageMargin + IMAGE_WIDTH) * col; 
     frame.origin.y = imageMargin + (imageMargin + IMAGE_HEIGHT) * row; 
     myImage.view.frame = frame; 
    } 

    self.scrollView.contentSize = CGSizeMake(self.scrollView.frame.size.width, (row + 1) * (IMAGE_HEIGHT + imageMargin) + imageMargin); 

    [self displayVisibleImages:NO]; 
} 

- (void)viewDidUnload 
{ 
    [self setScrollView:nil]; 
    _myImages = nil; 

    [super viewDidUnload]; 
} 

- (void)viewWillAppear:(BOOL)animated 
{ 
    [super viewWillAppear:animated]; 

    [self displayVisibleImages:NO]; 
} 

- (void)appDidBecomeActive 
{ 
    [self displayVisibleImages:YES]; 
} 

- (void)displayVisibleImages:(BOOL)forceLoad 
{ 
    CGPoint contentOffset = self.scrollView.contentOffset; 
    CGRect contentFrame = self.scrollView.bounds; 
    contentFrame.origin = contentOffset; 

    for (MyImage *myImage in _myImages) 
    { 
     if (CGRectIntersectsRect(contentFrame, myImage.view.frame)) 
     { 
      // if the image is visible, then make sure it's loaded 

      if (!myImage.loaded || forceLoad) 
       [myImage loadImage:_queue]; 
     } 
     else 
     { 
      // if not, go ahead and unload it to conserve memory 

      if (myImage.loaded || myImage.loading) 
       [myImage unloadImage]; 
     } 
    } 
} 

- (void)scrollViewDidScroll:(UIScrollView *)scrollView 
{ 
    [self displayVisibleImages:NO]; 
} 

- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration 
{ 
    CGFloat version = [[[UIDevice currentDevice] systemVersion] floatValue]; 

    if (version < 5.0) 
     [self viewWillLayoutSubviews]; 
} 

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation 
{ 
    return TRUE; 
} 

- (void)tapHandler:(UITapGestureRecognizer *)sender 
{ 
    CGPoint location = [sender locationInView:self.scrollView]; 

    for (MyImage *myImage in _myImages) 
    { 
     if (CGRectContainsPoint(myImage.view.frame, location)) 
      NSLog(@"Tapped in image %1d", myImage.view.tag); 
    } 
} 

- (void)loadImages 
{ 

    NSArray *imageUrlStrings = [self loadImageUrls]; 
    _myImages = [[NSMutableArray alloc] init]; 

    NSUInteger imagesPerRow = (self.scrollView.frame.size.width/IMAGE_WIDTH); 
    CGFloat imageMargin = (self.scrollView.frame.size.width - (IMAGE_WIDTH * imagesPerRow))/(imagesPerRow + 1.0); 

    NSInteger row = 0; 
    NSInteger col = -1; 

    for (NSUInteger i = 0; i < [imageUrlStrings count]; i++) 
    { 
     col++; 
     if (col >= imagesPerRow) 
     { 
      col = 0; 
      row++; 
     } 

     MyImage *myImage = [[MyImage alloc] init]; 
     myImage.urlString = [imageUrlStrings objectAtIndex:i]; 
     CGRect frame = myImage.view.frame; 
     frame.origin.x = imageMargin + (imageMargin + IMAGE_WIDTH) * col; 
     frame.origin.y = imageMargin + (imageMargin + IMAGE_HEIGHT) * row; 
     myImage.view.frame = frame; 
     [self.scrollView addSubview:myImage.view]; 
     myImage.view.tag = i; 

     [_myImages addObject:myImage]; 
    } 

    self.scrollView.contentSize = CGSizeMake(self.scrollView.frame.size.width, (row + 1) * (IMAGE_HEIGHT + imageMargin) + imageMargin); 
} 

@end 

ThumbnailCache只是一個簡單的NSCache單獨的對象。 (無論你是以singleton的形式實現它,取決於你;你不需要,但考慮到我的應用程序的特性,這很方便。)我已經更新了這個以封裝第二個Documents緩存(因此你從一個遠程服務器,緩存在NSCache對象中以獲得最佳性能,如果要保存程序的後續調用,從而需要從服務器重新檢索映像,則在緩存在Documents文件夾中,從而爲您提供跨會話的持久性緩存)。這理論上可以(應該?)優化以清除長時間未使用的圖像的文件夾,但我會留給其他人實施。

// 
// ThumbnailCache.h 
// 
// Created by Robert Ryan on 7/17/12. 
// Modified 8/9/12 to support secondary Documents-based cache. 
// 

#import <UIKit/UIKit.h> 

@interface ThumbnailCache : NSCache 

+ (id)sharedManager; 

- (id)objectForKey:(id)key useDocumentsCache:(BOOL)useDocumentsCache; 
- (void)setObject:(UIImage *)image forKey:(id)key data:(NSData *)data; 

@end 

// 
// ThumbnailCache.m 
// 
// Created by Robert Ryan on 7/17/12. 
// Modified 8/9/12 to support secondary Documents-based cache. 
// 

#import "ThumbnailCache.h" 

@implementation ThumbnailCache 

- (id)init 
{ 
    self = [super init]; 
    if (self) 
    { 
     self.name = @"Thumbnail cache"; 
    } 

    return self; 
} 

+ (id)sharedManager 
{ 
    static ThumbnailCache *sharedMyManager = nil; 
    static dispatch_once_t onceToken; 
    dispatch_once(&onceToken, ^{ 
     sharedMyManager = [[self alloc] init]; 
    }); 
    return sharedMyManager; 
} 

- (id)objectForKey:(id)key 
{ 
    return [self objectForKey:key useDocumentsCache:YES]; 
} 

- (id)objectForKey:(id)key useDocumentsCache:(BOOL)useDocumentsCache 
{ 
    // This is a variation of the standard objectForKey method which takes an additional 
    // parameter, useDocumentsCache, which will tell this to also check the Documents 
    // cache or not. This is a subtle refinement in case you don't want your main queue 
    // to use the Documents cache. Generally, if you're dealing with optimized images, 
    // this is not necessary, but if you're dealing with large images, this permutation 
    // can be useful. 

    // first, just try to get the image from the NSCache 

    id result = [super objectForKey:key]; 

    // if successful (or if we don't want to look in the Documents cache), then just return. 

    if (result || !useDocumentsCache) 
     return result; 

    // otherwise, if we didn't find it in the NSCache and we want to look in our Documents 
    // cache, then let's do so 

    NSString *path = [self pathInDocumentCache:key]; 

    if (!result && path) 
    { 
     // get the data from the remote server 

     NSData *data = [NSData dataWithContentsOfFile:path]; 
     if (data) 
     { 
      // and if we found it, save it in our NSCache 

      UIImage *image = [UIImage imageWithData:data]; 
      if (image) 
       [self setObject:image forKey:key]; 

      return image; 
     } 
    } 

    return result; 
} 

- (void)setObject:(UIImage *)image forKey:(id)key data:(NSData *)data 
{ 
    // This is a variation of the standard setObject:forKey which takes an additional NSData. 
    // The notion is that our cache stores UIImage objects (to save the theoretical overhead, 
    // if any, of loading image data into a NSData and then into a UIImage ... I wouldn't be 
    // surprised if Apple did some cool optimization of UIImage objects, though I don't know), 
    // so if we want to write our image file, but don't want to convert the UIImage back to 
    // a NSData, then let's just take the original NSData as a parameter. 

    // save the object in the NSCache 

    [super setObject:image forKey:key]; 

    // now let's also save the NSData in our Documents-based cache 

    NSFileManager *fileManager = [NSFileManager defaultManager]; 
    NSString *path = [self pathInDocumentCache:key]; 

    if (path && ![fileManager fileExistsAtPath:path]) 
    { 
     // let's create the folder if we need to 

     NSString *folder = [path stringByDeletingLastPathComponent]; 
     if (![fileManager fileExistsAtPath:folder]) 
      [fileManager createDirectoryAtPath:folder withIntermediateDirectories:YES attributes:nil error:nil]; 

     // and let's write the NSData to that folder 

     [data writeToFile:path atomically:YES]; 
    } 
} 

- (NSString *)pathInDocumentCache:(NSString *)key 
{ 
    if (![key isKindOfClass:[NSString class]]) 
     return nil; 

    NSString *docsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]; 
    NSString *imagePath = [docsPath stringByAppendingPathComponent:@"image_cache"]; 
    NSURL *url = [NSURL URLWithString:key]; 

    return [imagePath stringByAppendingPathComponent:[url relativePath]]; 
} 

@end 

我會感到驚訝,如果有沒有一些偉大的公開可用的庫類,太多,但如果你想推出自己的,上面是一個可能性。

+0

非常感謝!由於我對iOS開發不熟悉,因此我不知道這一點。再次謝謝你! – Shredder2794 2012-07-28 15:05:26

+0

我有很多東西在我的盤子上,學校開始和東西,我只是現在開始玩這個代碼。除非旋轉設備時,網格不會重新繪製以包含更多(或更少)「列」。我的意思是如果我在網格中有7張圖像,第一行是5,第二行是2,當我旋轉設備時,網格保持不變,也就是說,頂部行仍然有5張圖像, 2在第二個。下一個評論 – Shredder2794 2012-08-04 00:42:01

+0

沒有試圖成爲一個幫助吸血鬼,但我怎麼去設置它,當你旋轉設備它重繪圖像的數量,以配合可用的景觀? – Shredder2794 2012-08-04 00:42:25