不幸的是,我没有看到任何明显的代码片断本身,这会导致崩溃。在这个答案的最后,我提供了一个我已经完成的代码示例,所以也许你可以交叉引用它来反对你的。
一对夫妇的想法:
你说这个工程上快速连接,但不慢的连接。这是从主线程运行同步查询的症状。如果您意外地从主队列中进行此同步调用,则在较慢的连接上,看门狗进程可能会终止您的应用程序。只要主线程没有响应,它就会这样做。
因此,使用异步调用(如您在其他问题中追求的那样)或确保这发生在后台队列中。
顺便说一句,你说你使用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
你可以在放置断点时测试它吗?代码似乎没问题,因为它在这里显示。也许你可以在这里添加更多的代码可以解决问题。 –