2011-10-03 118 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:]'。 –