Câu trả lời:
Các cấu trúc trong Swift được truyền theo giá trị, nhưng bạn có thể sử dụng công cụ inout
sửa đổi để sửa đổi mảng của mình (xem câu trả lời bên dưới). Các lớp học được thông qua tham khảo. Array
và Dictionary
trong Swift được thực hiện như các cấu trúc.
NSArray
bởi vì NSArray
và mảng Swift có sự khác biệt về ngữ nghĩa tinh tế (như kiểu tham chiếu) và điều đó có thể dẫn bạn đến nhiều lỗi hơn.
inout
với Structs?
Đối với toán tử tham số hàm chúng ta sử dụng:
let (đó là toán tử mặc định, vì vậy chúng ta có thể bỏ qua let ) để tạo một tham số không đổi (điều đó có nghĩa là chúng ta không thể sửa đổi ngay cả bản sao cục bộ);
var để làm cho nó biến (chúng ta có thể sửa đổi nó cục bộ, nhưng nó sẽ không ảnh hưởng đến biến bên ngoài đã được truyền cho hàm); và
inout để làm cho nó một tham số vào ra. Trong thực tế có nghĩa là vượt qua biến bằng tham chiếu, không phải theo giá trị. Và nó không chỉ đòi hỏi phải chấp nhận giá trị bằng tham chiếu, mà còn phải vượt qua nó bằng tham chiếu, vì vậy hãy chuyển nó bằng & - foo(&myVar)
thay vì chỉfoo(myVar)
Vì vậy, làm điều đó như thế này:
var arr = [1, 2, 3]
func addItem(inout localArr: [Int]) {
localArr.append(4)
}
addItem(&arr)
println(arr) // it will print [1, 2, 3, 4]
Nói chính xác, nó không chỉ là một tham chiếu, mà còn là bí danh thực sự cho biến ngoài, vì vậy bạn có thể thực hiện một mẹo như vậy với bất kỳ loại biến nào, ví dụ với số nguyên (bạn có thể gán giá trị mới cho nó), mặc dù nó có thể không phải là một thực hành tốt và có thể gây nhầm lẫn khi sửa đổi các loại dữ liệu nguyên thủy như thế này.
inout
vị trí đã thay đổi, tức làfunc addItem(localArr: inout [Int])
var
không còn có sẵn cho thuộc tính tham số chức năng.
Xác định cho mình một giao diện BoxedArray<T>
thực hiện Array
giao diện nhưng ủy thác tất cả các chức năng cho một thuộc tính được lưu trữ. Như vậy
class BoxedArray<T> : MutableCollection, Reflectable, ... {
var array : Array<T>
// ...
subscript (index: Int) -> T {
get { return array[index] }
set(newValue) { array[index] = newValue }
}
}
Sử dụng BoxedArray
bất cứ nơi nào bạn sử dụng một Array
. Việc gán một BoxedArray
sẽ theo tham chiếu, nó là một lớp và do đó thay đổi đối với thuộc tính được lưu trữ, thông qua Array
giao diện, sẽ hiển thị cho tất cả các tham chiếu.
String
là một kiểu con của Any
NHƯNG nếu import Foundation
sau đó bạn String
trở thành một kiểu con của AnyObject
.
Đối với phiên bản Swift 3-4 (XCode 8-9), hãy sử dụng
var arr = [1, 2, 3]
func addItem(_ localArr: inout [Int]) {
localArr.append(4)
}
addItem(&arr)
print(arr)
Cái gì đó như
var a : Int[] = []
func test(inout b : Int[]) {
b += [1,2,3,4,5]
}
test(&a)
println(a)
???
func test(b: inout [Int])
... có lẽ đây là một cú pháp cũ; Tôi chỉ tham gia Swift vào năm 2016 và câu trả lời này là từ năm 2014 vì vậy có lẽ mọi thứ đã khác đi?
Một lựa chọn khác là để người tiêu dùng của mảng yêu cầu chủ sở hữu cho nó khi cần thiết. Ví dụ, một cái gì đó dọc theo dòng:
class Account {
var chats : [String]!
var chatsViewController : ChatsViewController!
func InitViewController() {
chatsViewController.getChats = { return self.chats }
}
}
class ChatsViewController {
var getChats: (() -> ([String]))!
func doSomethingWithChats() {
let chats = getChats()
// use it as needed
}
}
Sau đó, bạn có thể sửa đổi mảng bao nhiêu tùy thích trong lớp Tài khoản. Lưu ý rằng điều này không giúp ích gì cho bạn nếu bạn cũng muốn sửa đổi mảng từ lớp trình điều khiển xem.
Sử dụng inout
là một giải pháp nhưng tôi cảm thấy không hợp lý vì mảng là loại giá trị. Về mặt phong cách, cá nhân tôi thích trả lại một bản sao đột biến:
func doSomething(to arr: [Int]) -> [Int] {
var arr = arr
arr.append(3) // or likely some more complex operation
return arr
}
var ids = [1, 2]
ids = doSomething(to: ids)
print(ids) // [1,2,3]
inout
là tốt hơn vì nó tiết kiệm pin. Tôi muốn nói rằng tính dễ đọc, tính bất biến và độ an toàn của luồng của giải pháp này là tốt hơn và chỉ nên sử dụng như là một tối ưu hóa trong những trường hợp hiếm hoi trong trường hợp sử dụng bảo đảm nó.
sử dụng a NSMutableArray
hoặc a NSArray
, đó là các lớp
bằng cách này, bạn không cần phải thực hiện bất kỳ trình bao bọc nào và có thể sử dụng bản dựng trong bắc cầu
open class NSArray : NSObject, NSCopying, NSMutableCopying, NSSecureCoding, NSFastEnumeration
account
một biến toàn cục và xác định thuộcchats
tínhChatsViewController
là :var chats: [Chat] { return account.chats }
.