Swift和SwiftUI

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)
        }
    }
}

你可能感兴趣的:(Swift和SwiftUI)