2013-07-06 12 views
6

Piszę aplikację, w której muszę wysyłać obrazy PNG i JPG na serwer. Kod do przekształcania obrazu JPEG/PNG na ciąg Base64, który napisałem jako blok Obj-C. Ale gdy próbowałem dodać ciąg zwracany przez blok do NSDictionary, otrzymałem code=EXC_ARM_DA_ALIGN. W moim projekcie używam ARC. Czytałem kilka postów dotyczących tego problemu ARC: EXC_BAD_ACCESS when calling a method from inside a block, inside a delegate method Używam więc copy! Ale to mi nie pomogło. Zanim użyję copy, otrzymałem EXC_BAD_EXCEPTION z kodem = 1 i teraz z kodem na tytule. Oto mój kod:Dlaczego otrzymałem EXC_BAD_ACCESS_EXCEPTION (code = EXC_ARM_DA_ALIGN), gdy używam bloków z ARC?

__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++; 
} 
+3

Czy to wszystko dosłownie w jedną metodę? Więc blok jest tworzony lokalnie, zanim go nazwiesz? A może skopiował/wkleił kod z różnych metod? Pamiętaj też, że 'image_size' musi być umieszczony w NSNumber przed dodaniem go do słownika. Z nowym kompilatorem możesz to zrobić za pomocą '@ (image_size)'. –

+0

@FirozeLafeer: To wygląda na odpowiedź na problem! –

+0

@FirozeLafeer ma właściwą odpowiedź – Danilo

Odpowiedz

4

NSDictionary oczekuje, że jego klucze i wartości będą wskazywać obiekty Objective-C. To co masz w image_size jest NSUInteger, który jest typem pierwotnym (unsigned long).

Aby zapisać wartość typu pierwotnego w NSDictionary, należy go zawrzeć w NSNumber lub NSValue. Z nowszymi wersjami LLVM, że jest to łatwe wyrażenie:

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

Lub jeśli masz starszą kompilator wtedy coś takiego:

[NSNumber numberWithUnsignedLong:image_size]

nadzieję, że pomoże.

BTW, nie jestem pewien o użyciu bloku w tym przypadku. Wydaje się, że motywacją była zmienna __block jako odpowiednik parametru out i nic więcej? Możesz rozważyć właśnie zrobienie tej oddzielnej funkcji lub metody, która pobiera NSUInteger * jako parametr wyjściowy. Nie jest to natychmiastowy problem, ale coś, co warto rozważyć, aby trochę to posprzątać.

+0

Tnanks man! Świetna odpowiedź. Naprawdę mi pomogłeś. Czy możesz podać mi referencję, gdzie mogę przeczytać więcej na temat nowej składni boksu: @ (image_size). Nie słyszałem o tym. – MainstreamDeveloper00

+0

@HarryCater, oto dokument dotyczący wyrażeń w ramkach i innych powiązanych zmian: http://clang.llvm.org/docs/ObjectiveCLiterals.html –

-1

Trudno być całkowicie pewien, ale co należy spróbować zrobić jest zlokalizowanie wszystkich zmiennych. Czasami ARC nie odwołuje się do liczby dla jednej zmiennej, jeśli używasz tej samej zmiennej w wielu metodach. Miałem problem podobny do tego jeden raz i zlokalizowałem wszystkie zmienne i zatrzymałem EXC_BAD_ACCESS. Mam nadzieję, że pomogłem.

+2

O czym ty mówisz? Środowisko wykonawcze ObjC modyfikuje wszystko, co można wysłać, zachować i zwolnić, i nie jest "__unsafe_unretained". ARC nie "zapomina zarządzać" niczego rozsądnie zdefiniowanego. Fakt, że czas życia zmiennej był nieoczekiwany, to twoja wina. – CodaFi

Powiązane problemy