不幸的是,我沒有看到任何明顯的代碼片斷本身,這會導致崩潰。在這個答案的最後,我提供了一個我已經完成的代碼示例,所以也許你可以交叉引用它來反對你的。
一對夫婦的想法:
你說這個工程上快速連接,但不慢的連接。這是從主線程運行同步查詢的症狀。如果您意外地從主隊列中進行此同步調用,則在較慢的連接上,看門狗進程可能會終止您的應用程序。只要主線程沒有響應,它就會這樣做。
因此,使用異步調用(如您在其他問題中追求的那樣)或確保這發生在後臺隊列中。
順便說一句,你說你使用performSelectorInBackground
提交到後臺線程。現在大多數人會使用GCD或NSOperationQueue
。請參閱Concurrency Programming Guide。
一般來說,如果有例外,我會問你檢查你的一些變量:
坦率地說,如果這個正在快速連接,而不是緩慢的,問題是不太可能在這些變量的基本設置,而不管你是他們在其他地方異步更新(不是同步線程編程指南的Synchronization部分中的更新或通過Eliminating Lock-Based Code的併發編程指南)中的隊列更新。編寫線程安全代碼時,需要注意同步更改,並且在某些情況下,連接的速度可能會影響行爲。
如果這兩點不能解決您的問題,那麼我們真的需要深入研究您的例外。不用說,只要你發佈有關異常的任何問題,你必須:
告訴我們的例外是
確定引起異常的行什麼;您可以通過
如果你原諒觀察,而我很欣賞你試圖從太多的代碼饒了我們(有時人崗噸無關的代碼,所以感謝節約我們),你一般不會共享不足的代碼。十次中有九次,人們正在遭受的錯誤/異常是由於一些簡單的變量沒有被設置爲您認爲它所具有的(例如未初始化等)。因此,您需要包含稍微更完整的代碼示例,或者您的代碼片段應包含NSLog
,if
或assert
語句,以證明這些值是有效的。
例如,您可能希望在
if ([NSThread isMainThread])
{
NSLog(@"%s: should not be on main thread!!!", __FUNCTION__);
}
這扔可以保證自己這是在後臺線程上運行。您可能還想在登錄時登錄Obj1.thumbImage
和postBody
。 (a)發佈一些簡單的代碼,(b)告訴我們它正在崩潰在這個片段的某處(但不是確切的地方)和(c)向我們保證值傳遞給非常簡單的代碼片段都是有效的(儘管代碼片段沒有說明)。簡單的現實,通常不是所有這三個條件在同一時間都是真實的。當人們發佈崩潰時,問題就像在代碼本身傳遞給違規代碼的變量一樣。
幾個不相關的要點:
順便說一句,在你sendSynchronousRequest
,你爲error
指定nil
。如果API爲您提供診斷錯誤成功或失敗的機會,那麼您應該利用這一點。
使用UIImageJPEGRepresentation
確實是數據丟失嚴重的最壞情況。如果可能的話,回到UIImage
的來源(它是如何創建的?NSData
?)。如果你不能這樣做,可能會考慮UIImagePNGRepresentation
,因爲它仍然具有壓縮功能,但數據丟失較少。有時候你必須做UIImageJPEGRepresentation
,但認爲它是最後的手段。
如果你的服務器只返回「成功」文本字符串,那麼我想這就是你所能做的。如果可能的話,最好是如果你可以編程你的服務器返回一個JSON響應,你可以很容易地使用/解析不同類型的錯誤/響應的不同返回碼。
不管怎麼說,這是一個工作的上傳程序:
- (void)viewDidLoad
{
[super viewDidLoad];
// [self performSelectorInBackground:@selector(upload) withObject:nil];
NSURL *url = [NSURL URLWithString:@"http://my.url.com/upload.php"];
NSString *path = [[NSBundle mainBundle] pathForResource:@"myimage" ofType:@"jpg"]; // note, I'm going back to bundle, not grabbing `UIImage` from imageview
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[self uploadFileAtPath:path
forField:@"file"
URL:url
parameters:nil];
});
}
- (NSString *)generateBoundaryString
{
// generate boundary string
//
// adapted from http://developer.apple.com/library/ios/#samplecode/SimpleURLConnections
//
// Note in iOS 6 and later, you can just:
//
// return [NSString stringWithFormat:@"Boundary-%@", [[NSUUID UUID] UUIDString]];
CFUUIDRef uuid;
NSString *uuidStr;
uuid = CFUUIDCreate(NULL);
assert(uuid != NULL);
uuidStr = CFBridgingRelease(CFUUIDCreateString(NULL, uuid));
assert(uuidStr != NULL);
CFRelease(uuid);
return [NSString stringWithFormat:@"Boundary-%@", uuidStr];
}
- (NSString *)mimeTypeForPath:(NSString *)path
{
// Get a mime type for an extension using MobileCoreServices.framework.
//
// You could hard code this instead, but I like using MobileCoreServices as
// it increases my code reuse possibilities in the future.
CFStringRef extension = (__bridge CFStringRef)[path pathExtension];
CFStringRef UTI = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, extension, NULL);
assert(UTI != NULL);
NSString *mimetype = CFBridgingRelease(UTTypeCopyPreferredTagWithClass(UTI, kUTTagClassMIMEType));
assert(mimetype != NULL);
CFRelease(UTI);
return mimetype;
}
- (void)uploadFileAtPath:(NSString *)imagePath
forField:(NSString *)fieldName
URL:(NSURL*)url
parameters:(NSDictionary *)parameters
{
NSString *filename = [imagePath lastPathComponent];
NSData *imageData = [NSData dataWithContentsOfFile:imagePath];
NSMutableData *httpBody = [NSMutableData data];
NSString *boundary = [self generateBoundaryString];
NSString *mimetype = [self mimeTypeForPath:imagePath];
// configure the request
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];
[request setCachePolicy:NSURLRequestReloadIgnoringLocalCacheData];
[request setHTTPShouldHandleCookies:NO];
[request setTimeoutInterval:30];
[request setHTTPMethod:@"POST"];
// set content type
NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@", boundary];
[request setValue:contentType forHTTPHeaderField: @"Content-Type"];
// add params (all params are strings)
[parameters enumerateKeysAndObjectsUsingBlock:^(NSString *parameterKey, NSString *parameterValue, BOOL *stop) {
[httpBody appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[httpBody appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"\r\n\r\n", parameterKey] dataUsingEncoding:NSUTF8StringEncoding]];
[httpBody appendData:[[NSString stringWithFormat:@"%@\r\n", parameterValue] dataUsingEncoding:NSUTF8StringEncoding]];
}];
// add image data
if (imageData) {
[httpBody appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[httpBody appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"; filename=\"%@\"\r\n", fieldName, filename] dataUsingEncoding:NSUTF8StringEncoding]];
[httpBody appendData:[[NSString stringWithFormat:@"Content-Type: %@\r\n\r\n", mimetype] dataUsingEncoding:NSUTF8StringEncoding]];
[httpBody appendData:imageData];
[httpBody appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
}
[httpBody appendData:[[NSString stringWithFormat:@"--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
// setting the body of the post to the reqeust
[request setHTTPBody:httpBody];
NSError *error;
NSData *returndata = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:&error];
if (error)
{
NSLog(@"error=%@", error);
return;
}
// I generally return JSON response, so this is where I parse it;
// obviously, your validation process will differ.
NSDictionary *results = [NSJSONSerialization JSONObjectWithData:returndata options:0 error:&error];
if (error)
NSLog(@"error=%@", error);
if (results)
NSLog(@"result=%@", results);
}
來源
2013-05-20 17:07:16
Rob
當你崩潰時你會得到什麼錯誤?並在哪條線崩潰? –
我無法得到它,因爲它發生在罕見的情況。這可能是什麼原因呢? – Xcode
你可以在放置斷點時測試它嗎?代碼似乎沒問題,因爲它在這裏顯示。也許你可以在這裏添加更多的代碼可以解決問題。 –