Why did I use EXC_BAD_ACCESS_EXCEPTION (code = EXC_ARM_DA_ALIGN) when using blocks with ARC?

I am writing an application where I need to send PNG and JPG images to a server. The code for converting a JPEG / PNG image to a Base64 string I wrote as an Obj-C block. But when I tried to add the string returned by the block to NSDictionary , I got code=EXC_ARM_DA_ALIGN . In my project I use ARC. I read a few posts on this ARC problem : EXC_BAD_ACCESS when calling a method from inside a block inside a delegate method So I use copy ! But that did not help me. Before using copy , I got EXC_BAD_EXCEPTION with code = 1 and now with the code in the header. Here is my code:

  __block NSUInteger image_size; //Obj-C block where PNG or JPEG image converts to Base64 string NSString* (^ToBase64)(UIImage* imageToConvert, NSMutableDictionary* metadata) = ^(UIImage* imageToConvert, NSMutableDictionary* metadata) { NSMutableData *rawData = [NSMutableData data]; NSString* encodedImage ; if ([(NSString*)[metadata objectForKey:@"extension"] isEqualToString:@"PNG"]) { [rawData setData:UIImagePNGRepresentation(imageToConvert)]; [Base64 initialize]; encodedImage = [Base64 encode:rawData]; image_size = [rawData length]; } else if ([(NSString*)[metadata objectForKey:@"extension"] isEqualToString:@"JPG"]) { [rawData setData:UIImageJPEGRepresentation(imageToConvert, 1.0)]; [Base64 initialize]; encodedImage = [Base64 encode:rawData]; image_size = [rawData length]; } return encodedImage; } ; //Initialize dictionary with image data and metadata to send int iteration = 0; for (UIImage* currentEntry in imagesToSent) { NSMutableDictionary* currentImageMetadata = (NSMutableDictionary*)[imagesMetadata objectAtIndex:iteration]; [uploadMessage setObject:[[NSMutableDictionary alloc] initWithObjectsAndKeys: [ToBase64(currentEntry,currentImageMetadata) copy],@"image_data", //here I got an exception [currentImageMetadata objectForKey:@"extension"], @"extension", [currentImageMetadata objectForKey:@"image_name" ], @"image_name", image_size, @"size", nil] forKey:[NSString stringWithFormat:@"image%d",iteration]]; iteration++; } 
+6
source share
2 answers

NSDictionary expects its keys and values ​​to be pointers to Objective-C objects. In image_size , you have NSUInteger, which is a primitive type (unsigned long).

So, to save a primitive type value in an NSDictionary, you have to wrap it in NSNumber or NSValue. With newer versions of LLVM, this is a simple expression:

@(image_size) // this will give you an NSNumber *

Or, if you have a senior compiler, then something like this:

[NSNumber numberWithUnsignedLong:image_size]

Hope this helps.

By the way, I'm not sure about using a block in this case. It seems that the motivation was for the __block variable to be equivalent to the out parameter and nothing more? You can only think that it is a separate function or method that takes NSUInteger * as an out parameter. Not a problem here, but something to consider it a bit.

+4
source

It's hard to be absolutely sure, but what you should try is localizing all your variables. Sometimes ARC does not refer to counting for one variable if you use the same variable in several ways. I had a problem like this and I localized all the variables and stopped EXC_BAD_ACCESS. Hope I helped.

-1
source

Source: https://habr.com/ru/post/948857/


All Articles