2010-10-28 68 views
0

我想添加到UIImageView設置圖片的URL的能力。因此我想要做類似的事情。異步請求和委託可能帶來的風險

[anImageView setImageWithContentAtUrl:[NSURL URLWithString:@"http://server.com/resource.png"]]; 

所以我創建了一個類(下面的代碼)。

NSString *kUserInfoImageViewKey = @"imageView"; 
NSString *kUserInfoActivityIndicatorKey = @"activityIndicator"; 

@implementation UIImageView (asynchronous) 

#pragma mark - 
- (void)setImageWithContentAtUrl:(NSURL *)imageUrl andActivityIndicator:(UIActivityIndicatorView *)activityIndicatorOrNil { 
    [activityIndicatorOrNil startAnimating]; 

NSMutableDictionary *dict = [[NSMutableDictionary alloc] init]; 
[dict setValue:self forKey:kUserInfoImageViewKey]; 
[dict setValue:activityIndicatorOrNil forKey:kUserInfoActivityIndicatorKey]; 

ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:imageUrl]; 
request.delegate = self; 
request.userInfo = dict; 
    [dict release]; 
[request startAsynchronous]; 
} 

#pragma mark - 
#pragma mark private 

- (void)requestFinished:(ASIHTTPRequest *)aRequest { 
// get concerned view from user info 
NSDictionary *dictionary = aRequest.userInfo; 
    UIImageView *imageView = (UIImageView *)[dictionary valueForKey:kUserInfoImageViewKey]; 
UIActivityIndicatorView *activityIndicator = (UIActivityIndicatorView *) [dictionary valueForKey:kUserInfoActivityIndicatorKey]; 

    [activityIndicator stopAnimating]; 

    NSData *responseData = [aRequest responseData]; 
UIImage * image = [[UIImage alloc] initWithData:responseData]; 

imageView.image = image; 
[image release]; 
} 

- (void)requestFailed:(ASIHTTPRequest *)request { 
} 

一個ASIHTTPRequest被創建並且以圖像作爲委託來啓動。如果在ASIHTTPRequest返回結果之前解除分配圖像,我認爲存在風險。因此,也許在setImageWithContentAtUrl中添加一個保留:並在requestFinished和requestFailed中添加一個版本:但我並不十分自信。

怎麼可能做這樣的事情?

問候, 昆汀

+0

如果我在setImageWithContentAtUrl中保留圖像並在ASIHTTPRequest回調中釋放,它是否工作? - (無效)setImageWithContentAtUrl:(NSURL *)IMAGEURL andActivityIndi​​cator:(UIActivityIndi​​catorView *)activityIndi​​catorOrNil { ... [自保留]; [request startAsynchronous]; } - (void)requestFinished:(ASIHTTPRequest *)aRequest {...} [self release]; (void)requestFailed:(ASIHTTPRequest *)request { } [self release]; } 一些副作用? Regards, – Quentin 2010-10-31 16:04:13

回答

1

昆汀,

我經常使用ASIHTTPRequest異步調用,所以我知道你是從這裏來。此外,這是第一次設置的痛苦,但是你知道Three20圖書館的TTImageView(我認爲就是這樣)已經做了你想做的事情嗎?它甚至會在本地緩存圖像,所以你不必每次都加載它。無論如何。

您的擔心是正確的:ASIHTTPRequest是NSOperation對象(它實際上是一個子類)的包裝,所以只要請求處於活動狀態,NSOperationQueue就會保留ASIHTTPRequest。

如果您的用戶更改視圖(例如,在導航欄控制器上),然後解除分配您的UIImageView,則代碼在嘗試回撥到代理時可能會崩潰。因此,當您釋放圖像視圖時,最好堅持對請求的引用,然後取消它。

而不是一個類別,這可能是其中子類更好的時代之一 - 因爲你想覆蓋dealloc方法(這是我處理這個問題的方式)。

首先,這個屬性添加到您的子類:

@property (nonatomic, retain) ASIHTTPRequest *request; 

此行,然後添加到您的方法,這樣你就可以抓住它:在您的ASIHTTPRequest委託方法

self.request = request; 

最後, ,破壞引用:

self.request = nil; 

然後你的dealloc可能看起來像這樣:

- (void) dealloc 
{ 
    if (self.request) 
    { 
    // Cancels the NSOperation so ASIHTTPRequest doesn't call back to this 
    [self.request cancel]; 
    } 
    [request release]; 
    [super dealloc] 
} 
+0

謝謝你確認我的「恐懼」。所以我將繼承UIImageView。 – Quentin 2010-10-29 06:11:00