NSURL - 没有可变子类,所以不需要“复制”作为属性?

时间:2012-12-21 02:54:13

标签: objective-c foundation

@interface SomeClass : NSObject

@property (copy,   nonatomic) NSString *usefulString;
@property (strong, nonatomic) NSString *dangerousString;

@property (copy,   nonatomic) NSURL *curiousURLOne;
@property (strong, nonatomic) NSURL *curiousURLTwo;

@end

在上面的课程中,dangerousString被认为是一个坏主意,因为NSMutableString继承自NSString。这意味着您的类的用户可以将可变字符串设置为dangerousString,然后在SomeClass的实例下面更改可变字符串的值。属性usefulString没有这种危险,因为它将值复制到一个新的(不可变的)字符串对象中。

然而,似乎NSURL(以及任何其他基础类没有可变对应物 - 例如NSNumber),属性声明的复制语义是不必要的。 NSURL确实符合NSCopying的copyWithZone: (...但是我不得不怀疑它是不是只返回保留计数增加的同一个对象 - 为什么还要做其他事情?)

为什么要将属性声明为copy且没有变异的危险?

2 个答案:

答案 0 :(得分:9)

使用iOS7你可以使用NSURLComponents,现在它非常简单,看看这个例子:

NSString *urlString = @"https://mail.google.com/mail/u/0/?shva=1#inbox";
NSURLComponents *components = [[NSURLComponents alloc] initWithString:urlString];

NSLog(@"%@ - %@ - %@ - %@", components.scheme, components.host, components.query, components.fragment);



NSURLComponents *components = [NSURLComponents new];
[components setScheme:@"https"];
[components setHost:@"mail.google.com"];
[components setQuery:@"shva=1"];
[components setFragment:@"inbox"];
[components setPath:@"/mail/u/0/"];

[webview loadRequest:[[NSURLRequest alloc] initWithURL:[components URL]]];

答案 1 :(得分:6)

Apple不提供可变子类这一事实并不意味着恶意用户无法专门构建一个欺骗您的类。如果你假设字符串可以在你的班级后面改变,你需要至少考虑到一个恶意的用户可能会将NSURL扩展到一个可变类:

@interface TrickThemURL : NSURL
    // override key properties, such as baseURL and host, to be mutable
@end

如果程序员给你一个TrickThemURL的对象而你在验证之前没有复制它,那么程序员现在可以自由地更改URL而不让你的班级知道。