iOS 中的 NSURLConnection 调配

NSURLConnection swizzling in iOS

我已经为 sendSynchronousRequest 创建了 NSURLConnection 方法 swizzling,但是它没有工作下面是我的代码。每当我试图从主函数调用它时,它就会崩溃。

    let originalRequestSyncSelector = #selector(self.sendSynchronousRequest(_:returning:))
    let swizzledRequestSyncSelector = #selector(self.swizzSendSynchronousRequest(_:returning:error:))

    let originalSyncRequestMethod = class_getClassMethod(self, originalRequestSyncSelector)
    let swizzledSyncRequestMethod = class_getInstanceMethod(self, swizzledRequestSyncSelector)

    if originalSyncRequestMethod == nil || swizzledSyncRequestMethod == nil {
      return
    }
    method_exchangeImplementations(originalSyncRequestMethod!, swizzledSyncRequestMethod!)


  @objc func swizzSendSynchronousRequest(_ request: NSURLRequest?, returning response: URLResponse?, error: Error?) -> Data? {

    var tempData: Data?
    print("Inside Sync Swizzled Method")
    print("------------\(String(describing: request))")
    return tempData
  }

有几件事可能会导致问题:

  1. 方法签名不同。原始实现没有 error 参数,而是一个抛出函数。此外,与您的 swizzled 方法不同,sendSynchronousRequest 采用 URLRequest 而不是 NSURLRequest.
  2. 您正在调配一个实例和一个 class 方法。我不确定如何(或是否)使它起作用。
  3. sendSynchronousRequest 作为抛出函数暴露给 Swift。如果您的 swizzled 函数未标记 throws,它会起作用,但抛出函数不能暴露给 ObjC,并且在被 swizzled 时可能会导致问题。

这里有一些 playground 的工作代码:

import Foundation
import ObjectiveC

extension NSURLConnection {
    @objc static func swizzSendSynchronousRequest(_ request: URLRequest?, returning response: URLResponse?) -> Data? {

        print("Inside Sync Swizzled Method")
        print("------------\(String(describing: request))")
        return Data()
    }
}

let originalRequestSyncSelector = #selector(NSURLConnection.sendSynchronousRequest(_:returning:))
let swizzledRequestSyncSelector = #selector(NSURLConnection.swizzSendSynchronousRequest(_:returning:))

let originalSyncRequestMethod = class_getClassMethod(NSURLConnection.self, originalRequestSyncSelector)
let swizzledSyncRequestMethod = class_getClassMethod(NSURLConnection.self, swizzledRequestSyncSelector)

method_exchangeImplementations(originalSyncRequestMethod!, swizzledSyncRequestMethod!)


let request = URLRequest(url: URL(string: "https://example.com")!)
do {
    let data = try NSURLConnection.sendSynchronousRequest(request, returning: nil)
    print(data)
} catch {
    print(error)
}

无论如何,我认为在 Objective-C 中执行混合会是一个更好的主意。 much better documentation 介绍了如何做到这一点,您可以在 Swift <-> Objective-C 桥接魔法中避免陷阱。