Bộ sưu tập bất biến / có thể thay đổi trong Swift


88

Tôi đã tham khảo hướng dẫn lập trình Swift của Apple để hiểu cách tạo các đối tượng Có thể thay đổi / bất biến (Mảng, Từ điển, Bộ, Dữ liệu) bằng ngôn ngữ Swift. Nhưng tôi không thể hiểu cách tạo bộ sưu tập bất biến trong Swift.

Tôi muốn xem các điểm tương đương trong Swift cho phần sau trong Objective-C

Mảng bất biến

NSArray *imArray = [[NSArray alloc]initWithObjects:@"First",@"Second",@"Third",nil];

Mảng có thể thay đổi

NSMutableArray *mArray = [[NSMutableArray alloc]initWithObjects:@"First",@"Second",@"Third",nil];
[mArray addObject:@"Fourth"];

Từ điển bất biến

NSDictionary *imDictionary = [[NSDictionary alloc] initWithObjectsAndKeys:@"Value1", @"Key1", @"Value2", @"Key2", nil];

Từ điển có thể thay đổi

NSMutableDictionary *mDictionary = [[NSMutableDictionary alloc]initWithObjectsAndKeys:@"Value1", @"Key1", @"Value2", @"Key2", nil];
[mDictionary setObject:@"Value3" forKey:@"Key3"];

Câu trả lời:


115

Mảng

Tạo mảng bất biến

Cách đầu tiên:

let array = NSArray(array: ["First","Second","Third"])

Cách thứ hai:

let array = ["First","Second","Third"]

Tạo mảng có thể thay đổi

var array = ["First","Second","Third"]

Nối đối tượng vào mảng

array.append("Forth")


Từ điển

Tạo từ điển bất biến

let dictionary = ["Item 1": "description", "Item 2": "description"]

Tạo từ điển có thể thay đổi

var dictionary = ["Item 1": "description", "Item 2": "description"]

Nối cặp mới vào từ điển

dictionary["Item 3"] = "description"

Thông tin thêm về Nhà phát triển Apple


12
Mảng "độ dài cố định" sẽ chính xác hơn. Nó không phải là bất biến.
Sulthan

1
bất biến Dictionarylà thực sự bất biến (đối diện Array)
Bryan Chen

@BryanChen Oh .. Cảm ơn!
nicael

@BryanChen Yep, tôi quên xóa var.
nicael

2
Đúng vậy. Thông tin thêm về tính bất biến của mảng trong câu hỏi này và câu trả lời của nó .
Matt Gibson

31

Swift không có bất kỳ sự thay thế nào cho NSArrayhoặc các lớp thu thập khác trong Objective-C.

Có các lớp mảng và từ điển, nhưng cần lưu ý đây là các kiểu "giá trị", so với NSArray và NSDictionary là kiểu "đối tượng".

Sự khác biệt là nhỏ nhưng có thể rất quan trọng để tránh lỗi trường hợp cạnh.

Nhanh chóng, bạn tạo một mảng "không thay đổi" với:

let hello = ["a", "b", "c"]

Và một mảng "có thể thay đổi" với:

var hello = ["a", "b", "c"]

Các mảng có thể thay đổi có thể được sửa đổi giống như NSMutableArray:

var myArray = ["a", "b", "c"]

myArray.append("d") // ["a", "b", "c", "d"]

Tuy nhiên, bạn không thể chuyển một mảng có thể thay đổi cho một hàm:

var myArray = ["a", "b", "c"]

func addToArray(myArray: [String]) {
  myArray.append("d") // compile error
}

Nhưng đoạn mã trên không hoạt động với NSMutableArray:

var myArray = ["a", "b", "c"] as NSMutableArray

func addToArray(myArray: NSMutableArray) {
  myArray.addObject("d")
}

addToArray(myArray)

myArray // ["a", "b", "c", "d"]

Bạn có thể đạt được NSMutableArrayhành vi của bằng cách sử dụng một inouttham số phương thức:

var myArray = ["a", "b", "c"]

func addToArray(inout myArray: [String]) {
  myArray.append("d")
}

addToArray(&myArray)

myArray // ["a", "b", "c", "d"]

Đã viết lại câu trả lời này 2015-08-10 để phản ánh hành vi Swift hiện tại.


1
Điều này rõ ràng đã được thay đổi bây giờ. Một mảng hằng giờ thực sự không thay đổi được và một mảng biến hiện thực sự có thể thay đổi được. Chúng được chuyển dưới dạng giá trị , do đó chúng sẽ được sao chép khi được gán cho một biến khác hoặc được chuyển giữa các hàm. Tuy nhiên, điều này không liên quan gì đến tính đột biến hay tính bất biến.
Balthazar

Cũng như tôi đã đề cập trong câu trả lời của mình, việc được chuyển dưới dạng giá trị có liên quan đến khả năng thay đổi / bất biến vì lần duy nhất bạn quan tâm là khi chuyển một mảng sang mã khác (có thể sửa đổi nó).
Abhi Beckert

