IOS Objective-C、Swift及多執行緒和記體體管理

以下書目參考自 https://www.zhihu.com/question/28491905

(PS 編號順序鼻不代表入手順序,請根據自己目前的程度,選擇需要看的書和順序)

(1) Objective-C高级编程 iOS与OS X多线程和内存管理
https://a.co/d/aUzbeNg

(2) Effective Objective C 2.0:编写高质量iOS与OS X代码的52个有效方法
Effective Objective-C 2.0: 52 Specific Ways to Improve Your iOS and OS X Programs (Effective Software Development Series)
https://a.co/d/6WEdatk

(3) iOS 15 Programming Fundamentals with Swift
https://www.oreilly.com/library/view/ios-15-programming/9781098118495/?_gl=1bpqv03_gaMTU4Nzc5MTc3MC4xNjcyNjY2NzMw_ga_092EL089CH*MTY3NTE4MjQyMy4zLjEuMTY3NTE4MjQ0Mi40MS4wLjA.

(4) Programming iOS 14
https://www.oreilly.com/library/view/programming-ios-14/9781492092162/?_gl=11pl1cc_gaMTU4Nzc5MTc3MC4xNjcyNjY2NzMw_ga_092EL089CH*MTY3NTE4MjQyMy4zLjEuMTY3NTE4MjUwNi41Ny4wLjA.

(5) iOS應用逆向工程:分析與實戰
https://www.books.com.tw/products/CN11090535
Note: 这本书也挺不错,不过,书里的好几个工具都过时了,看看就好。

(6) iOS Core Animation: Advanced Techniques
https://a.co/d/2Lr6MKv

Ref:

https://www.zhihu.com/question/28491905

Software engineering – Describe View, ViewModel, DataService, BluetoothService relationships by interaction diagram, class diagram

Prerequisite:

  • Interaction diagram描述object之間的互動
  • Class diagram描述class之間構成的結構與關係

Ref:

Interaction diagram

https://zh.wikipedia.org/zh-tw/%E4%BA%A4%E4%BA%92%E6%A6%82%E8%BF%B0%E5%9C%96

Class diagram

https://en.wikipedia.org/wiki/Class_diagram

UML class diagram relationships說明:

link:

https://cacoo.com/diagrams/42iti8NqW7vXxEnX/51F5C

Ref:

UML class diagram Relationships:

https://spicyboyd.blogspot.com/2018/07/umlclass-diagram-relationships.html​

IOS app工程師職涯發展

以前不知道自學的訣竅&自己的問題,所以很多很棒的資源看了就忘或者是一知半解。

Ios工程師的自我修煉除了下面提供的roadmap和matrix,個人認為ios developer應該還要把內功(ex: 實作演算法和clean code能力)和擇一domain knowledge長期耕耘(ex ai or network or image/video processing⋯⋯)。

至於architecture 部分應該也是要,但architecture的範圍很廣,所以我還搞不清楚到底如何培養?還是說這個只能靠天賦?

雖然上述許多能力很抽象,在不同公司或組織對同個項目的理解與定義也不同。但有個方向努力還是比較安心😎

內容

  • 軟體工程師職涯/公司類型/薪資分級/面試重點
  • IOS Developer Roadmap
  • IOS Developer Matrix
  • IOS_app_分析與實作流程討論報告
  • 架構師的自我修煉:技術、架構和未來
  • 工作開發流程與層級

軟體工程師職涯/公司類型/薪資分級/面試重點:

Ios developer roadmap:

https://github.com/BohdanOrlov/iOS-Developer-Roadmap

Ios developer matrix:
https://github.com/BohdanOrlov/ios-skills-matrix

IOS_app_分析與實作流程討論報告 (p.s. 個人工作6年經驗分享,僅供參考)

Ref: https://www.magicbytesolutions.com/ios-app.php

架構師的自我修煉:技術、架構和未來

