Swift not only adds a lot of features compared to Objective-C, but also makes a lot of changes. The most common mistake in actual programming is that Swift changes almost all the corresponding types in Objective-C from reference types to value types.

For example, the most commonly used data type in development is array:

NSMutableArray *array1 = [NSMutableArray arrayWithArray:@[@1, @2, @3]];
NSMutableArray *array2 = array1;
[array2 removeLastObject];
NSLog(@"% @", array1); / / 1. 2Copy the code
var array1 = [1, 2, 3]
var array2 = array1
array2.removeLast()
print(array1) // 1, 2, 3
Copy the code

At the beginning of learning Swift, I just thought it was just a language with different design for different data types. In the development, I just needed to pay attention to adding inout for parameters that needed to be modified inside the function.

But the more I worked with Swift, the more I realized that this design was actually more difficult to use than the Objective-C reference type.

For example, to implement a wrapper class that sorts an array, pass in the array and sort the array in ascending order, use the simplest bubble sort implementation, if it is objective-C:

#import <Foundation/Foundation.h>

@interface MySort<ObjectType>: NSObject 

- (void)sortWithArray:(NSMutableArray<ObjectType> *)array;

@end

@implementation MySort

- (void)sortWithArray:(NSMutableArray *)array {
	if(! array || array.count < 2) {return;
	}
	
	for (NSInteger end = array.count - 1; end > 0; end--) {
		for (NSInteger begin = 1; begin <= end; begin ++) {
			if ([array[begin] compare:array[begin - 1]] == NSOrderedAscending) {
				id tmp = array[begin];
				array[begin] = array[begin - 1];
				array[begin - 1] = tmp;
			}
		}
	}
}

@end

int main(int argc, char *argv[]) {
	NSMutableArray *array = [NSMutableArray arrayWithArray:@[@9, @8, @7, @6, @5, @4, @3, @2, @1, @0]];
	MySort *sort = [MySort new];
	[sort sortWithArray:array];
	NSLog(@"% @", array);
}
Copy the code

In Objective-C, array is a reference type, so you can sort the array by passing it directly. If you use Swift, you need to modify array in the function and add inout to it:

public class MySort<ObjectType: Comparable> {
    public final func sortWithArray(array: inout [ObjectType]) {
        guard array.count > 1 else {
            return
        }
        for end in stride(from: array.count - 1, to: 0, by: -1) {
            for begin in1... end {if array[begin] < array[begin - 1] {
                    letTMP = array[begin] array[begin] = array[begin-1] array[begin-1] = TMP}}}}} var array = [9,8,7,6,5,4,3,2,1,0] var mySort = MySort<Int>() mySort.sortWithArray(array: &array)print(array)
Copy the code

So far, there are no problems. Let’s say we need the sorting class to save the data and implement sorting in other methods.

In Objective-C, you simply add a member to the class and pass it the array object passed by the method:

@interface MySort<ObjectType>: NSObject {
@private
	NSMutableArray<ObjectType> *_array;
}

- (void)sortWithArray:(NSMutableArray<ObjectType> *)array;

@end

@implementation MySort

- (void)sortWithArray:(NSMutableArray *)array {
	if(! array || array.count < 2) {return;
	}
	
	_array = array;
}

- (void)sort {
	for (NSInteger end = _array.count - 1; end > 0; end--) {
		for (NSInteger begin = 1; begin <= end; begin ++) {
			if ([_array[begin] compare:_array[begin - 1]] == NSOrderedAscending) {
				id tmp = _array[begin];
				_array[begin] = _array[begin - 1];
				_array[begin - 1] = tmp;
			}
		}
	}
}

@end
Copy the code

But there is a problem with Swift:

public class MySort<ObjectType: Comparable> {
    private var array: [ObjectType]?
    
    public final func sortWithArray(array: inout [ObjectType]) {
        guard array.count > 1 else {
            return
        }
        self.array = array
        sort()
    }
    
    private func sort() {
        for end instride(from: array! .count - 1, to: 0, by: -1) {for begin in1... end {ifarray! [begin] < array! [begin - 1] {lettmp = array! [begin] array! [begin] = array! [begin - 1] array! [begin - 1] = tmp } } } } } var array: [Int] = [9,8,7,6,5,4,3,2,1,0] var mySort = mySort <Int> &array) // [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]print(array)
Copy the code

Since arrays are value types, passing the array passed by a function to a member of the sorting class: self.array = array is a default copy operation, and the rest of the sorting process simply sorts the data copied from the sorting class. If we need to change the sort of the array passed by the function, we need to pass the locally copied array to the external inout argument after sort() is called:

    public final func sortWithArray(array: inout [ObjectType]) {
        guard array.count > 1 else {
            return
        }
        self.array = array
        sort()
        array = self.array!
    }
Copy the code

This was bad because there were two more copies of the data for no reason, and I ended up using a bad way of using Pointers:

public class MySort<ObjectType: Comparable> {
    private var array: UnsafeMutablePointer<[ObjectType]>?
    
    public final func sortWithArray(array: inout [ObjectType]) {
        guard array.count > 1 else {
            return
        }
        self.array = withUnsafeMutablePointer(to: &array) { $0 }
        sort()
    }
    
    private func sort() {
        for end instride(from: array! .pointee.count - 1, to: 0, by: -1) {for begin in1... end {ifarray! .pointee[begin] < array! .pointee[begin - 1] {lettmp = array! .pointee[begin] array! .pointee[begin] = array! .pointee[begin - 1] array! .pointee[begin - 1] = tmp } } } } } var array: Var mySort = mySort <Int>() mysort.sortwithArray (array: &array)print(array)
Copy the code

This does avoid copying, but really very ugly, inconvenient, just solve the problem.

Someone has a better solution welcome to share.