1

I have following callback in block in Objective C

typedef void (^COMPLETION_BLOCK)(NSString *response, NSError *errorString);

+ (void)responseFromURL:(NSURL *)url completionBlock:(COMPLETION_BLOCK)completionBlock
{
   __block  NSError *error = nil;    
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
        NSString *response = [NSString stringWithContentsOfURL:url
                                                      encoding:NSUTF8StringEncoding
                                                         error:&error];

        dispatch_async(dispatch_get_main_queue(), ^{
                completionBlock(response, error);
        });
    });
}

Here is how i call it in Objective C

[Utilities responseFromURL:NSURL URLWithString:@""] completionBlock:^(NSString *response, NSError *errorString)
{

}]

I have tried converting this in Clousers in swift here is the code

class Utilities
{
    typealias COMPLETION_BLOCK = ( response : NSString, error : NSError) -> ()

    func responseFromURL(url: NSURL , completionBlock:COMPLETION_BLOCK)
    {
        let priority = DISPATCH_QUEUE_PRIORITY_DEFAULT
        var e : NSError?;

        dispatch_async(dispatch_get_global_queue(priority, 0))
        {
            var content:NSString? = NSString(contentsOfURL: url,
                encoding: NSUTF8StringEncoding,
                error: &e)

            dispatch_async(dispatch_get_main_queue())
            {
                completionBlock(response: content!,error:  e!);
            }
        }
    }
}

I am not sure if this is correct conversion. Secondly how am i suppose to call the block in swift?

var urlString = String(format: BASE_URL + "%d", categoryType);
        var url = NSURL(string :urlString);

1 Answer 1

3

You are almost there. You don't need the typealias as you can specify the completionBlock in the function definition.

One thing that would cause you problems is the forced unwrapping of content & e one of which is going to be nil.

Here is my version of your function:

func responseFromURL(url : NSURL, completionBlock : (response : String?, error : NSError?) -> Void) {
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0)) {
        var error : NSError? = nil
        let response = String(contentsOfURL: url, encoding: NSUTF8StringEncoding, error: &error)

        dispatch_async(dispatch_get_main_queue()) {
            completionBlock(response: response, error: error)
        }
    }
}

And to call it:

responseFromURL(myURL) { (response, error) in
    if error != nil {
        // handle error
    }
    else if response != nil {
        // data came back
    }
}

A couple of points to notice:

  • in the completion block definition, I specified that both response and error parameters are optionals. You should get one or the other back, but you need to check which one.
  • unlike in Objective-C, you do not have to send in a pointer to the error. The completion handler will send you back an error if it needs to.
  • I used the shorter form of Swift closures but if you let auto-complete do its thing, you will get the longer form which may be more readable.
Sign up to request clarification or add additional context in comments.

2 Comments

please check my edited code, this is the myUrl i am trying to pass in ur code however it is giving error, extra argument in call. Secondly there is orange line on entire code below it . I have tried to access it using Utilities.responseFromUrl See my code how i am defining function in utilities
nvrmind needed to make it static, Fixed it, Thanks :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.