Làm cách nào để chuyển đổi NSMutableArray thành NSArray trong mục tiêu-c?
NSArray *array = mutableArray;
Làm cách nào để chuyển đổi NSMutableArray thành NSArray trong mục tiêu-c?
NSArray *array = mutableArray;
Câu trả lời:
NSArray *array = [mutableArray copy];
Copy
làm bản sao bất biến. Điều này khá hữu ích vì Apple có thể thực hiện các tối ưu hóa khác nhau. Ví dụ gửi copy
đến một mảng bất biến chỉ giữ lại đối tượng và trả về self
.
Nếu bạn không sử dụng bộ sưu tập rác hoặc ARC, hãy nhớ rằng -copy
vẫn giữ đối tượng.
copy
tạo ra NSArray bình thường chứ không phải NSMutableArray?
NSArray
& NSMutableArray
, NSString
& NSMutableString
. Nhưng không phải ví dụ NSViewController
luôn chứa trạng thái đột biến.
An NSMutableArray
là một lớp con của NSArray
vì vậy bạn sẽ không cần phải chuyển đổi nhưng nếu bạn muốn đảm bảo rằng mảng không thể được sửa đổi, bạn có thể tạo một NSArray
trong hai cách sau tùy thuộc vào việc bạn có muốn tự động phát hành hay không:
/* Not autoreleased */
NSArray *array = [[NSArray alloc] initWithArray:mutableArray];
/* Autoreleased array */
NSArray *array = [NSArray arrayWithArray:mutableArray];
EDIT: Giải pháp được cung cấp bởi Georg Schölly là một cách tốt hơn để làm điều đó và sạch sẽ hơn rất nhiều, đặc biệt là bây giờ chúng tôi có ARC và thậm chí không phải gọi autorelease.
Tôi thích cả hai giải pháp chính:
NSArray *array = [NSArray arrayWithArray:mutableArray];
Hoặc là
NSArray *array = [mutableArray copy];
Sự khác biệt chính mà tôi thấy ở họ là cách họ cư xử khi mutableArray là con số không :
NSMutableArray *mutableArray = nil;
NSArray *array = [NSArray arrayWithArray:mutableArray];
// array == @[] (empty array)
NSMutableArray *mutableArray = nil;
NSArray *array = [mutableArray copy];
// array == nil
[mutableArray copy]
có thể được đơn giản hóa thành [nil copy]
. Trong object-c, bất kỳ thông điệp nào được gửi đến nil sẽ luôn là nil. Điều quan trọng cần nhớ là phân biệt giữa "không có gì" và "một mảng không có gì trong đó".
bạn thử mã này ---
NSMutableArray *myMutableArray = [myArray mutableCopy];
và
NSArray *myArray = [myMutableArray copy];
Dưới đây là cách để chuyển đổi NSMutableArray sang NSArray:
//oldArray is having NSMutableArray data-type.
//Using Init with Array method.
NSArray *newArray1 = [[NSArray alloc]initWithArray:oldArray];
//Make copy of array
NSArray *newArray2 = [oldArray copy];
//Make mutablecopy of array
NSArray *newArray3 = [oldArray mutableCopy];
//Directly stored NSMutableArray to NSArray.
NSArray *newArray4 = oldArray;
Trong Swift 3.0 có kiểu dữ liệu mới Array . Khai báo Array bằng let
từ khóa thì nó sẽ trở thành NSArray Và nếu khai báo sử dụng var
từ khóa thì nó sẽ trở thành NSMutableArray .
Mã mẫu:
let newArray = oldArray as Array
Trong mục tiêu-c:
NSArray *myArray = [myMutableArray copy];
Trong nhanh chóng:
var arr = myMutableArray as NSArray
NSArray *array = mutableArray;
Đây [mutableArray copy]
antipattern là khắp nơi trên mẫu mã. Dừng làm như vậy cho các mảng có thể thay đổi được tạm thời và được giải quyết ở cuối phạm vi hiện tại.
Không có cách nào thời gian chạy có thể tối ưu hóa việc sao chép lãng phí của một mảng có thể thay đổi sắp ra khỏi phạm vi, bị giải mã thành 0 và bị loại bỏ hoàn toàn.
NSMutableArray
cho một NSArray
biến sẽ không làm thay đổi nó (đó là câu hỏi của OP). Việc phơi bày một giá trị như vậy (ví dụ như giá trị trả về hoặc là một tài sản) có thể dẫn đến các vấn đề rất khó gỡ lỗi nếu giá trị đó bị thay đổi bất ngờ. Điều này áp dụng cho cả đột biến bên trong và bên ngoài do giá trị đột biến được chia sẻ.
NSMutableArray
biến là đủ. Vì đối tượng không bao giờ ngừng là một mảng có thể thay đổi, nên gọi các phương thức đột biến trên nó sẽ thành công và làm thay đổi dữ liệu chia sẻ. Mặt khác, mảng có thể thay đổi ban đầu đã được sao chép, thay đổi nó thành một mảng bất biến, sau đó được gán cho một NSMutableArray
biến và có các phương thức biến đổi được gọi trên đó, các cuộc gọi đó sẽ thất bại doesNotRespondToSelector
vì lỗi đã nhận được cuộc gọi phương thức đột biến thực tế bất biến và không đáp ứng với các phương pháp đó.
Nếu bạn đang xây dựng một mảng thông qua khả năng biến đổi và sau đó muốn trả về một phiên bản không thay đổi, bạn có thể chỉ cần trả về mảng có thể thay đổi dưới dạng "NSArray" thông qua kế thừa.
- (NSArray *)arrayOfStrings {
NSMutableArray *mutableArray = [NSMutableArray array];
mutableArray[0] = @"foo";
mutableArray[1] = @"bar";
return mutableArray;
}
Nếu bạn "tin tưởng" người gọi để coi đối tượng trả về (về mặt kỹ thuật vẫn có thể thay đổi) như một NSArray bất biến, thì đây là một lựa chọn rẻ hơn [mutableArray copy]
.
Để xác định xem nó có thể thay đổi một đối tượng đã nhận hay không, người nhận tin nhắn phải dựa vào loại chính thức của giá trị trả về. Nếu nó nhận được, ví dụ, một đối tượng mảng được gõ là bất biến, thì nó không nên cố gắng biến đổi nó . Nó không phải là một thực tiễn lập trình có thể chấp nhận để xác định xem một đối tượng có thể thay đổi được hay không dựa trên tư cách thành viên của lớp.
Thực hành trên được thảo luận chi tiết hơn ở đây:
Cách thực hành tốt nhất: Trả về mutableArray.copy hoặc mutableArray nếu kiểu trả về là NSArray
Tôi đã tìm kiếm câu trả lời trong swift 3 và câu hỏi này đã được hiển thị như là kết quả đầu tiên trong tìm kiếm và tôi lấy cảm hứng từ câu trả lời từ đó vì vậy đây là mã 3 swift
let array: [String] = nsMutableArrayObject.copy() as! [String]
NSArray *array = [mutableArray copy];