目前分類:iOS (229)

瀏覽方式: 標題列表 簡短摘要

記錄很讚的文章

[Swift] map, compactMap平行處理

小賢 發表在 痞客邦 留言(0) 人氣()

自訂屬性包裝器(property wrapper) ,

找不到key、String, Int, Double, CGFloat 嘗試轉型,都失敗會給預設值。

小賢 發表在 痞客邦 留言(0) 人氣()

一、Mac環境設定(command line):

  1. 安裝 Homebrew

小賢 發表在 痞客邦 留言(0) 人氣()

1.修改 打包IPA參數

projectPath, projectName, scheme, infoPlist

小賢 發表在 痞客邦 留言(0) 人氣()

自訂Model to query string encoder,

在使用HttpGet protocol旳時候,

小賢 發表在 痞客邦 留言(0) 人氣()

截圖 2022-12-31 下午10.13.00

參考資料:https://juejin.cn/post/6844903846427230221

小賢 發表在 痞客邦 留言(0) 人氣()

泛型條件約束的Auto sync UserDefaults with Enum key SwiftUI property wrapper

截圖 2022-05-16 下午11.57.45

小賢 發表在 痞客邦 留言(0) 人氣()

Swift 初見 (Swift 2)

小賢 發表在 痞客邦 留言(0) 人氣()

  建立類似Windows Phone的雙向綁定型態轉換器(IValueConverter),
並搭配extension來實現預設實作,再建DateToStringConverter。

在使用的時候,

TextField("test", text: $enterDate.convert(converter: dateToStringConverter), prompt: Text("請輸入"))


            
extension Binding {
    func convert(converter: T) -> Binding where T: IValueConverter,
                                                                Value == T.Source {
        return Binding {
            return converter.convert(value: self.wrappedValue)
        } set: { (value: T.Target)  in
            do {
                self.wrappedValue = try converter.convertBack(value: value)
            } catch {
                print(String(describing: error))
            }
        }
    }
}

protocol IValueConverter {
    associatedtype Source
    associatedtype Target
    associatedtype Parameter

    var parameter: Parameter { get }
    
    func convert(value: Source) -> Target
    func convertBack(value: Target) throws -> Source
}

struct DateToStringConverter: IValueConverter {

    typealias Source = Date?
    typealias Target = String
    typealias Parameter = String

    let parameter: Parameter
    
    init(parameter: Parameter) {
        self.parameter = parameter
    }

    func convert(value: Source) -> Target {
        return value?.toString(format: parameter) ?? ""
    }
    
    func convertBack(value: Target) throws -> Source {
        guard let value = value.toDate(format: parameter) else {
            throw NSError(domain: "Can't cast from \(Source.self) to \(Target.self)", code: -1)
        }

        return value
    }
}


小賢 發表在 痞客邦 留言(0) 人氣()

NavigationParameter,可用來做頁面傳遞資料的一個封裝Model。

 

小賢 發表在 痞客邦 留言(0) 人氣()

截圖 2022-02-26 下午8.47.20

 

小賢 發表在 痞客邦 留言(0) 人氣()

ViewModel:

        

            import WebAPI
            import MVVM

            final class Page2ViewModel: ObservableObject, Refreshable, Updateable {

                @Published var isUpdate: Bool = false
                
                @Published private(set) var cellViewModels: [Page2CellViewModel] = []
                @Published private(set) var model: MainApodModel? {
                    didSet {
                        guard let model = model else {
                            return
                        }

                        cellViewModels = model.result.map { Page2CellViewModel(model: $0) }
                    }
                }

                func refresh() {

                    isUpdate = true

                    let parameter = MainApodParameter()

                    Task { @MainActor in
                        do {
                            let model: MainApodModel = try await MainApodWebAPI().invokeAsync(parameter)
                            
                            isUpdate = false
                            self.model = model
                            
                        } catch let error {

                            print(error.localizedDescription)

                            isUpdate = false
                        }
                    }
                }
            }
        

ViewController:

小賢 發表在 痞客邦 留言(0) 人氣()

        

import WebAPI
import MVVM

struct Page2ViewModel: Refreshable, Updateable, MutatingClosure {

    weak var binder: Binder?
    
    var isUpdate: Bool = false
    
    private(set) var cellViewModels: [Page2CellViewModel] = []
    private(set) var model: MainApodModel? {
        didSet {
            guard let model = model else {
                return
            }

            cellViewModels = model.result.map { Page2CellViewModel(model: $0) }
        }
    }
    
    init(binder: Binder)
    {
        self.binder = binder
        refresh()
    }

        
    mutating func refresh() {

        isUpdate = true

        let parameter = MainApodParameter()
        let copySelf = self

        Task { @MainActor in
            do {
                let model: MainApodModel = try await MainApodWebAPI().invokeAsync(parameter)
                
                copySelf.mutating { (mutatingSelf: inout Page2ViewModel) in
                    mutatingSelf.isUpdate = false
                    mutatingSelf.model = model
                }
                
            } catch let error {

                print(error.localizedDescription)

                copySelf.mutating { (mutatingSelf: inout Page2ViewModel) in
                    mutatingSelf.isUpdate = false
                }
            }
        }
    }
}

        
    

 

await之後是callback,這樣想就可以跟之前的做法接起來

小賢 發表在 痞客邦 留言(0) 人氣()


小賢 發表在 痞客邦 留言(0) 人氣()

 

Privacy Policy

小賢 發表在 痞客邦 留言(0) 人氣()

截圖 2021-08-31 上午5.11.19

(Release 出現not match字樣)

小賢 發表在 痞客邦 留言(0) 人氣()

用async / await 包裝PromiseKit,來快速支援 這新功能,有時間再慢慢將WebAPI layer的PromiseKit完全拿掉

但可惜的是最低需求是iOS 15、Swift 5.5及Xcode 13 (beta) 以上

小賢 發表在 痞客邦 留言(0) 人氣()

— For Xcode 12.5 及 Xcode 13

(Carthage 0.37 改用 xcframeworks 來相容Intel及Apple自己的M1 CPU)

小賢 發表在 痞客邦 留言(0) 人氣()

使用 SwiftUI的Hosting View Controller 來橋接iOS的UIKitSwiftUI View ,

小賢 發表在 痞客邦 留言(0) 人氣()

Activity Diagram


截圖 2021-05-28 下午12.47.50

小賢 發表在 痞客邦 留言(0) 人氣()