https://www.books.com.tw/products/CN11722551?fbclid=IwAR2wDrH8mb9e6ShGgdSuhwxtKqOA2N7dyrqinVQ-aSZEIs3bvSSQSAUS4Xk&mibextid=5zvaxg

工作開發流程與層級

RxSwift學習重點整理

RxSwift學習重點:

不可忘記的前提:

  • 事件是在哪一條thread上執行(ex: main thread or background thread)
  • 物件的生命週期(i.e Observable/Observer的生命週期)
  • 效能
  • 使用的記憶體控管

RxSwift好處:

  • 運用function programming方式,解決code過於分散等問題,讓程式碼好維護(p.s. RxSwift拿去跟Target-action/Closure/Delegate相比)
  • 呼叫update UI的code永遠需要nested在asynchronous action內的問題 (p.s. KVO, Swift的didSet也有解決這個問圖)
  • 解決asynchronous action之間有Dependency時,都會需要nested

RxSwfit達成上述好處的實作概念:

  • 透過抽象化asynchronous action,包成function programming的形式讓開發者使用

RxSwift正確用法的抽象概念:

  • 確保「訂閱/與訂閱物件的生命週期」能被預期(i.e. 知道何時生成/銷毀)
  • 妥善運用compound operator(例如: combineLatest/zip、flatMap vs flatMapLatest、distinctUntilChanged、……),知道其差別與何時使用

判斷工程師對RxSwift熟練的程度:

  1. 會用RxSwift完成功能
  2. 會區分RxSwift和Target-action/Closure/Delegate的差別
  3. 了解如何妥善運用RxSwift,而不是一些可以用基本data structure(ex: Array、Dictionary……)的地方,也不自覺得使用RxSwift
  4. 了解RxSwift比較複雜的operator且能說出類似operator的差別與何時使用
  5. 會管控RxSwift的訂閱生命週期與Observable和Observer是在哪個thread上執行
  6. 有辦法運用RxSwift達成MVVM architecture(p.s. 達成Decouple UI和ViewModel、UI和ViewModel和Service的關係)
  7. 能把上面整理的RxSwift重點自己講出來,且「能上機實作出來」
  8. 不僅(7)能達成,也有應用於大型系統架構的實務經驗(ex: 一萬行code及能畫出UML class diagrams,並說明運用RxSwift後,達成什麼事,有哪些地方/原則要注意)

Backpressure feature of RxJava(p.s. RxSwift doesn’t have this feature)

https://github.com/ReactiveX/RxJava/wiki/Backpressure

Ref:
https://beeth0ven.github.io/RxSwift-Chinese-Documentation/

SwiftUI學習

SwiftUI

目的:

  • 避免重複創建object
  • 確保object的生命週期,以確定function可以正常work、確保使用者的資料不會遺失、避免將runtime的資料永久保存
  • 確保「效能」(Note:「如何更新」、「何時更新」 (i.e. 確保「效能」,讓使用者操作不卡頓)

方法:

SwiftUI背後的重點:

1) ID – 判斷兩個UI元件是否相同
(p.s. 參考"截圖 2023-01-10 上午10.47.05(2__ID的使用地方"、
“截圖 2023-01-10 上午10.48.59_顯示ID_結構ID")
p.s. 不同ID = 不同元素

 ID種類: 顯示ID、結構ID

2) 生命週期

3) 依賴關係

關於SwiftUI stateObject & observedObject(p.s 管理物件生命週期和何時會重新產生物件)

https://onevcat.com/2020/06/stateobject/

SwiftUI vs Combine framework

https://stackoverflow.com/questions/72557548/what-is-difference-between-combine-and-rxswift#:~:text=Combine%20Subjects%20are%20thread%20safe,Combine%20you%20need%20them%20constantly.

https://quickbirdstudios.com/blog/rxswift-combine-transition-guide/

https://quickbirdstudios.com/blog/combine-vs-rxswift/

