[NSURLSessionDataTask response]: unrecognized selector sent to instance - ios

I have the following issue:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSURLSessionDataTask response]: unrecognized selector sent to instance 0x7fced8599e60'
This is where it comes from:
GET("users/check_email", parameters: parameters, progress: nil, success: { sessionDataTask, response in
//the line with error
let statusCode = (sessionDataTask.response as? NSHTTPURLResponse)?.statusCode ?? 0
completionBlock(self.queryType?.mockStatusCode ?? statusCode, nil)
}) { sessionDataTask, error in
completionBlock(nil, NSError(responseError: error))
}
This happens when I try to mock a response. At some place of code I pass to success block:
var sessionDataTask = NSURLSessionDataTask()
success?(sessionDataTask, queryType?.mockResponse())
Something is wrong with sessionDataTask. NSURLSessionDataTask inherits from NSURLSessionTask which has response property. I don't know why I get this error.

If you declare your mock NSURLSessionDataTask like below, response will be nil.
Obj C:
NSURLSessionDataTask * sessionDataTask = [[NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]] dataTaskWithURL:[NSURL URLWithString:#""]];
[sessionDataTask response];
Swift:
var sessionDataTask = NSURLSessionDataTask(NSURLSession(sessionWithConfiguration:NSURLSessionConfiguration.defaultSessionConfiguration()).dataTaskWithURL(NSURL(string: "")))
sessionDataTask.response()

Apple documentation says:
public class NSURLSessionTask : NSObject, NSCopying {
#NSCopying public var response: NSURLResponse? { get } /* may be nil if no response has been received */
}
So the only solution for this in Swift is:
var statusCode = 0
if sessionDataTask.respondsToSelector(Selector("response")) {
statusCode = (sessionDataTask.response as? NSHTTPURLResponse)?.statusCode ?? 0
}

Related

How to write blocks (closures) in swift3 right way?

I am trying to find how I can write this blocks in swift3, any help would be appreciated.
I am using obj-c PocketSDK in swift3 project.
https://github.com/Pocket/Pocket-ObjC-SDK
I can use this SDK fine with proper Bridge-Header settings, but still not sure how I can write blocks part.
obj-c
[[PocketAPI sharedAPI] callAPIMethod:#"get"
withHTTPMethod:PocketAPIHTTPMethodGET
arguments:arguments
handler:^(PocketAPI *api, NSString *apiMethod, NSDictionary *response, NSError *error) {
}];
This is the type def in PocketSDK.
-(void)callAPIMethod:(NSString *)apiMethod withHTTPMethod:(PocketAPIHTTPMethod)HTTPMethod arguments:(NSDictionary *)arguments delegate:(id<PocketAPIDelegate>)delegate;
typedef void(^PocketAPIResponseHandler)(PocketAPI *api, NSString*apiMethod, NSDictionary *response, NSError *error);
swift? (This shows error.)
let arguments: [String: Any] = [
"state": "unread",
"count": 20
]
PocketAPI.shared().callMethod("get", with: PocketAPIHTTPMethodGET, arguments: arguments) {
(api: PocketAPI,
apiMethod: String,
esponse: [AnyHashable:Any],
error: Error) in
}
#Updated
I could avoid the compile error without type def, but still get the unrecognized selector if I put arguments. If I set nil in arguments, I don't get it though. Anything wrong with the dictionary?
var arguments = [String : Any]()
arguments["count"] = 20
arguments["state"] = "unread"
PocketAPI.shared().callMethod("get", with: PocketAPIHTTPMethodGET, arguments: arguments) {
(api,
apiMethod,
response,
error) in
}
Error.
-[_SwiftTypePreservingNSNumber length]: unrecognized selector sent to instance 0x174624540 2017-08-15 14:05:51.345611+0900
Voicepaper2[1062:286998] * Terminating app due to uncaught exception
'NSInvalidArgumentException', reason: '-[_SwiftTypePreservingNSNumber
length]: unrecognized selector sent to instance 0x174624540'
* First throw call stack:
Solved! This was the final answer, thanks!
let arguments: [String: Any] = [
"state": "unread",
"count": "20"
]
PocketAPI.shared().callMethod("get", with: PocketAPIHTTPMethodGET, arguments: arguments) {
(api,
apiMethod,
response,
error) in
}

None of the success and failure blocks are getting executing

This is my code
let url = URL(string: "http://demo6680989.mockable.io/getData")
let manager = AFHTTPSessionManager()
manager.get((url?.absoluteString)!, parameters: nil, progress: nil, success: {
(dataTask, responseObj) in
if let dict : NSDictionary = responseObj as? NSDictionary {
//print("Response: \(dict)")
AuditListParser().parseAudit(jsonData: dict)
}
}, failure: {
(dataTask, error) in
print(error.localizedDescription)
})
When I used this url in browser it is giving me some data but when i execute the above code it is neither going into success block nor fialure block.
1st time it was running properly and printed the data. I dont what happened suddenly, when i run it again this problem came
please help me
Normally, AFHTTPSessionManager's GET:(NSString *)URLString parameters:(NSDictionary *)parameters success:(void ( ^ ) ( NSURLSessionDataTask *task , id responseObject ))success failure:(void ( ^ ) ( NSURLSessionDataTask *task , NSError *error ))failure method returns NSURLSessionDataTask object. So, you should start that task somehow for it to return in success or failure block. Just get the object that is being returned from get() method, and call resume() method of that object. Good luck!
EDIT
Like this:
let task = manager.get((url?.absoluteString)!, parameters: nil, progress: nil, success: {
(dataTask, responseObj) in
if let dict : NSDictionary = responseObj as? NSDictionary {
//print("Response: \(dict)")
AuditListParser().parseAudit(jsonData: dict)
}
}, failure: {
(dataTask, error) in
print(error.localizedDescription)
})
task.resume()

