【问题标题】:'self' used in method call 'getBooks' before all stored properties are initialized在初始化所有存储的属性之前,在方法调用“getBooks”中使用“self”
【发布时间】:2021-08-03 14:16:05
【问题描述】:

当我在 HomeViewModel 中调用 getBooks() 进行初始化时,会出现此错误 ===> 在初始化所有存储的属性之前,在方法调用“getBooks”中使用“self”

这是初始化

init() {
    
    getBooks()
    filterModelObservable = searchValueBehavior
        .map { $0 }
        .throttle(.milliseconds(500), scheduler: MainScheduler.instance)
        .distinctUntilChanged()
        .withLatestFrom(homeModelSubject) { searchValue, books in
            searchValue.isEmpty ? books : books.filter { $0.name.lowercased().contains(searchValue.lowercased()) }
        }
}

这是 getBooks() 函数

func getBooks() {
    loadingBehavior.accept(true)
    let url = "https://simple-books-api.glitch.me/books"
    APIServices.instance.getData(url: url, method: .get, params: nil, encoding: JSONEncoding.default, headers: nil) {[weak self] (bookModel: [Book]?, baseError: HomeBaseError?, error) in
        guard let self = self else { return }
        self.loadingBehavior.accept(false)
        if let error = error {
            //handler(false, "Error message\(error.localizedDescription.description)")
            print("this is error discription\(error.localizedDescription)")
        } else if let baseError = baseError {
            //handler(false,baseError.error)
            print(baseError.error)
        } else {
            guard let bookModel = bookModel else { return }
            //handler(true, "Success")
            if bookModel.count  > 0 {
                self.homeModelSubject.onNext(bookModel)
                self.isTableHidden.accept(false)
            } else {
                self.isTableHidden.accept(true)
            }
        }
    }
    
}

【问题讨论】:

  • 错误在所有存储的属性被初始化之前的意思。在调用self.getBooks 之前,必须初始化所有没有默认值的属性。我猜存储的属性是filterModelObservable 所以首先初始化filterModelObservable 然后调用getBooks()

标签: ios rx-swift


【解决方案1】:

这里的问题是您试图不加选择地将命令式代码与 Rx 代码混合在一起。你的班级中有太多的科目和接力,这使得你想要完成的工作比它需要的要困难得多......看看这个:

class HomeViewModel {
    let filterModelObservable: Observable<[Book]>
    let isLoading: Observable<Bool>
    let isTableHidden: Observable<Bool>
    let homeModel: Observable<[Book]>
    
    var searchValueObserver: AnyObserver<String?> { searchValueBehavior.asObserver() }
    private let searchValueBehavior = BehaviorSubject<String?>(value: "")
    
    init() {
        let url = "https://simple-books-api.glitch.me/books"
        homeModel = APIServices.instance.rx_getData(url: url, method: .get, params: nil, encoding: .default, headers: nil)
            .catch { error in
                print("this is error discription\(error.localizedDescription)")
                return .just([])
            }
            .share()
        
        isLoading = homeModel
            .map { _ in false }
            .startWith(true)
        
        isTableHidden = homeModel
            .map { $0.isEmpty }
        
        filterModelObservable = Observable.combineLatest(
            searchValueBehavior
                .map { $0 ?? "" }
                .startWith("")
                .throttle(.milliseconds(500), scheduler: MainScheduler.instance),
            homeModel
        )
        .map { searchValue, books in
            searchValue.isEmpty ? books : books.filter { $0.name.lowercased().contains(searchValue.lowercased()) }
        }
    }
}

extension APIServices {
    func rx_getData(url: String, method: Method, params: [String: String]?, encoding: JSONEncoding, headers: [String: String]?) -> Observable<[Book]> {
        Observable.create { [self] observer in
            getData(url: url, method: method, params: params, encoding: encoding, headers: headers) { books, baseError, error in
                if let books = books {
                    observer.onNext(books)
                    observer.onCompleted()
                }
                else {
                    observer.onError(error ?? baseError?.error ?? RxError.unknown)
                }
            }
            return Disposables.create()
        }
    }
}

注意我是如何定义一个 rx_getData 扩展的,它完成网络调用所需的最低限度并立即将其转换为 Observable,而不是尝试在闭包中做一堆工作。

通过这样做,我们可以在创建时定义其他 Observable 的所有动态行为...

isLoading observable 以 true 开头,然后在 homeModel 发出时发出 false。从其定义中可以清楚地看出这一点。

isTableHidden 在网络请求返回时发出;如果数组为空则为真,否则为假。

filterModelObservable 也可以。

请注意代码的清晰程度,以及您只需查看一处即可了解您需要了解的有关视图模型的特定属性的所有信息。

如果您停止过度使用主题和中继,您的代码将更加清晰易懂。

【讨论】:

    猜你喜欢
    • 2022-11-09
    • 2016-04-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-12
    • 1970-01-01
    相关资源
    最近更新 更多