2014-02-06 25 views
0

我正在使用NSOperation隊列來獲取圖像並將它們顯示在我的tableview單元格中。在圖像返回之前,我會顯示加載覆蓋圖,一旦操作完成,它會向代表顯示,然後刪除加載覆蓋圖。在NSOperationQueue中調出同步服務器調用

現在,我想在5秒後超時取出操作並刪除加載覆蓋,但基於定時器的方法沒有解決。請建議。

下面是我的代碼:

#import "MyImageFetchOperation.h" 
#import "MyImageFetchController.h" 
#import "MyHTTPRequest.h" 

@interface MyImageFetchOperation() 

@property (nonatomic, strong) NSString *imageURL; 
@property (nonatomic, weak) id <MyOperationCompletedDelegate> delegate; 
@property (nonatomic, assign) BOOL isCompleted; 
@property (nonatomic, weak) NSTimer *timeoutTimer; 

@end 

@implementation MyImageFetchOperation 
@synthesize imageURL; 
@synthesize delegate; 
@synthesize isCompleted; 

#define kMyImageFetchTimeout 5 

#pragma mark - 
#pragma mark Destruction 

- (void)dealloc { 
    self.delegate = nil; 
} 


- (id)initWithImageURL:(NSString *)iImageURL delegate:(id)iDelegate { 
    if (self = [super init]) { 
     self.imageURL = iImageURL; 
     self.delegate = iDelegate; 
    } 
    return self; 
} 


- (void)main { 
    self.isCompleted = NO; 
    NSMutableURLRequest *aRequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:self.imageURL]]; 
    [aRequest setTimeoutInterval:kMyImageFetchTimeout]; 
    [aRequest setHTTPMethod:@"GET"]; 

    self.timeoutTimer = [NSTimer scheduledTimerWithTimeInterval:kMyImageFetchTimeout target:self selector:@selector(requestTimedOut) userInfo:nil repeats:NO]; 

    [NSURLConnection sendAsynchronousRequest:aRequest queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *iData, NSError *iConnectionError) { 
     if (!self.isCompleted) { 
      if (iConnectionError) { 
       [[MyImageFetchController sharedRunnerImageFetchControllerMy] urlFailed:self.imageURL]; 
      } 

      UIImage *anImage = [UIImage imageWithData:iData]; 

      if (anImage) { 
       [MyUtilities cacheFile:anImage withName:[self.imageURL runnerMD5HashMy] toDirectory:[self.delegate cacheDirectoryForImages]]; 
      } else { 
       [[MyImageFetchController sharedRunnerImageFetchControllerMy] urlFailed:self.imageURL]; 
      } 

      [self.delegate operationCompletedForURL:self.imageURL]; 
      self.isCompleted = YES; 
     } 
    }]; 
} 


- (void)requestTimedOut { 
    self.isCompleted = YES; 
    [self.timeoutTimer invalidate]; 
    self.timeoutTimer = nil; 
    [[MyImageFetchController sharedRunnerImageFetchControllerMy] urlFailed:self.imageURL]; 
    [self.delegate operationCompletedForURL:self.imageURL]; 
} 

@end 
+0

爲什麼你需要計時器?您已經在URL請求上設置了超時,所以如果請求超時,應在最後5秒後調用完成處理程序,'iData == nil'。 –

+0

馬丁,他確實有問題。 「因此,當負載活動的一個實例發生時(例如,從網絡收到一個請求的字節),請求的空閒間隔被重置爲0」 因此,如果他將間隔設置爲5,但連接需要4個數據塊,每個數據塊需要2秒鐘纔到達,連接甚至可能不超時。 –

回答

0

你需要一個運行循環,使您的工作計時器,像這樣:

- (void)main 
{ 
    // your code 
    yourTimer = ... // create your timer 

    NSRunLoop* runLoop = [NSRunLoop currentRunLoop]; 
    [runLoop addTimer:yourTimer forMode:NSRunLoopCommonModes]; 
    [runLoop run]; 
} 

哦,還有,我想這是更好地建立自己的自動釋放池主。

0

你爲什麼不叫

[self.delegate operationCompletedForURL:self.imageURL]; 

這裏面如果?

if (iConnectionError) { 

作爲一方,您不應該在該塊內使用self,您應該使用__block變量。

+0

好吧,無論如何,因爲這個聲明不在任何if或else中而被調用。 – Abhinav

+0

是的,你說得對。但是,然後代理正在正確調用沒有計時器?最好的選擇是使用請求的超時時間(就像你看起來那樣),而不是使用定時器。 –

+0

是的,但是請求的時間安排並不能保證實際上在那段時間內超時。如果服務器連接建立需要時間,但一旦建立了服務器連接並且服務器在響應中很少遲緩,那麼它會工作,然後它將遵循默認超時。 – Abhinav