Search code examples
iosswiftgenericsswift3

How to call a generic method from a non generic method without completion handler in swift


I have this getData generic network call that has a completion handler:

func getData<K: Codable>(dataType : DataType, result: (Result<[K]>) -> Void) {
    networkManager.request(route: dataType) { (results:Result<[K]>) in
        switch results {
        case .success:
            switch dataType {
            case .users: self.networkDelegate.didLoadUserData()
            case .albums: self.networkDelegate.didLoadAlbumsData()
            case .comments: self.networkDelegate.didLoadCommentsData()
            case .photos: self.networkDelegate.didLoadPhotosData()
            case .posts: self.networkDelegate.didLoadPostData()
            case .todos: self.networkDelegate.didLoadTodosData()
            }
        case .error(let error): self.networkDelegate.onError(error: error)
        }
    }
}

And this is the call to that method:

router.getData(dataType: DataType.albums) { (result:Result<[PostModel]>) in
            //receives results but there is nothing to handle as the data is being sent via delegates
        }

I don't want to have a completion handler in router.getData(), because I would like to use delegates to notify my controller about the download state of the data.

So I did the same method (getData) but without the completion handler and the signature looks like this:

func getData<K:Codable>(dataType : DataType, result: Result<[K]>) {
        networkManager.request(route: dataType) { (results:Result<[K]>) in
            //here the delegates would call back my controller with the data 
        }
    }

the only difference is that now the call can be done without any completion handler block, so now Ideally I should be able to call it like this:

router.callToData(dataType: DataType.albums, result: (Result<[PostModel]>))

but I'm having an error :

Cannot convert value of type '(Result<[PostModel]>).Type' to expected argument type 'Result<[_]>'

Im trying everything but I cannot find a solution to this. Anyone can help?


Solution

  • func getData<K:Codable>(dataType : DataType, result: Result<[K]>) {}
    

    This says that you must pass a value of type Result<[K]>, but you wanted to pass the type for Result<[K]>, which would be this:

    func getData<K: Codable>(dataType : DataType, result: Result<[K]>.Type) {}
                                                                     ^^^^^
    

    And it would be called this way:

    getData(dataType: DataType.albums, result: Result<[PostModel]>.self)
                                                                  ^^^^^
    

    But I don't recommend that. Pass K itself, and this gets much simpler:

    func getData<K: Codable>(dataType : DataType, result: K.Type) {}
                                                          ^^^^^^
    getData(dataType: DataType.albums, result: PostModel.self)
                                               ^^^^^^^^^^^^^^