2012-12-21 31 views
9
@interface SomeClass : NSObject 

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

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

@end 

Trong lớp học trên, dangerousString được coi là ý tưởng tồi bởi vì NSMutableString được kế thừa từ NSString. Có nghĩa là có thể người dùng trong lớp của bạn có thể đặt chuỗi có thể thay đổi thành dangerousString và sau đó thay đổi giá trị của chuỗi có thể thay đổi từ bên dưới phiên bản SomeClass. Thuộc tính usefulString không có nguy cơ này vì nó sao chép giá trị vào một đối tượng chuỗi (không thay đổi) mới.NSURL - Không có phân lớp có thể thay đổi, vì vậy không cần phải "sao chép" dưới dạng thuộc tính?

Tuy nhiên, có vẻ như đối với NSURL (và bất kỳ lớp nền tảng nào khác không có đối tác có thể thay đổi - ví dụ: NSNumber) ngữ nghĩa sao chép của khai báo thuộc tính là không cần thiết. NSURL không phù hợp với NSCopying của copyWithZone:(... nhưng tôi phải tự hỏi, nếu nó không chỉ trả lại đối tượng cùng với một tăng count giữ lại -? Tại sao nó sẽ làm bất cứ điều gì khác)

Tại sao bạn sẽ kê khai tài sản là copy không có nguy cơ bị đột biến?

Trả lời

6

Thực tế là Apple không cung cấp một lớp con có thể thay đổi được không có nghĩa là người dùng độc hại không thể xây dựng một cách cụ thể để lừa lớp của bạn. Nếu bạn vận hành theo giả định rằng chuỗi có thể được thay đổi sau lưng của lớp học của bạn, bạn cần phải có ít nhất cho phép một khả năng của một người sử dụng có ý đồ xấu kéo dài NSURL vào một lớp học có thể thay đổi:

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

Nếu một lập trình viên mang đến cho bạn một đối tượng của TrickThemURL và bạn không sao chép nó trước khi xác thực, lập trình viên đó bây giờ được tự do thay đổi URL mà không cho phép lớp của bạn biết.

+2

Sẽ không TrickThemURL chỉ ghi đè -Copy nếu nó muốn trở thành độc hại? – Darren

+0

@ Darren Tôi đoán bạn đúng - một cách để an toàn là sử dụng '[NSURL urlWithString: urlArg.standardizedURL]' và sau đó xác thực kết quả. – dasblinkenlight

+0

Dựa trên thảo luận này có vẻ như 'strong' là" an toàn ". Điều này mở ra một cơ hội cho một trò chơi mèo và chuột, nhưng điều đó có thể được chấp nhận cho đến khi tính hữu dụng của lớp này vượt ra ngoài giới hạn của một ứng dụng đơn lẻ. – edelaney05

9

Với iOS7 bạn có thể sử dụng NSURLComponents, bây giờ nó rất đơn giản, nhìn ví dụ này:

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]]]; 
+0

Tôi không chắc chắn điều này có liên quan gì đến câu hỏi trên? Có vẻ như bạn chỉ đang hiển thị cách tạo URL bằng NSURLComponents. – codecaffeine

+0

Có, nhưng câu hỏi không hỏi làm thế nào để thay đổi một phần của URL, nó đã hỏi liệu có cần thiết đặt thuộc tính 'NSURL' là 'bản sao' vì nó không thay đổi. – codecaffeine