Shemil Hashan
Shemil Hashan

Reputation: 67

IOS SWIFT - Return response data when service call finish fetching

I have a web service which returns response in json. I created a separate class for data access in xcode(swift) for iphone. What I want to do is call a function in the data access layer, which returns the response dictionary, WHEN FETCHING IS COMPLETE.
Problem: How return ONLY WHEN fetching from service is complete.
Ex: Student Table->Click a student->Fetch data of student->Return data when fetching completes

func getUser(userID:String)->NSDictionary{

        let manager = AFHTTPRequestOperationManager()
        let parameters = ["uid":userID]
        manager.POST(urlStudentInfo, parameters: parameters,
            success: {(operation: AFHTTPRequestOperation!,responseObject: AnyObject!) in
                print("JSON success: " + responseObject.description)
                if let responseDic = responseObject as? NSDictionary{
                    let isUser = responseDic["status"] as! Bool
                    
                    if isUser{
                        
                        
                        
                    }else{
                        
                    }
                }
                
            },
            
            failure: { (operation: AFHTTPRequestOperation!,error: NSError!) in
                
        })

    return response

}

This is my function structure. Problem is fetching happens after the return is done. So the return is always nil.

Anyone have a suggestion to return only after fetching is complete?

Upvotes: 1

Views: 1816

Answers (2)

Rob
Rob

Reputation: 438232

Because you are calling an asynchronous method, you should not attempt to immediately return a value. Instead, provide a "completion handler" closure that you can call when the results are later returned.

I'd also suggest using AFNetworking 3.x, at the very least (because the AFHTTPRequestOperationManager of AFNetworking 2.x uses NSURLConnection, which is now deprecated):

func getUser(userID:String, completionHandler: (NSDictionary?, NSError?) -> ()) {
    let manager = AFHTTPSessionManager()
    let parameters = ["uid":userID]
    manager.POST(urlStudentInfo, parameters: parameters, progress: nil, success: { task, responseObject in
        if let responseDic = responseObject as? NSDictionary, let isUser = responseDic["status"] as? Bool {
            if isUser{
                completionHandler(responseDic, nil)
            } else {
                let error = NSError(domain: NSBundle.mainBundle().bundleIdentifier!, code: 1, userInfo: [NSLocalizedDescriptionKey: "status false"])
                completionHandler(nil, error)
            }
        } else {
            let error = NSError(domain: NSBundle.mainBundle().bundleIdentifier!, code: 2, userInfo: [NSLocalizedDescriptionKey: "Response not dictionary; or status not found"])
            completionHandler(nil, error)
        }
    }, failure: { task, error in
        completionHandler(nil, error)
    })
}

And you'd call it like so:

getUser(userID) { responseDictionary, error in
    guard responseDictionary != nil && error == nil else {
        print(error)
        return
    }

    // do something with responseDictionary here
}

// but do not try to use responseDictionary here, because the above runs asynchronously

Or, even better, you might consider using Alamofire. See https://stackoverflow.com/a/27393174/1271826 for example.

Upvotes: 0

Fonix
Fonix

Reputation: 11597

What does your {callService} actually look like? does it have a completion handler? but in general, asynchronous functions like webservices cant be thought of in the same way as a normal function, you need to launch the ws call in one function, then call another function to let something know its finished from the completion handler, or whatever lets the ws function know its completed. So in short, you shouldnt be trying to return anything from that function, and instead return the value from the completion handler

edit:

I would advise not to use NSNotifications, but rather delegate callbacks, or simply just use the data inside the completion handler directly. but whatever is trying to use that returned NSDictionary should instead be a delegate of the class this function is in (look up tutorials on protocols if you dont know how it works), then you can pass the dictionary back through the delegates callbacks inside the completion handler (think of how UITableviews make you implement all those functions to make it work, you need to make something similar for your webservice call)

this answer might help you understand what i mean

Upvotes: 1

Related Questions