2011-10-17 14 views
5

Założenie "someData" jest NSMutableData zawierające niektóre bajty danych.Opis initWithBytes dla NSString

jeśli piszę co następuje:

NSString *someString = [NSString string]; 
[someString initWithBytes:[someData mutableBytes] length:[someData length] encoding:NSUTF8StringEncoding]; 

Druga linia daje mi "nierozpoznany selektor wysyłane do instancji" błąd

Ale jeśli piszę:

NSString *someString=[[NSString alloc] initWithBytes:[someData mutableBytes] length:[someData length] encoding:NSUTF8StringEncoding]; 

to działa . Czy istnieje powód, dla którego poprzedni sposób nie działa? Czy można to zrobić bez "przydziału" (uprzednio tworząc someString?)

Dzięki.

+1

Powinieneś przeczytać podstawy "[Język programowania Objective-C] (http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Iproduction/introObjectiveC.html)". – sidyll

+0

Twoje pytanie powinno dotyczyć raczej 'alloc' i' init' niż metody 'NSString'. – Richard

Odpowiedz

4

Powodem jest to, że obiekt zwrócony przez [NSString string] nie reaguje na selektora -initWithBytes:length:encoding:. Dzieje się tak dlatego, że NSString są niezmienne - nie można ich zmienić po ich utworzeniu. Metoda ta wykorzystuje tę metodę i podaje odwołanie do stałego łańcucha (utworzonego podczas kompilacji), który jest pusty.

Co więcej, ale NSString to klaster klasy. Oznacza to, że gdy poprosisz o NSString, możesz uzyskać instancję jednej z jej podklas. Domyślam się, że dostajesz podklasę, która ma -initWithBytes:length:encoding: przesłoniętą, aby rzucić wyjątek, ponieważ nie ma sensu wysyłanie metody init do stałego łańcucha utworzonego podczas kompilacji.

W drugim przypadku podczas uruchamiania programu tworzony jest zupełnie nowy NSString, a następnie wysyłany jest komunikat init. To jest w porządku. Zauważ, że ponieważ jest to klaster klasy, ciąg zwracany przez metodę init może nie być tym samym, który został utworzony przez -alloc.

+0

Myślę, że widzę. Pierwszy przypadek tworzy NSString w czasie kompilacji. Po utworzeniu nie można go ponownie zainicjować. Ten drugi przypadek tworzy obiekt łańcucha w czasie wykonywania i inicjuje go w tej samej linii. Jednak zamiana drugiego wiersza w pierwszym przypadku na [someString init] nie powoduje błędu. Być może jest to problem z klastrami klas. – Dave

3

Pierwszy sposób tworzy pusty, autoodtwarzany ciąg, który został już zainicjowany, a następnie próbuje zainicjować ciąg po raz drugi. Drugi sposób alokuje pamięć, a następnie odpowiednio ją inicjuje. Zauważ, że druga metoda nie autoodtwarzania utworzonego łańcucha, więc zakres wywoływania jest nadal odpowiedzialny. Jeśli chcesz, możesz owinąć drugą drogę w metodzie spożywczym kategorii NSString dostać coś bardziej podobny do pierwszego:

@interface NSString (stringWithBytes) 

+ (NSString*)stringWithBytes:(const void *)bytes length:(NSUInteger)length encoding:(NSStringEncoding)encoding; 

@end 

@implementation NSString (stringWithBytes) 

+ (NSString*)stringWithBytes:(const void *)bytes length:(NSUInteger)length encoding:(NSStringEncoding)encoding { 
    NSString * aString = [[NSString alloc] initWithBytes:bytes length:length encoding:encoding]; 
    return [aString autorelease]; 
} 

@end 
+1

Czy nie powinny to być metody klasowe? – jrturton

+0

Ah, dobry połów. Będę edytować, aby dopasować. Wpisywanie kodu bezpośrednio zamiast wklejania z Xcode zawsze wydaje się powodować brakujące dane. – RPeck

+1

Piszę wiele odpowiedzi na moim _phone_. To cud, że mam jakiegokolwiek przedstawiciela. – jrturton