Three20 - TTStyledTextLabel遇到base64图像数据而不是URL - 崩溃

问题描述:

我正在使用TTStyledTextLabel和来自XHTML数据的TTStyledText来显示新闻文章。 它工作正常,除了img是数据而不是链接,在这种情况下它崩溃!Three20 - TTStyledTextLabel遇到base64图像数据而不是URL - 崩溃

代码

TTStyledTextLabel *storyLabel = [[TTStyledTextLabel alloc] init]; 
[storyLabel setText: [TTStyledText textFromXHTML:[articleContents objectForKey:@"storyText"]]]; 

正常工作与正常的图像网址XML,

但是当它遇到这样的图像数据:

img class="alignleft" src="data:image/jpg;base64,/9j/4AAQSkZJRgA... 
(lots more in here)...1HhI0T//2Q==" alt="" width="267" height="189"/

它与输出崩溃:

-[NSURLResponse allHeaderFields]: unrecognized selector 
sent to instance 0xb83b370 

这只发生在遇到图像数据时,否则如果是正常的img链接,它会加载正常。

谢谢!

在这里回答我自己的问题。

这似乎是一个罕见的情况发生(在我的具体情况)。我解决这个问题的方式是通过手动检查来查看img链接(它可能是图像数据)是否具有常见的图像文件类型扩展名(jpg,png,gif等)。如果不存在并丢弃数据,我只是无视它。

我对Web标准不太了解,以及是否认为可以将图像数据嵌入到链接应该存在的地方,但是现在我意识到它存在并可能导致使用此类的崩溃。希望这可以帮助任何有此问题的人。

问题是Three20 TTRequestLoader在NSURLConnectionDataDelegate方法中使用NSHTTPURLResponse而不是NSURLResponse。 NSURLResponse没有allHeaderFields方法,所以应用程序崩溃。

- (void)connection:(NSURLConnection*)connection didReceiveResponse:(NSHTTPURLResponse*)response { 
    _response = [response retain]; 

    if ([response isKindOfClass:[NSHTTPURLResponse class]]) { 
    NSDictionary* headers = [response allHeaderFields]; 
    int contentLength = [[headers objectForKey:@"Content-Length"] intValue]; 

    // If you hit this assertion it's because a massive file is about to be downloaded. 
    // If you're sure you want to do this, add the following line to your app delegate startup 
    // method. Setting the max content length to zero allows anything to go through. If you just 
    // want to raise the limit, set it to any positive byte size. 
    // [[TTURLRequestQueue mainQueue] setMaxContentLength:0] 
    TTDASSERT(0 == _queue.maxContentLength || contentLength <=_queue.maxContentLength); 

    if (contentLength > _queue.maxContentLength && _queue.maxContentLength) { 
     TTDCONDITIONLOG(TTDFLAG_URLREQUEST, @"MAX CONTENT LENGTH EXCEEDED (%d) %@", 
         contentLength, _urlPath); 
     [self cancel]; 
    } 

    _responseData = [[NSMutableData alloc] initWithCapacity:contentLength]; 
    } 
    else if ([response isKindOfClass:[NSURLResponse class]]) { 
    _responseData = [[NSMutableData alloc] init]; 
    } 
    else { 
    [self cancel]; 
    } 
} 

- (void)connectionDidFinishLoading:(NSURLConnection *)connection { 
    TTNetworkRequestStopped(); 

    if ([_response isKindOfClass:[NSHTTPURLResponse class]]) { 
    TTDCONDITIONLOG(TTDFLAG_ETAGS, @"Response status code: %d", _response.statusCode); 

    // We need to accept valid HTTP status codes, not only 200. 
    if (_response.statusCode >= 200 && _response.statusCode < 300) { 
     [_queue loader:self didLoadResponse:_response data:_responseData]; 
    } else if (_response.statusCode == 304) { 
     [_queue loader:self didLoadUnmodifiedResponse:_response]; 
    } else { 
     TTDCONDITIONLOG(TTDFLAG_URLREQUEST, @" FAILED LOADING (%d) %@", 
         _response.statusCode, _urlPath); 
     NSError* error = [NSError errorWithDomain:NSURLErrorDomain code:_response.statusCode 
             userInfo:nil]; 
     [_queue loader:self didFailLoadWithError:error]; 
    } 
    } 
    else if ([_response isKindOfClass:[NSURLResponse class]]) { 
    [_queue loader:self didLoadResponse:_response data:_responseData]; 
    } 

    TT_RELEASE_SAFELY(_responseData); 
    TT_RELEASE_SAFELY(_connection); 
} 

您可以通过检查类修复