Nhưng nếu bạn truy cập mảng như một thuộc tính, bạn vẫn có thể sửa đổi nó từ một đối tượng khác. Một trong những lợi ích của mảng không thay đổi là bạn có thể chuyển nó sang một đối tượng khác một cách an toàn mà không cần lo lắng liệu đối tượng kia có thể sửa đổi bản gốc hay không. Mối quan tâm này không tồn tại nữa khi các đối tượng được chuyển dưới dạng giá trị. Vì vậy, các ngữ nghĩa khác nhau yêu cầu thực hành mã hóa khác nhau. CHỈNH SỬA: Bây giờ tôi thấy bạn đã đổi tên bài đăng, vì vậy chúng tôi đồng ý. Tôi đồng ý rằng sự khác biệt là quan trọng để nhận thức về wrt. việc sử dụng các tập hợp có thể thay đổi.
Balthazar

6

Chỉ có một Arrayvà một Dictionarykiểu trong Swift. Khả năng thay đổi phụ thuộc vào cách bạn xây dựng nó:

var mutableArray = [1,2,3]
let immutableArray = [1,2,3]

tức là nếu bạn tạo một phép gán cho một biến thì nó có thể thay đổi được, trong khi nếu bạn tạo một phép gán cho một biến thì không.

CẢNH BÁO: Mảng bất biến không hoàn toàn bất biến! Bạn vẫn có thể thay đổi nội dung của chúng, không chỉ là chiều dài tổng thể của chúng!


1
FYI: hành vi của mảng đang thay đổi trong bản beta sắp tới; Tôi nghĩ rằng tất cả mọi người chất đống trên về điều đó một
russbishop

@xenadu Nguồn? ETA trên bản beta đó?
Tệp tương tự

Xin lỗi, không có nguồn. Nó đến từ một cuộc thảo luận với một trong những thành viên trong nhóm biên dịch. Ông cũng cho biết Beta 2 về cơ bản chỉ là một vài bản sửa lỗi đã được kiểm tra và không có gì liên quan đến phản hồi sau WWDC.
russbishop

5

Chỉ cần khai báo đối tượng hoặc biến (bất kỳ) của bạn với

'let' key word -> for "constan/Immutable" array, dictionary, variable, object..etc.

'var' key word -> for "Mutable" array, dictionary, variable, object..etc. 

Để biết thêm thông tin chi tiết

“Sử dụng let để tạo một hằng số và var để tạo một biến. Giá trị của một hằng số không cần biết tại thời điểm biên dịch, nhưng bạn phải gán giá trị cho nó chính xác một lần. Điều này có nghĩa là bạn có thể sử dụng hằng số để đặt tên cho một giá trị mà bạn xác định một lần nhưng sử dụng ở nhiều nơi. "

var myVariable = 42
myVariable = 50
let myConstant = 42

Đọc “Ngôn ngữ lập trình Swift”.


Trong trường hợp của Array, điều này không hoạt động như mong đợi. stackoverflow.com/a/24319712/623710
macshome

3

Nếu bạn muốn làm việc với Array(Swift) NSArray, bạn có thể sử dụng một hàm cầu nối đơn giản. Thí dụ:

var arr1 : Array = []

arr1.bridgeToObjectiveC().count

Nó hoạt động tương tự cho let.


0

Từ tài liệu của chính Apple:

Khả năng thay đổi của các bộ sưu tập

Nếu bạn tạo một mảng, một tập hợp hoặc một từ điển và gán nó cho một biến, tập hợp được tạo sẽ có thể thay đổi được. Điều này có nghĩa là bạn có thể thay đổi (hoặc thay đổi) bộ sưu tập sau khi nó được tạo bằng cách thêm, xóa hoặc thay đổi các mục trong bộ sưu tập. Ngược lại, nếu bạn gán một mảng, một tập hợp hoặc một từ điển cho một hằng số, thì tập hợp đó là bất biến và không thể thay đổi kích thước và nội dung của nó.

https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/CollectionTypes.html#//apple_ref/doc/uid/TP40014097-CH8-ID105

Các cách sử dụng khác của tập hợp bất biến / có thể thay đổi tùy thuộc vào lý do tại sao bạn muốn chúng có thể thay đổi / bất biến. Bộ sưu tập là các loại giá trị trong Swift, có nghĩa là nội dung của chúng được sao chép khi chúng được gán cho một giá trị khác hoặc được chuyển cho một hàm / phương thức khác. Do đó, bạn không cần phải lo lắng về việc liệu một hàm phương thức nhận có thể thay đổi mảng ban đầu hay không. Vì vậy, bạn không cần đảm bảo trả về một tập hợp bất biến nếu lớp của bạn đang giữ một tập hợp có thể thay đổi, chẳng hạn.


0

[Không thể thay đổi và không thể thay đổi]

Mảng của Swift có thể bị tắt tiếng

[let vs var, Value vs Reference Type]

Tập hợp bất biến [Giới thiệu] - là một cấu trúc tập hợp không thể thay đổi. Có nghĩa là bạn không thể thêm, bớt, sửa đổi sau khi tạo

let + struct(như Array, Set, Dictionary) là phù hợp hơn là bất biến

Có một số lớp (ví dụ NSArray) không cung cấp giao diện để thay đổi trạng thái bên trong

nhưng

class A {
    var value = "a"
}

func testMutability() {
    //given
    let a = A()
    
    let immutableArr1 = NSArray(array: [a])
    let immutableArr2 = [a]
    
    //when
    a.value = "aa"
    
    //then
    XCTAssertEqual("aa", (immutableArr1[0] as! A).value)
    XCTAssertEqual("aa", immutableArr2[0].value)
}   

Nó thà là unmodifiablemảng

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.