2011-10-03 184 views
2

我正在開發的應用程序正在吸引自定義廣告。我正在檢索廣告,網絡方面的工作正常。我遇到的問題是AdController收到廣告時分析JSON對象然後請求圖像。UIView動畫已延遲

// Request the ad information 
NSDictionary* resp = [_server request:coords_dict isJSONObject:NO responseType:JSONResponse]; 
// If there is a response... 
if (resp) { 
    // Store the ad id into Instance Variable 
    _ad_id = [resp objectForKey:@"ad_id"]; 
    // Get image data 
    NSData* img = [NSData dataWithContentsOfURL:[NSURL URLWithString:[resp objectForKey:@"ad_img_url"]]]; 
    // Make UIImage 
    UIImage* ad = [UIImage imageWithData:img]; 
    // Send ad to delegate method 
    [[self delegate]adController:self returnedAd:ad]; 
} 

這一切按預期工作,並AdController拉形象就好在...

-(void)adController:(id)controller returnedAd:(UIImage *)ad{ 
    adImage.image = ad; 
    [UIView animateWithDuration:0.2 animations:^{ 
     adImage.frame = CGRectMake(0, 372, 320, 44); 
    }]; 
    NSLog(@"Returned Ad (delegate)"); 
} 

的當委託方法被調用時,它會記錄該消息到控制檯,但它需要UIImageView* adImage最多需要5-6秒才能生成動畫。由於應用處理廣告請求的方式,動畫必須是即時的。

隱藏廣告的動畫是即時的。

-(void)touchesBegan{ 
    [UIView animateWithDuration:0.2 animations:^{ 
     adImage.frame = CGRectMake(0, 417, 320, 44); 
    }]; 
} 

回答

4

如果廣告加載發生在後臺線程(最簡單的檢查方法是[NSThread isMainThread]),那麼你就不能在同一個線程更新UI狀態!大多數UIKit不是線程安全的;當然,UIViews目前顯示的不是。可能發生的情況是,主線程不會「注意」後臺線程中發生的變化,因此在發生其他事情之前不會刷新屏幕。

-(void)someLoadingMethod 
{ 
    ... 
    if (resp) 
    { 
    ... 
    [self performSelectorInMainThread:@selector(loadedAd:) withObject:ad waitUntilDone:NO]; 
    } 
} 

-(void)loadedAd:(UIImage*)ad 
{ 
    assert([NSThread isMainThread]); 
    [[self delegate] adController:self returnedAd:ad]; 
} 
+0

網絡請求發生在後臺線程中,但是當它調用後臺委託時,不應該將它推送到委託對象所在的線程中嗎?我應該隱式告訴它在主Queue上派發委託方法嗎? – SkylarSch

+1

我繼續告訴代表派遣主要隊列,現在它的行爲正常。 – SkylarSch

+0

這取決於AdController中的代碼。大多數合理的API希望在主線程中使用,並在主線程上運行委託方法,但可能有一些不是經過精心設計的。如果它在主線程中運行,那麼你不想調用阻塞的' - [NSData dataWithContentsOfURL:]'。 –