目前分類:iOS (234)

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

Github:

https://github.com/Bosian/SwiftUIPullToRefreshScrollView/tree/main

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

遇到的問題:

xib建立native gogole Ad,然後被包在 UIViewrePresentable內,如果使用property或init產生instance的方式,

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

建資料夾Xcode 16將預設改成folder(以前是group),
這會導致 pod install 失敗,

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

[SwiftUI] Xcode 16 preview失敗解法

(1.Xcode 16 Editor > Canvas > Use Legacy Previews Execution)

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

神解法記錄

---

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

記錄很讚的文章

[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) 人氣()

---

---

GooglePlay Apps: 國軍Online倒數計時器Lite, 國軍Online倒數計時器

 

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