Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

I'm writing an application where I need to send PNG and JPG images to the server. Code for transforming JPEG/PNG image to Base64 string I wrote as Obj-C block. But when I tried to add string returned by block to NSDictionary I got code=EXC_ARM_DA_ALIGN. In my project I use ARC. I read several posts on this problem ARC: EXC_BAD_ACCESS when calling a method from inside a block, inside a delegate method So I use copy! But It didn't help me.Before I use copy I got EXC_BAD_EXCEPTION with code=1 and now with code on the title. 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++;
}
like image 600
MainstreamDeveloper00 Avatar asked Jul 06 '13 18:07

MainstreamDeveloper00


1 Answers

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

So in order to store a value of a primitive type in an NSDictionary you have to wrap it in an NSNumber or NSValue. With newer versions of LLVM, that's an easy expression:

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

Or if you have an older compiler then something like this:

[NSNumber numberWithUnsignedLong:image_size]

By the way, I'm not sure about the use of a block in this case. It seems the motivation was to have a __block variable as the equivalent of an out parameter and nothing more? You might consider just making that a separate function or method which takes a NSUInteger * as an out parameter. Not the immediate issue here, but something to consider to clean this up a bit.

like image 143
Firoze Lafeer Avatar answered Sep 19 '22 00:09

Firoze Lafeer