1.Swift相对与OC一些更好用的特性
(1)更好用的switch...case,for循环,枚举,结构体
a. switch...case
不需要break,一个case可以写多个条件,使用fallthrough继续执行
let num = arc4random() % 10
switch num {
case 1, 2:
print("1, 2")
case 3..<5:
print("3, 4")
case ..<7:
print("6")
case ...8:
print("8")
default:
print("defalut")
}
基本数据类型都能判断,并且能使用where语句
let testArray = [1,2,3]
switch testArray {
case let array1 where array1.first == 1:
print(array1.first!)
default:
print(testArray)
}
b. for循环
普通for循环
for i in 0..<8 {
}
for i in 0..<8 where i % 2 == 0 {
}
for i in (0..<8).reversed() {
}
for i in stride(from: 0, to: 8, by: 2) {
}
for i in stride(from: 0, through: 8, by: 2) {
}
集合类型的遍历
// 数组遍历
var array = [1,2,3,4]
for item in array {
}
for (i, item) in array.enumerated() {
}
for item in array {
array.append(item)
}
// 数组的函数式
let mapArray = array.map { (item) -> Int in
return item + 1
}
let filterArray = array.filter { (item) -> Bool in
return item % 2 == 0
}
let reduce = array.reduce(3) { (item1, item2) -> Int in
return item1 + item2
}
let sortArray = array.sorted { (item1, item2) -> Bool in
return item1 > item2
}
// 数组的截取
let index4 = 2
let array4 = [1,2,3,4,5]
let subArray4 = array4[0..
c 枚举
// Swift的枚举可以和整型,浮点数,字符串,布尔类型关联,不写默认关联字符串
enum Language: String {
case Swift
case ObjectiveC = "Objective-C"
case C
case Java
}
print(Language.Swift.rawValue)
Language.init(rawValue: "Swift")
// 可以绑定值
enum RequestResult {
case Success(Int)
case Error(String)
}
let requestResult = RequestResult.Success(1)
switch requestResult {
case .Success(let code):
print(code)
case .Error(let errorTint):
print(errorTint)
}
// 可以定义方法和计算型属性
enum Device {
case iPad, iPhone, AppleTV, AppleWatch
func introduced() -> String {
switch self {
case .iPad: return "iPad"
case .iPhone: return "iPhone"
case .AppleWatch: return "AppleWatch"
case .AppleTV: return "AppleTV"
}
}
var year: Int {
switch self {
case .iPhone: return 2007
case .iPad: return 2010
case .AppleTV: return 2011
case .AppleWatch: return 2012
}
}
}
let introduce = Device.iPhone.introduced()
d 结构体
结构体在Swift中的地位很重要,Array Dictionary Set Int Float Double Bool String都是结构体
/*
什么时候用结构体,什么时候用类
把结构体看做值
位置(经纬度)坐标(二维坐标,三维坐标)温度
把类看做是物体 人 车 动物
*/
/*
结构较小,适用于复制操作,相比一个class的实例被多次引用,struct更加安全
无须担心内存泄漏或者多线程冲突问题
*/
struct Location {
var longitude: Double
var latitude: Double
// 使用Failable-Initializer
init?(coordinateString: String) {
// 非常简洁的非空判断,安全可靠
guard
let commaIndex = coordinateString.index(of: ","),
let firstElement = Double(coordinateString[coordinateString.startIndex..
(2)String与NSString
// 1.String拼接用“+”,NSString是引用类型, String是值类型
let string1 = "Hello Swift"
let string2 = "Good"
let string3 = string1 + string2
// 2.获取的长度不同
let string4 = "你好,我来了a"
let string5: NSString = "你好,我来了a"
print(string4.count, string5.length)
// 3.获取字字符串
let range: NSRange = string5.range(of: "")
let subString5 = string5.substring(with: range)
print(subString5)
let range2 = string4.range(of: "")
let subString4 = string4[range2!]
print(subString4)
// 4.它们的长度都是1,基于unicode编码,不同的单个字符长度不一样,不能使用string[index]的方式访问单个字符,使用string.startIndex string.endIndex 构成前闭后开的区间 [startIndex, endIndex)
let subString4a = string4[string4.index(before: string4.endIndex)]
print(subString4a)
let subString4b = string4[string4.startIndex..
(3)函数
let testString = "林哲生"
//(4)函数
func sayHello(name: String = testString, greeting: String = "你们好啊", extra: Dictionary? = nil) {
print(name + greeting)
}
/*
1.支持重载
2.函数参数可设置默认值
*/
sayHello()
sayHello(name: "1")
sayHello(greeting: "2")
sayHello(extra: ["one": "1"])
// 改变外部传入的参数
var array = [1,2,3,4]
func sayHello(array: inout [Int]) {
array.append(5)
}
(4)可选项,安全的语言
var string1: String? = "Hello"
var string2: String? = "Hi"
// 解包判断1
if let string1 = string1 {
print(string1)
}
func sayHello(name: String = "林哲生", greeting: String = "你们好啊", extra: Dictionary? = nil) {
// 解包判断2
guard let uExtra = extra else {
return
}
print(uExtra)
}
func sayHello(greeting: String = "你们好啊", extra: Dictionary? = nil) {
// 解包判断2
guard let uExtra = extra else {
return
}
print(uExtra)
}
// 强解包,给与默认值
(5)各种各样的基类
NSObject(OC中所有的类都是继承NSObject) < AnyObject(Swift中的类可以不继承任何类) < Any(包含了函数的类型)
(6)基本数据类型都是值类型,copy - on - write
// 值类型
var arrayA = [1, 2, 3]
var arrayB = arrayA
arrayA.append(4)
arrayB.append(5)
print(arrayA)
print(arrayB)
// copy - on - write
let arrayA = [1, 2, 3]
var arrayB = arrayA
arrayA.withUnsafeBytes { print($0) }
arrayB.withUnsafeBytes { print($0) }
arrayB.append(4)
arrayB.withUnsafeBytes { print($0) }
2.Swift的动态性
(0)大纲
a 纯Swift的类和继承自NSObject的类通过runtimeAPI获取方法属性
b @objc之后可以被runtimeAPI获取到,但是方法无法被替换
c dynamic后方法动态调用,可以被替换
d Swift和OC相互调用,Swift在OC类中的名字
e Swift使用关联对象
f Swift5.0方法交换,动态访问属性(动态传递参数,动态调用方法)
(1)使用runtime API与Swift
a. @objc本意是让OC可以调用Swift的方法,@objc所修饰的属性,方法不能包含Swift特有的类
b. @objc 信息能使用runtime获取,dynamic动态调用
c. 如果类继承自Object-c的类会自动被编译器插入@objc标识
class TestSwiftClass {
var aBool: Bool = true
var aInt: UInt = 0
var aFloat: Float = 123.45
var aDouble: Double = 1234.567
var aString: String = "abc"
@objc func printHaha() {
print("Haha")
}
@objc func printHeihei() {
print("Heihei")
}
}
class TestObject: NSObject {
var aBool: Bool = true
var aInt: UInt = 0
var aFloat: Float = 123.45
var aDouble: Double = 1234.567
var aString: String = "abc"
override var description: String {
return "TestObject"
}
func testReturnVoid() {
}
@objc dynamic func testdescription() -> String {
return "testdescription"
}
}
// 1 获取类所有的属性,方法
showClassRuntime(anyClass: TestSwiftClass.self)
showClassRuntime(anyClass: TestObject.self)
// 2 交换方法 ,加@objc可以获取到
methodSwizzle(cls: TestObject.self, originSelector: #selector(getter: NSObjectProtocol.description), swizzleSelector: #selector(TestObject.testdescription))
let testObject = TestObject()
print("testObject:"+testObject.description)
// 3 加 dynamic 方法会被动态调用
methodSwizzle(cls: TestObject.self, originSelector: #selector(TestObject.testdescription), swizzleSelector: #selector(getter: NSObjectProtocol.description))
let testObject2 = TestObject()
print(testObject2.testdescription())
a .纯 Swift 类没有动态性,但在方法、属性前添加 dynamic 修饰可以获得动态性。
b .继承自 NSObject 的 Swift 类,其继承自父类的方法具有动态性,其他自定义方法、属性需要加 dynamic 修饰才可以获得动态性。
c .若方法的参数、属性类型为 Swift 特有、无法映射到 Objective-C 的类型 (如 Character、Tuple),则此方法、属性无法添加 dynamic 修饰(会编译错误)
d .Swift 类在 Objective-C 中会有模块前缀
e .仍然可以使用关联对象技术
(2)Swift5的“Method Swizzling”
// 可继承
@dynamicMemberLookup
class SwiftClass: NSObject {
dynamic func sayWordsA() {
print("A")
}
subscript(dynamicMember member: String) -> String {
let properties = ["nickName": "Zhou", "city": "GuangZhou"]
return properties[member] ?? "good"
}
subscript(dynamicMember member: String) -> Int {
let properties = ["nickName": 1, "city": 2]
return properties[member] ?? 3
}
}
extension SwiftClass {
@_dynamicReplacement(for: sayWordsA())
func sayWordsB() {
sayWordsA()
print("B")
}
@_dynamicReplacement(for: sayWordsA())
func sayWordsC() {
sayWordsA()
print("C")
}
}
extension SwiftClass {
var goodString: String? {
get {
return objc_getAssociatedObject(self, "goodString") as? String
}
set {
objc_setAssociatedObject(self, "goodString", newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_COPY_NONATOMIC)
}
}
}