1、 try、try?、try!的差別:
- try:需要用catch捕捉異常,如:
do {
let data = try encoder.encode(item)
try data.write(to: dataFilePath(), options: .atomic)
} catch {
print("Error encoding item array:\(error.localizedDescription)")
}
- try? :傳回一個可選值類型,如果出現異常,傳回nil.如果沒有異常,則傳回可選值。(如果不想處理異常那麼可以用這個關鍵字),如:
let data = try? encoder.encode(item)
try? data!.write(to: dataFilePath(), options: .atomic)
(因為使用try?是以data為可選類型,使用前需unwrap)
- try! : 抛出了異常後,程式會立刻停止(如果不想處理異常,而且不想讓異常繼續傳播下去,類似NSAssert().), 如:
let data = try! encoder.encode(item)
try! data.write(to: dataFilePath(), options: .atomic)
2、 PropertyListEncoder、NSKeyedArchiver、NSUserDefault
-
PropertyListEncoder
使用 PropertyListEncoder可以對遵循Codable協定的類進行歸檔
将包含自定義類HighScoreItem的數組進行歸檔:
static func saveHighScore(_ item:[HighScoreItem]){
let encoder = PropertyListEncoder()
do {
let data = try encoder.encode(item)
try data.write(to: dataFilePath(), options: .atomic)
} catch {
print("Error encoding item array:\(error.localizedDescription)")
}
}
解檔:
static func loadHighScores() -> [HighScoreItem]{
var items = [HighScoreItem]()
let path = dataFilePath()
if let data = try? Data(contentsOf: path){
let decoder = PropertyListDecoder()
do{
items = try decoder.decode([HighScoreItem].self, from: data)
}catch{
print("Error decoding item array:\(error .localizedDescription)")
}
}
return items
}
-
NSKeyedArchiver
NSKeyedArchiver可以将遵守NSCoding協定的Cocoa類進行歸檔,将資料轉換為 Data 類型,然後再存儲到UserDefaults或寫到檔案:
do {
let data = try NSKeyedArchiver.archivedData(withRootObject: item, requiringSecureCoding: true)
try data.write(to: dataFilePath(), options: .atomic)
} catch {
print("Error encoding item array:\(error.localizedDescription)")
}
-
NSUserDefault
适合存儲資料量較少的資料
let defaults = UserDefaults.standard
defaults.set(item, forKey: "item");
3、NSArry和Array
Array是Swift中的結構體類型(struct), 屬于是值類型.
NSArray是OC中的對象類型, 屬于引用類型.
var aarr = ["happy", "every", "day"]
var barr : NSMutableArray = ["happy", "every", "day"]
//1
aarr[2] = "minute" //直接改變了aarr第二個元素的值
barr[2] = "minute" //讓barr第二個元素指向"minute"
print("1---\(aarr)")
print("1---\(barr)")
/*輸出:
1---["happy", "every", "minute"]
1---(
happy,
every,
minute
)
*/
//2
func changeA (var a:Array<String>) {
a[2] = "second" //a是對aarr的拷貝
}
func changeB (a : NSMutableArray) {
a[2] = "second" //a是對barr的引用
}
changeA(aarr) //值類型指派時進行拷貝, 改變是a[2]的值, aarr并沒有影響
changeB(barr) //引用類型指派時傳遞的是引用, a[2]和barr[2]都指向同一個位址.
print("2---\(aarr)")
print("2---\(barr)")
/*輸出:
2---["happy", "every", "minute"]
2---(
happy,
every,
second
)
*/
代碼來自HWenj的文章《Swift中Array和OC中的NSArray》
4、weak和unowned差別
- unowned辨別的變量不能是可選類型(Optional),不能指向nil,必須在 init 方法中初始化值。
-
weak辨別的變量可以為可選類型,可以指向nil。
參考:糾結的哈士奇的文章
5、oc和swift中==的差別
如果比較的是類(引用類型)
- 在Objective-C 中,隻有兩個對象指向的記憶體位址一樣才為true
- 在Swift中,對比的是對象的值,跟記憶體位址無關(如果要對比記憶體位址使用===)
6、方法的參數
一般方法會有一個或多個參數,每個參數會有兩個名字,外部參數名(external label)和内部參數名(internal label),例如:
func downloadImage(for searchResult: SearchResult,
withTimeout timeout: TimeInterval,
andPlaceOn button: UIButton) {
. . .
}
這個方法有3個參數searchResult、timeout、button,這些是内部參數名,可以在方法内使用。
而外部參數名是方法名的一部分,即以上方法名為:downloadImage(for:withTimeout:andPlaceOn:)
調用方法時,寫法為:
downloadImage(for: result, withTimeout: 10,
andPlaceOn: imageButton)
有些方法第一個外部參數名會以下劃線“_”代替,進而忽略外部參數名,如:
override func tableView(_ tableView: UITableView,
numberOfRowsInSection section: Int) -> Int
這些方法一般都是來源于過去Objective-C的寫法,已經把首個外部參數名合并在方法名之中。
7、switch技巧
可以通過"…<"比對範圍。如:
switch difference {
case 0:
title = "Perfect!"
case 1..<5:
title = "You almost had it!"
case 5..<10:
title = "Pretty good!"
default:
title = "Not even close..."
}
8、for循環技巧
循環周遊數組時,我們這樣寫:
for item in items {
if !item.checked {
count += 1
}
}
可以在後面加上條件選擇
for item in items where !item.checked {
count += 1
}
如果我們想要循環n次,可以這樣寫:
for i in 0...4 { // or 0..<5
print(i)
}
也可以通過stride方法:
for i in stride(from: 0, to: 5, by: 1) {
print(i)
}
stride()方法建立了代表從0到5,增長間隔是1的對象。如果想輸出從0到5的偶數,則把最後一個參數改為2,如果想要倒數,最後的參數傳入負值即可。
9、通過filter篩選
如果要篩選出數組中,符合某一條件的對象。如篩選出items數組中,屬性checked為false的對象,可以用filter方法
10、存儲屬性(Stored property)vc計算屬性(Computed property)
- 存儲屬性:常見的執行個體變量和常量
- 計算屬性:不存儲資料,在讀和寫時會執行邏輯代碼,如:
var indexOfSelectedChecklist: Int {
get {
return UserDefaults.standard.integer(
forKey: "ChecklistIndex")
}
set {
UserDefaults.standard.set(newValue,
forKey: "ChecklistIndex")
}
}
11、類中的方法
類的方法有三種:
- 執行個體方法:需要先建立執行個體,才能調用,如:
let myInstance = MyObject() // create the object instance
. . .
myInstance.doSomething() // call the method”
- 類方法:不需要建立執行個體,直接由類調用,常用做工廠方法來建立執行個體,如:
class MyObject {
. . .
class func makeObject(text: String) -> MyObject {
let m = MyObject()
m.text = text
return m
}
}
let myInstance = MyObject.makeObject(text: "Hello world")
- 初始化方法:除了上面的工廠方法,也可以使用自定義的初始化方法,用于建立和初始化執行個體。在初始化方法中,執行個體變量和常量必須被指派(Swfit要求在初始化方法執行完之後,變量和常量除非是可選類型,否則必須被指派),如:
class MyObject {
. . .
init(text: String) {
self.text = text
}
}
let myInstance = MyObject(text: "Hello world")
一個類的初始化方法可以有多個,如UITableViewController有init?(coder:)、init(nibName:bundle:)、init(style:) 等多個初始化方法。
12、if判斷技巧
如果我們要用if判斷多個條件,在Objective-C中可以用“&”進行連接配接,而在Swift中可以使用“,”進行連接配接,如:
if error == nil, let p = placemarks, !p.isEmpty {
self.placemark = p.last!
} else {
self.placemark = nil
}
隻有error為nil、p不為nil、p數組不為空(placemarks為數組)三個條件同時為真,if判斷才為真。
13、 as、as?、as!的差別:
【先下班】