IOS Swift message dispatch

import Foundation
class CustomClass: NSObject {
@objc func getValue(_ arg: Int) {
print("val is: 100")
}
@objc func getValue2() {
print("val is: 2")
}
}
private func executeAction(className: String, methodName: String, arg: Any?) {
let cla: AnyClass? = NSClassFromString(className)
if let cla = cla as? NSObject.Type {
let selector: Selector = Selector(methodName)
let instance = cla.init()
if (instance.responds(to: selector)) {
if let arg = arg {
instance.perform(selector, with: arg)
} else {
instance.perform(selector)
}
} else {
print("method not found")
}
} else {
print("class not found")
}
}
executeAction(className: "YourProjectName.CustomClass", methodName: "getValue:", arg: 100)
executeAction(className: "YourProjectName.CustomClass", methodName: "getValue2", arg: nil)

class DataModel: NSObject {
var data = 1
var callback: ((Any?) -> Unmanaged<AnyObject>?)?
}
class CustomClass: NSObject {
@objc func getValue(_ model: DataModel, completion callback: Any!) {
print("get Value for CustomClass")
if let callback = callback as? ((Any?) -> Unmanaged<AnyObject>?) {
print("closure is not nil")
_ = callback(model.data)
}
}
@objc func setValue(_ model: DataModel, completion callback: Any!) {
print("test11 set Value for CustomClass, val is: \(model.data)")
if let callback = callback as? ((Any?) -> Unmanaged<AnyObject>?) {
print("test11 closure is not nil")
_ = callback(model.data)
}
}
}
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let dataModel = DataModel()
executeAction(className: "TestProject2.CustomClass", methodName: "setValue:completion:", arg: dataModel) { result in
print("test11 execute setValue callback complete!!, result: \(String(describing: result))")
return nil
}
}
private func executeAction(className: String, methodName: String, arg: Any?, callback: ((Any?) -> Unmanaged<AnyObject>?)? = nil) {
let cla: AnyClass? = NSClassFromString(className)
if let cla = cla as? NSObject.Type {
let selector: Selector = Selector(methodName)
let instance = cla.init()
if (instance.responds(to: selector)) {
if let arg = arg,
let callback = callback {
instance.perform(selector, with: arg, with: callback)
} else if let arg = arg {
instance.perform(selector, with: arg)
} else {
instance.perform(selector)
}
} else {
print("method not found")
}
} else {
print("class not found")
}
}
}

IOS – 模擬RxSwift

class DisposeBag {
var delegate: RxSimulator?
deinit {
print("test11 DisposeBag deinit")
delegate = nil
}
}
class RxSimulator {
var action: ((Bool) -> Void)? = nil
weak var disposeBag: DisposeBag?
func createObservable(closure: ((Bool) -> Void)? = nil) -> RxSimulator {
action = closure
return self
}
func subscribe(callback: ((Bool) -> Void)? = nil) -> RxSimulator {
action = callback
return self
}
func onNext(val: Bool) {
action?(val)
}
func disposed(by disposeBag: DisposeBag) {
self.disposeBag = disposeBag
self.disposeBag?.delegate = self
}
deinit {
print("test11 RxSimulator deinit")
}
}
class ViewController: UIViewController {
var disposeBag: DisposeBag? = DisposeBag()
override func viewDidLoad() {
super.viewDidLoad()
if let disposeBag = disposeBag {
let myClosure: ((Bool) -> Void)? = { input in
print("execute myClosure")
}
let observable = RxSimulator().createObservable(closure: myClosure)
observable.subscribe { result in
print("test11 In subscribe, result is: \(result)")
}.disposed(by: disposeBag)
DispatchQueue.global().asyncAfter(deadline: .now() + 3) {
print("test11 execute observable.onNext")
observable.onNext(val: true)
}
DispatchQueue.global().asyncAfter(deadline: .now() + 5) {
self.disposeBag = nil
}
}
}
}