1

The NSURLProtocol documentation says it is possible to set a key-value and associate it with a request. The documentation calls it "tagging a request".

class func property(forKey: String, in: URLRequest)

Returns the property associated with the specified key in the specified request.

class func setProperty(Any, forKey: String, in: NSMutableURLRequest)

Sets the property associated with the specified key in the specified request.

My objective is to: from the outside of my MYURLProtocol, associate a value with a request, through a class/static method - and subsequently get it out again using a request.

This works:

class func methodOnURLProtocolConcreteClass(value: Any, request: URLRequest) {
    let mutableRequest = request as! NSMutableURLRequest
    URLProtocol.setProperty(value, forKey: "value", in: mutableRequest)
    let loadedValue = URLProtocol.property(forKey: "value", in: mutableRequest as URLRequest)
    print(loadedValue) // Success!, prints out value
}

// call site
MyURLProtocol.methodOnURLProtocolConcreteClass(value: "Hello", request: request)

So some casting is needed because the signatures of the getter and setter of the property uses NSMutableURLRequest to set the value and URLRequest to get it out again.

If I do the same thing, but spread out over 2 methods:

class func methodOnURLProtocolConcreteClass(value: Any, request: URLRequest) {
    let mutableRequest = request as! NSMutableURLRequest
    URLProtocol.setProperty(value, forKey: "value", in: mutableRequest)
}

class func anotherMethodOnURLProtocolConcreteClass(request: URLRequest) {
    let loadedValue = URLProtocol.property(forKey: "value", in: request)
    print(loadedValue) // Failure!, loadedValue is nil
}

// call site
MyURLProtocol.methodOnURLProtocolConcreteClass(value: "Hello", request: request)
MyURLProtocol.anotherMethodOnURLProtocolConcreteClass(request: request)

So my suspicion is that somewhere along the cast/conversion back and forth from Swift URLRequest to Obj-C NSMutableURLRequest this object is "shallow copied" or similar to create the Swift value type and that causes it to loose association with the properties store on it.

Thanks

RickiG
  • 11,380
  • 13
  • 81
  • 120
  • This looks related: https://stackoverflow.com/q/41189959/1187415. – Martin R Apr 13 '18 at 17:19
  • @MartinR yes that is exactly my case. As you can see he does it in the same scope and it works, but that answer also doesn't work if you call from separate methods. I actually suspect you can't make an NSURLProtocol implementation where you start a new request in startLoading using the common approach, values are not correctly registered on URLRequests through NSURLProtocol anymore :/ – RickiG Apr 16 '18 at 10:13
  • 1
    It seems to me that this solution https://stackoverflow.com/a/41190632/1187415 works for your case as well (which would make this question a duplicate). Did you try that approach? – Martin R Apr 16 '18 at 11:47
  • Did you check the solution in https://stackoverflow.com/a/41190632/1187415? It would be nice to know if that solves your problem or not. – Martin R Apr 26 '18 at 07:11
  • It doesn't work for me. Like @RickiG said, it works within the same scope, but when I try to read the property of the URLRequest when it's passed back to me, it always comes back `nil` – Doug McBride May 14 '20 at 00:27

0 Answers0