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!的区别:
【先下班】