假设“someData”是包含一些字节数据的NSMutableData。
如果我写下以下内容:
NSString *someString = [NSString string];
[someString initWithBytes:[someData mutableBytes] length:[someData length] encoding:NSUTF8StringEncoding];
第二行给我一个“无法识别的选择器发送到实例”错误
但如果我写:
NSString *someString=[[NSString alloc] initWithBytes:[someData mutableBytes] length:[someData length] encoding:NSUTF8StringEncoding];
然后它的工作原理。前一种方式不起作用是有原因的吗?可以在没有“alloc”的情况下完成(事先创建someString吗?)
感谢。
答案 0 :(得分:4)
原因是[NSString string]
返回的对象不响应选择器-initWithBytes:length:encoding:
。这是因为NSString是不可变的 - 一旦创建它们就无法更改。方法-string
利用了这一点,只是为您提供了一个空的字符串(在编译时创建)的引用。
不仅如此,NSString也是一个类集群。这意味着当您要求NSString时,您实际上可能会获得其子类之一的实例。我的猜测是你得到一个被-initWithBytes:length:encoding:
重写的子类来抛出异常,因为将init方法发送到编译时创建的常量字符串是没有意义的。
在第二种情况下,您将在运行时创建一个全新的NSString,然后向其发送一条初始消息。这很好。请注意,因为它是一个类集群,所以init方法返回的字符串可能与-alloc
创建的字符串不同。
答案 1 :(得分:3)
第一种方法是创建一个已经初始化的空的自动释放字符串,然后尝试再次初始化字符串。第二种方式分配内存,然后适当地初始化它。请注意,第二种方法不会自动释放创建的字符串,因此调用范围仍然是负责的。如果你愿意,你可以在一个NSString类别的方便方法中包含第二种方式,以获得与第一种类似的东西:
@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