将UIImage转换为二进制,接收EXC_BAD_ACCESS

时间:2014-01-17 21:28:48

标签: ios uiimage

我正在使用https://github.com/IngmarStein/SignatureDemo中的来源向用户提供可以签名的视图。然后我将签名的图像发送到Heroku上运行的服务器。这在模拟器中运行良好。当我在实际设备(iPad)上测试时,该应用程序在此行崩溃:UIImagePNGRepresentation(signature)

处理签名提交的控制器方法: (signatureView是从前面提到的github repo下载的NISignatureView的一个实例)

- (IBAction)submit:(UIButton *)sender {
    @try {
        UIImage *signatureImage = [self.signatureView getSignatureImage];
        if (signatureImage) {
            void (^successBlock)(NSURLRequest *, NSHTTPURLResponse *, id) = ^(NSURLRequest *req, NSHTTPURLResponse *response, id JSON) {
                [self signatureCaptured];
            };
            [self.helper sendSignature:signatureImage total:self.total orderId:self.orderId authToken:self.authToken successBlock:successBlock failureBlock:nil view:self.view];
        } else {
            [self signatureCaptured];
        }
    }
    @catch (NSException *exception) {
        NSLog(@"Exception occurred: %@, %@", exception, [exception userInfo]);
        NSString *msg = [NSString stringWithFormat:@"There was an error capturing the signature. Please try again. \nError: %@", [exception name]];
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Error" message:msg delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil, nil];
        [alert show];
    }
}

NISignatureView的getSignatureImage方法:

- (UIImage *)getSignatureImage {
if (!self.drawnSignature)
    return nil;

CGFloat width = self.frame.size.width;
CGFloat height = self.frame.size.height;
NSInteger myDataLength = width * height * 4;

// allocate array and read pixels into it.
GLubyte *buffer = (GLubyte *) malloc(myDataLength);
glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, buffer);

// gl renders "upside down" so swap top to bottom into new array.
// there's gotta be a better way, but this works.
GLubyte *buffer2 = (GLubyte *) malloc(myDataLength);
for (int y = 0; y < height; y++) {
    for (int x = 0; x < width * 4; x++) {
        buffer2[(((int) height - 1) - y) * (int) width * 4 + x] = buffer[y * 4 * (int) width + x];
    }
}

// make data provider with data.
CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, buffer2, myDataLength, NULL);

// prep the ingredients
int bitsPerComponent = 8;
int bitsPerPixel = 32;
int bytesPerRow = 4 * width;
CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault;
CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault;

// make the cgimage
CGImageRef imageRef = CGImageCreate(width, height, bitsPerComponent, bitsPerPixel, bytesPerRow, colorSpaceRef, bitmapInfo, provider, NULL, NO, renderingIntent);

// then make the uiimage from that
UIImage *myImage = [[UIImage alloc] initWithCGImage:imageRef];

// release memory
CGImageRelease(imageRef);
CGColorSpaceRelease(colorSpaceRef);
CGDataProviderRelease(provider);
free(buffer);
free(buffer2);

return myImage;

}

从控制器调用的助手:

- (void)sendSignature:(UIImage *)signature total:(NSNumber *)total orderId:(NSNumber *)orderId authToken:(NSString *)authToken successBlock:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, id JSON))successBlock failureBlock:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON))failureBlock view:(UIView *)view {
    NSData *imageData = UIImagePNGRepresentation(signature);
    MBProgressHUD *submit = [MBProgressHUD showHUDAddedTo:view animated:YES];
    submit.labelText = @"Saving";
    [submit show:NO];
    NSString *url = [NSString stringWithFormat:@"%@?%@=%@", [NSString stringWithFormat:kDBCAPTURESIG([orderId intValue])], kAuthToken, authToken];
    AFHTTPClient *client = [[AFHTTPClient alloc] initWithBaseURL:[NSURL URLWithString:url]];
    [client setParameterEncoding:AFJSONParameterEncoding];
    NSDictionary *parameters = @{@"total" : total};
    NSMutableURLRequest *request = [client multipartFormRequestWithMethod:@"POST" path:@"" parameters:parameters constructingBodyWithBlock:^(id <AFMultipartFormData> formData) {
        [formData appendPartWithFileData:imageData name:@"signature" fileName:@"signature" mimeType:@"image/png"];
    }];
    AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request
                                                                                        success:^(NSURLRequest *req, NSHTTPURLResponse *response, id json) {
                                                                                            [submit hide:NO];
                                                                                            if (successBlock) successBlock(req, response, json);
                                                                                        } failure:^(NSURLRequest *req, NSHTTPURLResponse *response, NSError *error, id json) {
                [submit hide:NO];
                if (failureBlock) failureBlock(req, response, error, json);
                NSInteger statusCode = [[[error userInfo] objectForKey:AFNetworkingOperationFailingURLResponseErrorKey] statusCode];
                NSString *alertMessage = [NSString stringWithFormat:@"There was an error processing this request. Status Code: %d", statusCode];
                [[[UIAlertView alloc] initWithTitle:@"Error!" message:alertMessage delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil] show];
            }];
    [operation start];
}

应用程序在上面帮助程序的NSData *imageData = UIImagePNGRepresentation(signature);处崩溃。来自调试器的快照: enter image description here

更新 该应用程序不会每次都崩溃。崩溃发生在同一条线上,但有时只发生。我已经更新了描述以包含NISignatureView的getSignatureImage方法。某些对象在此方法结束时被释放。我想知道这是否与糟糕的访问错误有关。我很惭愧地说我还不了解释放和保留。 更新2 我在NISignatureView的NISignatureView属性的getSignatureImage中释放或释放了对象。将释放/自由逻辑移动到单独的方法。在我将图像发送到服务器之后调用此方法。这似乎有效。没有遇到过崩溃。但我不知道我在做什么是解决这个问题的正确方法。签名视图是否需要释放这些对象?卸载视图时它们不会自动释放吗?

0 个答案:

没有答案