为什么我的方法不被调用?

时间:2016-12-24 14:48:03

标签: swift delegates protocols

我有一个viewController使用DownloaderDelegate协议与DownloaderHandler进行通信。

我的协议定义为:

protocol DownloaderDelegate : class {

    func didReceive(data:Data)
}

我有一个viewController

class ViewController: UIViewController {
weak var downloadHandler : DownloaderHandler?    

override func viewDidLoad() {
    super.viewDidLoad()
    downloadHandler = DownloaderHandler()
    downloadHandler?.delegate = self
    changeBackground() 

}

 func changeBackground (){
        let googleURL = URL(fileURLWithPath: "https://www.google.com/doodle4google/images/splashes/featured.png")
        print(googleURL)
        downloadHandler?.downloadData(url:googleURL) // Line BB
    }
}

extension ViewController : DownloaderDelegate{
    func didReceive(data: Data) {
        let image = UIImage(data: data)
        let imageView = UIImageView(image: image!)
        view.insertSubview(imageView, at: 0)
    }
}

我有一个委托课程:

class DownloaderHandler : NSObject, URLSessionDelegate{
    weak var delegate :DownloaderDelegate?
    var downloadsSession: URLSession = {
        let configuration = URLSessionConfiguration.default
        let session = URLSession(configuration: configuration)
        return session // Line AA
    }()

    func downloadData(url: URL){ // Line CC
        downloadsSession.dataTask(with: url){ data, response, error in
            print("error is \(error), data is \(data) and response is \(response)") // Line DD

            if let badError = error {
                print(" the url didn't succeeed error is \(badError.localizedDescription)")
            }
            else if let someResponse = response as? HTTPURLResponse {
                if someResponse.statusCode == 200{
                    self.delegate?.didReceive(data: data!)
                }
            }

        }

    }
}

使用断点:行AA,加载。线路BB呼叫。线CC永远不会被调用。为什么?我究竟做错了什么?!

2 个答案:

答案 0 :(得分:4)

您已声明:

weak var downloadHandler : DownloaderHandler?    

然后你说:

downloadHandler = DownloaderHandler()

downloadHandlerweak引用,没有其他任何内容保留此DownloaderHandler实例,因此它在创建后会在一团烟雾中消失。您的日志记录显示它正在创建,但如果您要登录其deinit,您也会看到它立即消失。当您说downloadHandler?.downloadData(url:googleURL)时,您的downloadHandler引用为nil,因此没有任何反应;那时你正在和没人说话。

[你可能会盲目地遵循一个心理规则,委托引用应该是弱的。但是这个规则是基于代表具有独立存在的假设,因此不应该拥有"拥有"由推荐人。然而,这个对象没有独立存在;它更像是一个装饰对象(我称之为助手)。因此,参考需要很强。反向引用仍然很弱,因此您不会获得循环保留周期。]

答案 1 :(得分:1)

删除"弱"来自视图控制器上的downloadHandler属性的限定符。

由于它是对downloadHandler对象的唯一引用,因此只要viewDidLoad方法完成执行,它就会从内存中删除。

你可以做一个小测试;在BB行添加一个断点,检查downloadHandler是否有值。我怀疑它会是" nil",因为它是一个弱小的属性。