Small knowledge, big challenge! This paper is participating in theEssentials for programmers”Creative activities
Abstract
IOS development, especially the conversion from OC to Swift, requires a new understanding of Array, what attributes Swift retains, what attributes are added, and what memory storage is, etc. After understanding these, the use of Array can be more in line with the thoughts of Swift and convenient for myself.
Array is one of the most common data types in an application, and you can use Array to process data in an application. Use the Array type to hold elements of a single type. Arrays can hold elements of any type — from Int to String, even Class — but the elements in an array must be of the same type.
Swift can create arrays using array literals. If the element type is not defined, Swift will automatically infer the type of the element in the array. Such as:
// Let numbers = [1, 2, 3] // Let names = ["li", "zhang"]Copy the code
You can also create an empty array by specifying the element type of the array in the declaration, for example:
Var emptyInt: [Int] = [] var emptyDouble: Array<Double> = Array()Copy the code
If you need a fixed number of defaults to initialize an Array, you can use Array(repeating: Count 🙂 to create:
var digitCounts = Array(repeating: 1, count: 3)
print(digitCounts)
// Prints "[1, 1, 1]"
Copy the code
Accessing an array element
When you need to perform operations on all elements of an array, you can use for-in to loop through the contents of the array.
for name in names {
print(name)
}
// Print "li"
// Print "zhang"
Copy the code
You can use the isEmpty property to quickly check if the array contains any elements, which is the same as using the count property to find the number of elements in the array and determine if it is zero.
print(numbers.isEmpty) // Print false
print(numbers.count == 0) // Print false
Copy the code
The first and last attributes are used to safely access the first and last elements of an array, returning nil if the array is empty.
print(number.first) // Print "1"
print(number.last) // Print "3"
​
print(emptyInt.first, emptyInt.last, separator: ", ")
// Prints "nil, nil"
Copy the code
Individual elements in an array can be accessed by subscript. The first element of a non-empty array has subscript 0, and the array’s subscript ranges from 0 to count (excluding count). Values that use negative numbers, equal to, or greater than count raise runtime errors, such as:
print(number[0], number[2], separator: ", ")
// Prints "1, 3"
​
print(emptyInt[0])
// Triggers runtime error: Index out of range
Copy the code
Add and remove elements
Let’s say you need to store a list of incoming employees. During this time, you need to add and remove names.
var staffs = ["zhang", "wang", "li"]
Copy the code
Use the append(_:) method to add a single element to the end of the array. Append (contentsOf:) allows you to add multiple elements at the same time. The argument can be another array or a sequence of elements of the same type.
staffs.append("zhao")
staffs.append(contentsOf: ["song", "suo"])
// ["zhang", "wang", "li", "zhao", "song", "suo"]
Copy the code
You can also add new elements to the middle of an array, using insert(_:at:) to insert a single element, and insert(contentsOf:at:) to insert multiple elements from another collection or array literal. Elements at and after the index are moved back to make room.
staffs.insert("ding", at: 3)
// ["zhang", "wang", "li", "ding", "zhao", "song", "suo"]
Copy the code
To remove elements from an array, use the remove(at:), removeSubrange(_:), and removeLast() functions.
staffs.remove(at: 0)
// ["wang", "li", "ding", "zhao", "song", "suo"]
​
staffs.removeLast()
// ["wang", "li", "ding", "zhao", "song"]
Copy the code
The effect of replacing an existing element with a new value is achieved by assigning a new value to a subscript.
if let i = staffs.firstIndex(of: "ding") {
staffs[i] = "bian"
}
// ["wang", "li", "bian", "zhao", "song"] Â
Copy the code
Increase the size of an array (important)
Each array retains a specific amount of memory to hold its contents. When you add elements to an array that exceed its reserved capacity, the array allocates more memory and assigns all of its elements to the new storage space. The time to add an element is fixed, and the performance is relatively average. But there are performance costs to reallocating operations, which occur less and less frequently as the array grows larger.
If you know approximately how many elements you need to store, use the reserveCapacity(_:) function before adding elements to avoid intermediate reallocation. Use the count and capacity attributes to determine how many more elements an array can hold without allocating more storage.
var array = [1, 2]
array.reserveCapacity(20)
Copy the code
For most Arrays of Element type, the storage area is a contiguous memory. For arrays of Element type class or ObjC Protocol, the storage area can be a contiguous memory, or an instance of NSArray. Since any subclass of NSArray can be an Array, there is no guarantee that it is a block of memory or an instance of NSArray in this case.
Modifying an array copy (emphasis)
Each array has a separate storage space for the values of all the elements contained in the array. For simple types, such as integers or other structures, when you change a value in an array, the value of that element does not change in any copy of the array. Such as:
var numbers = [4, 5, 6]
var numbersCopy = numbers
​
numbers[0] = 9
print(numbers)
// Prints "[9, 5, 6]"
print(numbersCopy)
// Prints "[4, 5, 6]"
Copy the code
If the elements of the array are instances of classes. In this case, a value stored in an array refers to an object that exists outside the array. If you change a reference to an object in an array, only that array has a reference to the new object. However, if two arrays contain references to the same object, you can see changes to the object’s properties in both arrays, for example:
class InterR {
var value = 10
}
​
var integers1 = [InterR(), InterR()]
var integers2 = integers1
​
integers1[0].value = 100
print(integers2[0].value)
// Prints "100"
​
integers1[0] = InterR()
print(integers1[0].value)
// Prints "10"
print(integers2[0].value)
// Prints "100"
Copy the code
Like all variable-size collections in the standard library, arrays are optimized using copy-on-write. Multiple copies share the same storage space until one copy is modified. When this happens, the array being modified is stored in a new storage space and then modified in the corresponding location. Copy-on-write optimization can reduce the number of copies.
This means that if an array shares storage space with other copies, the first change to the array incurs the cost of copying the array. You can then operate on it as its sole owner.
In the following example, you create an array and two copies that share the same storage. When the original array is modified, it makes a unique copy of its storage before modifying it. Then modify it. The two copies continue to share the original storage space.
var numbers = [7, 8, 9] var copy1 = numbers var copy2 = numbers numbers[0] = 100 numbers[1] = 200 numbers[2] = 300 // numbers: [100, 200, 300] // Copy 1 and copy 2: [7, 8, 9]Copy the code
Switching between Array and NSArray (emphasis)
When accessing the API of an NSArray instance, use the type conversion operator AS to convert the Array instance. For conversion to succeed, the Element type of the array must be a class type, an @objc Protocol, or a link to Foundation type.
The following example shows how to connect an Array instance to NSArray using the write(to:atomically:) function. In this example, the Colors array can be converted to NSArray because the colors array’s String elements are converted to NSString. On the other hand, the compiler prevents converting the moreColors array because its Element type is Optional and it cannot convert Foundation.
let colors = ["periwinkle", "rose", "moss"] let moreColors: [String?] = ["ochre", "pine"] let url = URL(fileURLWithPath: "names.plist") (colors as NSArray).write(to: url, atomically: true) // true (moreColors as NSArray).write(to: url, atomically: true) // error: cannot convert value of type '[String?] ' to type 'NSArray'Copy the code
If the Array’s elements are already instances of class or @objc Protocol, then the conversion from Array to NSArray takes only O(1) time and space; otherwise, it takes O(n) time and space.
When the element type of the target Array is a class or @objc protocol, the conversion from NSArray to Array first calls copy(with:) on the Array to get an immutable copy, Additional Swift bookkeeping work is then performed, which takes O(1) time. For already immutable instances of NSArray, copy(with:) usually returns the same array in O(1) time; otherwise, copy performance is uncertain. If copy(with:) returns the same Array, the NSArray and Array instances use the same copy-on-write optimization for the shared storage space, and the same optimization is used when two Array instances share the storage space.
When the element type of the target Array is a non-class type of the conversion Foundation type, the conversion from NSArray to Array copies the conversion to contiguous storage in O(n) time. For example, converting from NSArray to Array performs such a copy. No further conversions are required when accessing elements of an Array instance.
Pay attention to
The ContiguousArray and ArraySlice types are not converted, and instances of these types always have a contiguous memory space as their storage.
digression
Time is short and what you said may not be comprehensive. If you have any problems during your review, please leave a message in the comment section and I will reply as soon as possible