I have created NSURLConnection method swizzling for sendSynchronousRequest, however its not been working below is my code. Whenever I am trying to call this from main function, its crashing.
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
}
There's a couple of things that might cause problems:
error
parameter, but is a throwing function. Also, unlike your swizzled method, sendSynchronousRequest
takes a URLRequest
instead of an NSURLRequest
.sendSynchronousRequest
is exposed to Swift as a throwing function. It works if your swizzled function is not marked with throws
, but throwing functions can't be exposed to ObjC and might cause issues when being swizzled.Here is some working code for a 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)
}
Regardless, I think it would be a better idea to perform swizzling in Objective-C. There's much better documentation on how to do that, and you can avoid pitfalls in Swift <-> Objective-C bridging magic.