アプリケーションに問題があります。シミュレーターで実行されますが、デバイスで実行しようとするとクラッシュします。私はそれをテストし、レビューのために Apple に提出する前に動作しましたが、今、もう一度見てみると、クラッシュし続けます。また、最初はクラッシュしませんが、2 番目のビューに移動しようとするとクラッシュします。それを理解するのを手伝ってくれるかどうか教えてください。ありがとう!
(別の投稿でこの提案/回答を見つけたので、既に NSZombieEnable を設定しようとしましたが、うまくいきません)
OS Version: iPhone OS 5.1.1 (9B206)
Report Version: 104
Exception Type: EXC_BAD_ACCESS (SIGSEGV)
Exception Codes: KERN_INVALID_ADDRESS at 0x6f466874
Crashed Thread: 0
Thread 0 name: Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0 libobjc.A.dylib 0x335b2f7e objc_msgSend + 22
1 Foundation 0x34d24d04 _NSDescriptionWithLocaleFunc + 44
2 CoreFoundation 0x3597496e __CFStringAppendFormatCore + 7998
3 CoreFoundation 0x358ef1d8 _CFStringCreateWithFormatAndArgumentsAux + 68
4 Foundation 0x34d24c2e +[NSString stringWithFormat:] + 54
5 Sustain 0x00082148 +[HTMLParser parseDataForRequest:error:] (HTMLParser.m:169)
6 Sustain 0x00085a5a -[ProxyRequestResponseHandler requestFinished:] (ProxyRequestResponseHandler.m:251)
7 CoreFoundation 0x358f31f4 -[NSObject performSelector:withObject:] + 36
8 Sustain 0x00054364 -[ASIHTTPRequest reportFinished] (ASIHTTPRequest.m:2004)
9 CoreFoundation 0x358f31f4 -[NSObject performSelector:withObject:] + 36
10 Foundation 0x34dc3740 __NSThreadPerformPerform + 344
11 CoreFoundation 0x35968acc __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 8
12 CoreFoundation 0x35968298 __CFRunLoopDoSources0 + 208
13 CoreFoundation 0x3596703e __CFRunLoopRun + 646
14 CoreFoundation 0x358ea49e CFRunLoopRunSpecific + 294
15 CoreFoundation 0x358ea366 CFRunLoopRunInMode + 98
16 GraphicsServices 0x33685432 GSEventRunModal + 130
17 UIKit 0x330c2cce UIApplicationMain + 1074
18 Sustain 0x00019c26 main (main.m:16)
19 Sustain 0x00019bc0 start + 32
Thread 0 crashed with ARM Thread State:
r0: 0x00128a98 r1: 0x325894f6 r2: 0x359eccd5 r3: 0x6f46687c
r4: 0x32588417 r5: 0x00000000 r6: 0x3f3078c8 r7: 0x2fe0cb70
r8: 0x2fe0cc13 r9: 0x0c96253d r10: 0x359730b6 r11: 0x00000000
ip: 0x3f2e26f0 sp: 0x2fe0cb5c lr: 0x34d24d0b pc: 0x335b2f7e
cpsr: 0x200f0030
HTMLParser で要求した計算方法は次のとおりです。
+ (BOOL)parseDataForRequest:(ASIHTTPRequest *)request error:(NSError **)error
{
NSStringEncoding encoding = [request responseEncoding];
NSString *string = [[NSString alloc] initWithContentsOfFile:[request downloadDestinationPath] usedEncoding:&encoding error:NULL];
[string release];
NSURL *baseURL = [request url];
xmlInitParser();
xmlDocPtr doc;
if ([request downloadDestinationPath]) {
doc = htmlReadFile([[request downloadDestinationPath] cStringUsingEncoding:NSUTF8StringEncoding], [self encodingNameForStringEncoding:encoding], HTML_PARSE_RECOVER | HTML_PARSE_NONET | HTML_PARSE_NOWARNING | HTML_PARSE_NOERROR);
} else {
NSData *data = [request responseData];
doc = htmlReadMemory([data bytes], (int)[data length], "", [self encodingNameForStringEncoding:encoding], HTML_PARSE_RECOVER | HTML_PARSE_NONET | HTML_PARSE_NOWARNING | HTML_PARSE_NOERROR);
}
if (doc == NULL) {
[super parseDataForRequest:request error:error];
return YES;
}
// Create xpath evaluation context
xmlXPathContextPtr xpathCtx = xmlXPathNewContext(doc);
if(xpathCtx == NULL) {
if (error) {
*error = [NSError errorWithDomain:NetworkRequestErrorDomain code:101 userInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"Error: unable to create new XPath context",NSLocalizedDescriptionKey,nil]];
}
return NO;
}
// Evaluate xpath expression
xmlXPathObjectPtr xpathObj = xmlXPathEvalExpression(xpathExpr, xpathCtx);
if(xpathObj == NULL) {
xmlXPathFreeContext(xpathCtx);
if (error) {
*error = [NSError errorWithDomain:NetworkRequestErrorDomain code:101 userInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"Error: unable to evaluate XPath expression!",NSLocalizedDescriptionKey,nil]];
}
return NO;
}
// Now loop through our matches
xmlNodeSetPtr nodes = xpathObj->nodesetval;
int size = (nodes) ? nodes->nodeNr : 0;
int i;
for(i = size - 1; i >= 0; i--) {
assert(nodes->nodeTab[i]);
NSString *parentName = [NSString stringWithCString:(char *)nodes->nodeTab[i]->parent->name encoding:encoding];
NSString *nodeName = [NSString stringWithCString:(char *)nodes->nodeTab[i]->name encoding:encoding];
xmlChar *nodeValue = xmlNodeGetContent(nodes->nodeTab[i]);
NSString *value = [NSString stringWithCString:(char *)nodeValue encoding:encoding];
xmlFree(nodeValue);
// Here we add a <base> element to the header to make the end result play better with javascript
// (UIWebView seemed to ignore the Content-Base http header when I tried)
if ([[nodeName lowercaseString] isEqualToString:@"head"]) {
xmlNodePtr node = xmlNewNode(NULL, (xmlChar *)"base");
xmlNewProp(node, (xmlChar *)"href", (xmlChar *)[[baseURL absoluteString] cStringUsingEncoding:encoding]);
node = xmlDocCopyNode(node, doc, 1);
xmlAddChild(nodes->nodeTab[i], node);
// Our xpath query matched all <link> elements, but we're only interested in stylesheets
// We do the work here rather than in the xPath query because the query is case-sensitive, and we want to match on 'stylesheet', 'StyleSHEEt' etc
} else if ([[parentName lowercaseString] isEqualToString:@"link"]) {
xmlChar *relAttribute = xmlGetNoNsProp(nodes->nodeTab[i]->parent,(xmlChar *)"rel");
if (relAttribute) {
NSString *rel = [NSString stringWithCString:(char *)relAttribute encoding:encoding];
xmlFree(relAttribute);
if ([[rel lowercaseString] isEqualToString:@"stylesheet"] || [[rel lowercaseString] isEqualToString:@"alternate stylesheet"]) {
xmlNodeSetContent(nodes->nodeTab[i], (xmlChar *)[[self localURLForURL:value withBaseURL:baseURL] cStringUsingEncoding:encoding]);
}
}
// Parse the content of <style> tags and style attributes to find external image urls or external css files
} else if ([[nodeName lowercaseString] isEqualToString:@"style"]) {
xmlNodeSetContent(nodes->nodeTab[i], (xmlChar *)[[CSSParser replaceURLsInCSSString:value withBaseURL:baseURL] cStringUsingEncoding:encoding]);
// Parse the content of <source src=""> tags (HTML 5 audio + video)
// We explictly disable the download of files with .webm, .ogv and .ogg extensions, since it's highly likely they won't be useful to us
} else if ([[parentName lowercaseString] isEqualToString:@"source"] || [[parentName lowercaseString] isEqualToString:@"audio"]) {
NSString *fileExtension = [[value pathExtension] lowercaseString];
if (![fileExtension isEqualToString:@"ogg"] && ![fileExtension isEqualToString:@"ogv"] && ![fileExtension isEqualToString:@"webm"]) {
xmlNodeSetContent(nodes->nodeTab[i], (xmlChar *)[[self localURLForURL:value withBaseURL:baseURL] cStringUsingEncoding:encoding]);
}
// For all other elements matched by our xpath query (except hyperlinks), add the content as an external url to fetch
} else if (![[parentName lowercaseString] isEqualToString:@"a"]) {
xmlNodeSetContent(nodes->nodeTab[i], (xmlChar *)[[self localURLForURL:value withBaseURL:baseURL] cStringUsingEncoding:encoding]);
}
if (nodes->nodeTab[i]->type != XML_NAMESPACE_DECL) {
nodes->nodeTab[i] = NULL;
}
}
xmlXPathFreeObject(xpathObj);
xmlXPathFreeContext(xpathCtx);
// We'll use the xmlsave API so we can strip the xml declaration
xmlSaveCtxtPtr saveContext;
if ([request downloadDestinationPath]) {
// Truncate the file first
NSFileManager *fileManager = [[[NSFileManager alloc] init] autorelease];
[fileManager createFileAtPath:[request downloadDestinationPath] contents:nil attributes:nil];
saveContext = xmlSaveToFd([[NSFileHandle fileHandleForWritingAtPath:[request downloadDestinationPath]] fileDescriptor],[self encodingNameForStringEncoding:NSUTF8StringEncoding],2|8); // 2 == XML_SAVE_NO_DECL, this isn't declared on Mac OS 10.5
xmlSaveDoc(saveContext, doc);
xmlSaveClose(saveContext);
} else {
#if TARGET_OS_MAC && MAC_OS_X_VERSION_MAX_ALLOWED <= __MAC_10_5
// xmlSaveToBuffer() is not implemented in the 10.5 version of libxml
NSString *tempPath = [NSTemporaryDirectory() stringByAppendingPathComponent:[[NSProcessInfo processInfo] globallyUniqueString]];
[[[[NSFileManager alloc] init] autorelease] createFileAtPath:tempPath contents:nil attributes:nil];
saveContext = xmlSaveToFd([[NSFileHandle fileHandleForWritingAtPath:tempPath] fileDescriptor],[self encodingNameForStringEncoding:NSUTF8StringEncoding],2|8); // 2 == XML_SAVE_NO_DECL, this isn't declared on Mac OS 10.5
xmlSaveDoc(saveContext, doc);
xmlSaveClose(saveContext);
[request setRawResponseData:[NSMutableData dataWithContentsOfFile:tempPath]];
#else
xmlBufferPtr buffer = xmlBufferCreate();
saveContext = xmlSaveToBuffer(buffer,[self encodingNameForStringEncoding:NSUTF8StringEncoding],2|8); // 2 == XML_SAVE_NO_DECL, this isn't declared on Mac OS 10.5
xmlSaveDoc(saveContext, doc);
xmlSaveClose(saveContext);
[request setRawResponseData:[[[NSMutableData alloc] initWithBytes:buffer->content length:buffer->use] autorelease]];
xmlBufferFree(buffer);
#endif
}
NSString *contentType = [[[request responseHeaders] objectForKey:@"Content-Type"] lowercaseString];
contentType = [[contentType componentsSeparatedByString:@";"] objectAtIndex:0];
if (!contentType) {
contentType = @"text/html";
}
[[request responseHeaders] setValue:[NSString stringWithFormat:@"%@; charset=utf-8"] forKey:@"Content-Type"];
[request setResponseEncoding:NSUTF8StringEncoding];
xmlFreeDoc(doc);
doc = nil;
[super parseDataForRequest:request error:error];
return YES;
}
2 番目のビューでは、ロード後にキャッシュされる webView をロードします。これを取得するために、このプロジェクトを使用しました : https://github.com/pokeb/ProxyingUIWebView 別のデバイスでテストしようとしましたが、同じクラッシュが発生しました。これは、セカンダリ ビュー コントローラーにあるものです。
-(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
NSString *urlString = [NSString stringWithFormat:@"%@", request.URL];
NSBundle *mainBundle = [NSBundle mainBundle];
NSString *baseUrl = [mainBundle objectForInfoDictionaryKey:@"testUrl"];
if ([urlString rangeOfString:baseUrl].location != NSNotFound) //Check if URL is in-app.
{
NSURLRequest *testRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://127.0.0.1:8080/?url=http.somelink.net"]];
NSString *requestUrlString = [NSString stringWithFormat:@"%@",request.URL];
NSString *testUrlString = [NSString stringWithFormat:@"%@",testRequest.URL];
if ([requestUrlString isEqualToString:testUrlString]) //First view load
{
return YES;
}
if (navigationType == UIWebViewNavigationTypeLinkClicked ||
navigationType == UIWebViewNavigationTypeFormSubmitted ||
navigationType == UIWebViewNavigationTypeFormResubmitted ||
navigationType == UIWebViewNavigationTypeReload ||
navigationType == UIWebViewNavigationTypeOther)
{
if ([requestUrlString rangeOfString:@"Id="].location != NSNotFound) //Navigate to
{ //secondary view.
SecondaryTopTenSwapsViewController *secondaryController = [[SecondaryTopTenSwapsViewController alloc] init];
secondaryController.urlRequest = request;
[self.navigationController pushViewController:secondaryController animated:YES];
}
return NO;
}
return YES;
}
else //Not in-app URL. Check if user wants to leave application and open Safari.
{
UIAlertView *leaveApplicationAlert = [[UIAlertView alloc] initWithTitle:@"Open link?" message:@"Are you sure you want to exit the application and open the link in Safari?" delegate:self cancelButtonTitle:@"NO" otherButtonTitles:@"YES", nil];
leaveApplicationAlert.tag = 1;
[leaveApplicationAlert show];
externalUrl = request.URL;
return NO;
}
}
また、セカンダリView Controllerで直後にクラッシュすることがわかりました
-(void)webViewDidStartLoad:(UIWebView *)webView
また、メモリの警告を受け取った場合、ルート ビュー コントローラにポップしてすべてのサブビューを解放するなど、メモリの問題である可能性はありません。