了解NSString的initWithBytes

时间:2011-10-17 15:06:32

标签: objective-c

假设“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吗?)

感谢。

2 个答案:

答案 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