# 13, 14 - 13: Publisher, CloudKit, CoreData - 14: App Architecture, Document Architecture, Undo ## Publisher  ```swift= // fetch the url backgroundImageFetchStatus = .fetching DispatchQueue.global(qos: .userInitiated).async { let imageData = try? Data(contentsOf: url) DispatchQueue.main.async { [weak self] in if self?.emojiArt.background == EmojiArtModel.Background.url(url) { self?.backgroundImageFetchStatus = .idle if imageData != nil { self?.backgroundImage = UIImage(data: imageData!) } } } } ``` ```swift= // fetch the url backgroundImageFetchStatus = .fetching let session = URLSession.shared let publisher = session.dataTaskPublisher(for: url) .map { (data, urlResponse) in UIImage(data: data) } .replaceError(with: nil) .receive(on: DispatchQueue.main) backgroundImageFetchCancellable = publisher .sink { [weak self] image in self?.backgroundImage = image self?.backgroundImageFetchStatus = image != nil ? .idle : .failed(url) } ``` 1. 取得 Publisher (subscription) 2. Publisher 設定 - `.map(_:)` 改變產物 - `.receive(on: DispatchQueue.main)` 3. Publisher 資料接收 - `.sink(receiveValue:)` 處理產出的資料 4. Cancellable 保存與使用 > Publisher 有很多 method 很像 array 的 method,`.map(_:)` - URLSession - Timer - NotificationCenter ## CoreData - @ObservedObject - @FetchRequest ## App Architecture - `App` protocol - `Scene` protocol - WindowGroup { } - DocumentGroup(newDocument:) { } - DocumentGroup(viewing:) { } - `@SenceStorage` - `@AppStorage` - `@ScaledMetric`  ```swift= @SceneStorage("EmojiArtDocument.steadyStatePanOffset") var steadyStatePanOffset: CGSize = .zero @SceneStorage("EmojiArtDocumentView.steadyStateZoomScale") var steadyStateZoomScale: CGFloat = 1 @AppStorage("username") var username: String = "Anonymous" ``` - 被存在 `UserDefaults.standard` - 所以不推薦存大量資料 - 所以不要存機敏性資料 7:48 Code app icon -> Asset.xcassets 19:56 `RawRepresentable` 每次開啟 app 後 load backgroundImage 完成又去 zoomToFit ## 28:02 Document Architecture * FileDocument * ReferenceFileDocument * UTType * Document Types * 39:05 Undo ```swift= func undoablyPerform(operation: String, with undoManager: UndoManager?) { let oldModel = model doIt() undoManager?.registerUndo(withTarget: self) { mySelf in mySelf.model = oldModel } undoManager?.setActionName(operation) } ``` ## 43:14 Back To Code - 49:50 讓 **ViewModel** conform to `ReferenceFileDocument` - 1:02:16 undo imple - 1:12:01 support document https://github.com/skkimeo/CS193p-Spring-2021
×
Sign in
Email
Password
Forgot password
or
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up