Swift相比Objective-C不止增長了不少特性,還有很多修改,對於實際編程中最容易出現的錯誤莫過於Swift將幾乎全部Objective-C中對應的類型,都由引用類型都修改成值類型。編程
好比開發中最經常使用到的數據類型array:數組
NSMutableArray *array1 = [NSMutableArray arrayWithArray:@[@1, @2, @3]];
NSMutableArray *array2 = array1;
[array2 removeLastObject];
NSLog(@"%@", array1); // 1, 2
複製代碼
var array1 = [1, 2, 3]
var array2 = array1
array2.removeLast()
print(array1) // 1, 2, 3
複製代碼
剛開始學習Swift時,只是以爲這只是一個語言對於不一樣數據類型的設計不一樣而已,開發中只要注意對於須要函數內部修改的參數,加上inout便可。bash
可是隨着對於Swift的深刻使用,愈來愈以爲,這個設計相比於Objective-C的引用類型來講,確實是更加的難以使用。ide
好比實現一個對於數組的排序封裝類,將數組傳入並將數組按照升序排序,這裏採用最簡單的冒泡排序實現,若是是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);
}
複製代碼
由於Objective-C中,數組是引用類型,直接將數組傳遞就能夠實現對其排序,若是將上述的代碼用Swift實現,須要在函數中修改array,須要將參數加上inout來實現:學習
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 in 1 ... end {
if array[begin] < array[begin - 1] {
let tmp = 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)
複製代碼
目前來看沒有任何問題,下面假如須要排序類先將數據保存,並在其它方法中實現排序。ui
在Objective-C中,只須要爲類添加一個成員,而且將方法傳入的數組對象傳遞給它便可:spa
@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
複製代碼
可是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 in stride(from: array!.count - 1, to: 0, by: -1) {
for begin in 1 ... end {
if array![begin] < array![begin - 1] {
let tmp = 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>()
mySort.sortWithArray(array: &array)
// [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
print(array)
複製代碼
由於數組是值類型,將函數傳入的數組傳遞給排序類的成員時:self.array = array 是一個默認拷貝的操做,在接下來的排序過程,只是對排序類中拷貝的數據進行排序。若是須要將函數傳入的數組也修改排序,須要在sort()調用後,將本地拷貝的數組傳遞給外部的inout 參數:指針
public final func sortWithArray(array: inout [ObjectType]) {
guard array.count > 1 else {
return
}
self.array = array
sort()
array = self.array!
}
複製代碼
這樣作很是的很差,由於無緣無故的多出來兩次數據的拷貝操做,最終我是使用了一個不太好的辦法,就是利用指針來處理:
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 in stride(from: array!.pointee.count - 1, to: 0, by: -1) {
for begin in 1 ... end {
if array!.pointee[begin] < array!.pointee[begin - 1] {
let tmp = array!.pointee[begin]
array!.pointee[begin] = array!.pointee[begin - 1]
array!.pointee[begin - 1] = tmp
}
}
}
}
}
var array: [Int] = [9,8,7,6,5,4,3,2,1,0]
var mySort = MySort<Int>()
mySort.sortWithArray(array: &array)
print(array)
複製代碼
這樣子確實避免了拷貝,不過真的很是的很差看,也不方便,只是解決了問題而已。
有人有更好的辦法解決歡迎分享。