【问题标题】:Why delegate object is nil?为什么委托对象为零?
【发布时间】:2020-05-31 15:24:08
【问题描述】:

我在代理模式方面遇到了一些奇怪的问题,我无法让它像我期望的那样工作。我想我在这里遗漏了一些东西,但我自己无法弄清楚。

这是我的类的定义方式,

class NetworkManager {

    weak var delegate: DownloaderProtocol?

    func downloadFile(downloadUrl: URL ) {
        downloadTask(with: downloadUrl).resume()
    }

    func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
        delegate?.downloadCompleted(task: task, error: error)
    }
}


class DownloadManager: DownloaderProtocol {

    var networkManager: NetworkManager

    init(networkManager: NetworkManager) {
        self.networkManager = networkManager
    }

    func downloadMatches(urls: [String]) {
        self.networkManager.delegate = self

        for(....) {
            self.networkManager.downloadFile(url: url)
        }
    }

    func downloadCompleted(task: URLSessionTask, error: Error) {
        // Implementation
    }
}



class Matches {

    var networkManager: NetworkManager
    init() {
        self.networkManager = NetworkManager()
    }

    func getMatchSchedules(urls: [String] , completionHandler: @escaping (Result<Data, Error>) -> Void) {
        return DownloadManager.downloadMatches(urls: [String])
    }
}

有什么问题?

当调用 urlSession - didCompleteWithError 方法时,我可以看到委托对象为 nil

我尝试了什么?

  1. 如果我删除委托的弱引用,即weak var delegate: DownloaderProtocol?var delegate: DownloaderProtocol?,那么委托对象不是零。效果很好。
  2. 我什至尝试在 Matches 类中设置委托,但委托仍然显示为 nil

欢迎任何帮助或指出。

【问题讨论】:

  • 您的代码不清楚。但我倾向于说你的对象可能会被释放太子(范围问题?)。 return DownloadManager.downloadMatches(urls: [String]) 行很奇怪(静态函数,但没有声明为这样,没有返回等)
  • @Larme,对不起,我正在使用完成处理程序
  • 网络管理器中的其他变量似乎没有这个问题,只有委托是零。令人惊讶的是,我刚刚看到委托仅在调试模式下工作(带断点)
  • 菜鸟问题你在哪里分配网络管理器的代表,因为匹配实例没有对代表的引用,我看不到你在哪里设置 networkManager.delegate = DownloadManager()
  • @kjoe。也许您应该查看我设置委托的下载管理器类

标签: ios swift swift3 delegates


【解决方案1】:

我推荐这种方法,因为问题中发布的不是所有代码,而是相关的代码。

 class NetworkManager {

    weak var delegate: DownloaderProtocol?

    func downloadFile(downloadUrl: URL ) {
        downloadTask(with: downloadUrl).resume()
    }

    func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
        delegate?.downloadCompleted(task: task, error: error)
    }
}


class DownloadManager: DownloaderProtocol {

    var networkManager: NetworkManager

    init(networkManager: NetworkManager) {
        self.networkManager = networkManager
        self.networkManager.delegate = self
    }

    func downloadMatches(urls: [String]) {


        for url in urls {
            guard let url = URL(string: url) else {return}
            self.networkManager.downloadFile(downloadUrl: url)
        }
    }

    func downloadCompleted(task: URLSessionTask, error: Error) {
        // Implementation
    }
}



class Matches {

    var downloadManager: DownloadManager//NetworkManager
    init() {
        //self.networkManager = NetworkManager()
        //self.networkManager.delegate = DownloadManager()
        let networkManager = NetworkManager()
        self.downloadManager = DownloadManager(networkManager: networkManager)
    }

    func getMatchSchedules(urls: [String] , completionHandler: @escaping (Result<Data, Error>) -> Void) {
        return downloadManager.downloadMatches(urls: ["asadsdad"])
    }
}

您需要一个下载管理器,在创建匹配时具有网络管理器的匹配项创建网络管理器并设置为下载管理器的 init,以便您有一个委托集。

【讨论】:

    【解决方案2】:

    您可以使用回调代替委托。 这比委托更容易。

    typealias APIServiceSuccessCallback = ((Any?) -> ())
    

    ViewController A:

    //call from A -> B result fire if completionHandler fire in VC B
        addCompanyTargetsController.responseCreateBookingObj = { [unowned self] (returnObject) in
                        if let object = returnObject as? [String:Any] {
                            if object["success"] as? Bool == true {
                                self.loadTargetList()//success block
                            }
                        }
                    }
    

    视图控制器 B:

    var responseCreateBookingObj : APIServiceSuccessCallback? //declaration
    
    func completionHandler() { //from where you fire call this method
            guard let callBack = self.responseCreateBookingObj else{
                return
            }
            callBack( true as AnyObject)
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-04-09
      • 1970-01-01
      • 1970-01-01
      • 2015-08-13
      • 1970-01-01
      • 1970-01-01
      • 2012-01-30
      • 1970-01-01
      相关资源
      最近更新 更多