100 Days of SwiftUI(DAY 80(Project16 part 2))

Swiftの結果タイプを理解する
Understanding Swift’s Result type

私たちが本当に望んでいるのは、非ブロッキング呼び出しです。つまりResult、戻り値として返送することはできません。代わりに、メソッドが2つのパラメーターを受け入れるようにする必要があります。1つはフェッチするURL用で、もう1つは値で呼び出される完了クロージャーです。つまり、メソッド自体は何も返しません。そのデータは、将来のある時点で呼び出される完了クロージャーを使用して戻されます。

@escaping。これは、「このクロージャーは、このメソッドの現在の実行の外で使用される可能性があるため、完了するまでメモリーを存続させてください。

文字列とクロージャを受け入れ、何も返しません–しかし、今度は、完了クロージャをさまざまな方法で呼び出します。

URLが悪い場合はを呼び出しますcompletion(.failure(.badURL))。
リクエストから有効なデータが返されたら、それを文字列に変換してからを呼び出しますcompletion(.success(stringData))。
リクエストからエラーが返された場合は、を呼び出しますcompletion(.failure(.requestFailed))。
なんらかの理由でデータまたはエラーが返されない場合は、を呼び出しますcompletion(.failure(.unknown))。

//
//  ContentView.swift
//  HotProspects
//
//

import SwiftUI

//---------------------------
struct ContentView: View {
    enum NetworkError: Error {
        case badURL, requestFailed, unknown
    }
//ブロッキング関数呼び出し
//    func fetchData(from urlString: String) -> Result<String, NetworkError> {
//        .failure(.badURL)
//    }
//非ブロッキング呼び出し-> Void
//    func fetchData(from urlString: String, completion: (Result<String, NetworkError>) -> Void) {
//        completion(.failure(.badURL))
//    }

//    func fetchData(from urlString: String, completion: @escaping (Result<String, NetworkError>) -> Void) {
//        DispatchQueue.main.async {
//            completion(.failure(.badURL))
//        }
//    }
    
    func fetchData(from urlString: String, completion: @escaping (Result<String, NetworkError>) -> Void) {
        // check the URL is OK, otherwise return with a failure
        guard let url = URL(string: urlString) else {
            completion(.failure(.badURL))
            return
        }

        URLSession.shared.dataTask(with: url) { data, response, error in
            // the task has completed – push our work back to the main thread
            DispatchQueue.main.async {
                if let data = data {
                    // success: convert the data to a string and send it back
                    let stringData = String(decoding: data, as: UTF8.self)
                    completion(.success(stringData))
                } else if error != nil {
                    // any sort of network failure
                    completion(.failure(.requestFailed))
                } else {
                    // this ought not to be possible, yet here we are
                    completion(.failure(.unknown))
                }
            }
        }.resume()
    }
    
    var body: some View {
        Text("Hello, World!")
        .onAppear {
            self.fetchData(from: "https://www.apple.com") { result in
                switch result {
                case .success(let str):
                    print(str)
                case .failure(let error):
                    switch error {
                    case .badURL:
                        print("Bad URL")
                    case .requestFailed:
                        print("Network problems")
                    case .unknown:
                        print("Unknown error")
                    }
                }
            }
        }
    }
}
//---------------------------
struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}


ObservableObjectの変更を手動で公開する
Manually publishing ObservableObject changes

import SwiftUI
//---------------------------
class DelayedUpdater: ObservableObject {
    //@Published var value = 0
    var value = 0 {
        willSet {
            objectWillChange.send()
        }
    }

    init() {
        for i in 1...10 {
            DispatchQueue.main.asyncAfter(deadline: .now() + Double(i)) {
                self.value += 1
            }
        }
    }
}
//---------------------------
struct ContentView: View {
    @ObservedObject var updater = DelayedUpdater()

    var body: some View {
        Text("Value is: \(updater.value)")
    }
}
//---------------------------

willSetオブザーバー内に機能を追加する機会があります。おそらく、何かをログに記録したり、別のメソッドを呼び出したり、整数を内部に固定したりしてvalue、範囲外にならないようにしたい場合があります。これですべてが制御されます。

SwiftUIでの画像補間の制御
Controlling image interpolation in SwiftUI


struct ContentView: View {

    var body: some View {
//        Image("example")
//        .resizable()
//        .scaledToFit()
//        .frame(maxHeight: .infinity)
//        .background(Color.black)
//        .edgesIgnoringSafeArea(.all)
        Image("example")
        .interpolation(.none)
        .resizable()
        .scaledToFit()
        .frame(maxHeight: .infinity)
        .background(Color.black)
        .edgesIgnoringSafeArea(.all)
    }
}