Swift 3 timed event

I have the following:
let processURLS = processingViewController()
Timer.scheduledTimer(timeInterval: 1,
target: self,
selector: #selector(processURLS.getURLsToSend),
userInfo: nil,
repeats: true)
When this event is triggered, I received the following error and I'm not sure why this doesn't work
2016-11-09 14:47:00.504932 AcumenJLR[3414:905978] * Terminating app
due to uncaught exception 'NSInvalidArgumentException', reason:
'-[AcumenJLR.homeViewController getURLsToSend]: unrecognized selector
sent to instance 0x100d25c60'
* First throw call stack: (0x1816721c0 0x1800ac55c 0x181679278 0x181676278 0x18157059c 0x18215c8f8 0x1816208f4 0x181620608
0x18161fec4 0x18161dac0 0x18154c048 0x182fd2198 0x1875372fc
0x187532034 0x100114620 0x1805305b8) libc++abi.dylib: terminating with
uncaught exception of type NSException
Here is the getURLsToSend method
func getURLsToSend () {
//create a fetch request, telling it about the entity
let fetchRequest: NSFetchRequest<URLsToSend> = URLsToSend.fetchRequest()
let context = getContext()
do {
//Get results
let searchResults = try getContext().fetch(fetchRequest)
print ("num of results = \(searchResults.count)")
//You need to convert to NSManagedObject to use 'for' loops
for urls in searchResults as [NSManagedObject] {
//get the Key Value pairs (although there may be a better way to do that...
//print("\(urls.value(forKey: "url"))")
let currentURL = urls.value(forKey: "url")!
//print(urls.value(forKey: "url")!)
completeLoadAction(urlString: currentURL as! String) { code in
if (code == 200){
context.delete(urls)
}
}
}
} catch {
print("Error with request: \(error)")
}
According to the target / action pattern the method specified in selector must be declared in the class specified in target in this case the current class self.
Either change the target or implement the method in self.
May be you have some paramter in method but you are not sending any value from there

Receive response as NSDictionary instead of NSData

I'm trying to get the response from the server as NSDictionary instead of NSData, so first I'm using AFNetworking library and the server request these settings to be HTTP not JSON serializer as the following :
self.responseSerializer = AFHTTPResponseSerializer() as AFHTTPResponseSerializer
self.requestSerializer = AFHTTPRequestSerializer() as AFHTTPRequestSerializer
self.requestSerializer.HTTPMethodsEncodingParametersInURI = NSSet(array: ["GET"]) as! Set<String>
self.responseSerializer.acceptableContentTypes = NSSet(objects: "application/json","text/json","text/javascript","text/html") as? Set<String>
Next is when i get the response from the server it comes to be NSData and its because I'm using AFHTTPRequestSerializer() and here is my code :
self.POST(addUserURL, parameters: dictionary, progress: nil, success: { (task, responseObject) -> Void in
print(responseObject)
}) { (task, error) -> Void in
}
Also inside AFNetworking block its not allowed to handle try and catch for NSJSONSerializtion which can be a possible solution but it doesn't work.
Use NSJSONSerialization for that as shown in below code :
do {
let jsonObject = try NSJSONSerialization.JSONObjectWithData(responseObject, options: .AllowFragments) as! NSDictionary
// use jsonObject here
} catch {
print("json error: \(error)")
}
As response that you get from the server doesn't have top level object that is either Array or Dictionary you have to specify custom reading options in that should be used by AFNetworking.
In order to do that you have to set responseSerializer property on an instance of AFURLSessionManager class. You can do it as follows:
let sessionManager = OLFURLSessionManager.init() //you probably want to keep session manager as a singleton
sessionManager.responseSerializer = AFJSONResponseSerializer.serializerWithReadingOptions(.AllowFragments)
//you should use that instance of session manager to create you data tasks
After that you should be able to correctly parse response from the server as follows:

Passing SubClass Variable in sendSynchronousRequest Method in Swift

I have the following code:
var error : NSError?
var response : NSHTTPURLResponse?
var urlData : NSData = NSURLConnection.sendSynchronousRequest
(
request,
returningResponse: &response,
error: &error
) as NSData
returningResponse takes an instance of NSURLResponse as mentioned in the reference docs.
Im using NSHTTPURLResponse which is a subclass of NSURLResponse. This works fine in Objective-C but I do not know how to write this in Swift because the compiler throws an error on that line.
The error is:
Cannot convert the expression's type 'NSData' to type 'inout NSHTTPURLResponse'
What does this mean? and how to get it right?
The problem is that you are passing a different type than the method is expecting. You should still pass in NSURLResponse. You can cast the type afterwards:
var urlData = NSURLConnection.sendSynchronousRequest
(
request,
returningResponse: &response,
error: &error
)
if let httpResponse = response as? NSHTTPURLResponse {
// Work with HTTP response
}
Also note, the type of urlData can be inferred from the return type of the method. There is no need to specify the type nor convert the result to NSData so I removed both of those.

Resources