Using Variables Outside of Completion Block

using variables outside of completion block

The entire purpose of the completion parameter of userBinfo is to provide a mechanism for being informed when the asynchronous observeEventType is called. So put code contingent upon the completion of that asynchronous method inside the userBinfo { user in ... } closure.

And if part of the UI doesn't make sense until that asynchronous completion closure is called, then have viewDidLoad configure the UI to make that explicit (perhaps show a UIActivityIndicatorView or whatever) and then remove that stuff inside the completion handler.

override func viewDidLoad() {
super.viewDidLoad()

// do whatever you want to let the user know that something asynchronous
// is happening, e.g. add a spinning `UIActivityIndicatorView` or whatever

userBinfo { user in
self.userBinfos = user

// Update the UI here, including removing anything we presented to let
// the user know that the asynchronous process was underway. If you were
// dealing with UITableView`, you'd call `tableView.reloadData()` here.
}

// but not here
}

Accessing variable out completion block

By default, calling checkCreateTabPermission as:

checkCreateTabPermission { pass, employee, cancel in
// here you can use the `employee`
}

should make you able to access the returned employee. So, you could call the needed method inside the completion of checkCreateTabPermission:

checkCreateTabPermission { pass, employee, cancel in
myMethod(employee: employee)
}

Or if you want to access the employee outside of the completion, you could declare a variable (which is nil by default) to hold its value once it returned:

var myEmployee: Employee?

checkCreateTabPermission { [weak self] pass, employee, cancel in
self?.myEmployee = employee
}

// you could use `myEmployee` here, but you have to make sure its not nil,
// in other words, `checkCreateTabPermission` has been called and retrieved one.
if let myUnwrappedEmployee = myEmployee {
// use `myUnwrappedEmployee`...
}

How can I retain a local variable that is set in a completion block?

Call a new function inside the block. Do what you want to do with fileURL inside the new method.

FileFactory.FetchFileWithURL(workingURL, completionHandler: { (url) ->    Void in
fileURL = url
print(fileURL) //prints valid URLs
doSomethingWithFileUrl(url)
})

Variable becomes nil outside completion handler

You can't "fix" it in the way you'd like, unfortunately. The completion handler here might in theory be called synchronously (ie, at the time of the call to requestContentEditingInput), but can (and most likely will) be called at some time later, when the asset is ready. That could include actual downloading or any other unpredictable time-consuming preparation of the asset that happens on some other thread.

In other words, the function requestContentEditingInput returns to you right away (and your code continues executing), but the function also commences doing some work in the background. That background work, when it finishes, calls your handler block.

The nature of execution flow means that you simply cannot guarantee (and certainly cannot assume) that the handler will be called before execution moves on to your print(imageURL) line.

This kind of asynchronicity is a very common pattern, though! Nothing to be afraid of. You need to put any code that must run subsequently within that handler block (or call out from the handler block to another function if that is cleaner within your file).

Swift- updating global variable outside closure with completion handler

Code in function doURLsessions is asynchronous - it isn't blocking other code from executing and since it is a network request it takes some time to finish. In your case print(arrFromURL) is called before doURLsessions is finished so arrFromURL is still empty.

Storing the values from completion handler into a variable

The issue isn't a matter of scope, it's that the log is called before the completion block. The reverse geocode call is asynchronous. It will return the block whenever it's done with what it's doing, but in the meantime, the rest of your method will execute. If you print co the line after you set its value but within the completion block, it will display the correct value.

Example:

[geocoder reverseGeocodeLocation:locationManager.location
completionHandler:^(NSArray *placemarks, NSError *error) {
NSLog(@"reverseGeocodeLocation:completionHandler: Completion Handler called!");

if (error){
NSLog(@"Geocode failed with error: %@", error);
return;

}


CLPlacemark *placemark = [placemarks objectAtIndex:0];



NSLog(@"placemark.country %@",placemark.country);
co = placemark.country;

// The completion block has returned and co has been set. The value equals placemark.country
NSLog(@"%@",co);
}];
// This log is executed before the completion handler. co has not yet been set, the value is nil
NSLog(@"%@",co);

If you need to use the co variable outside of the block, you should call the methods it will be used in from within the completion block:

[geocoder reverseGeocodeLocation:locationManager.location
completionHandler:^(NSArray *placemarks, NSError *error) {

[self myMethodWithCountry:placemark.country];

}];

- (void)myMethodWithCountry:(NSString *)country {
// country == placemark.country
}

How to use variables outside of .observe

Your best option is to call needed function at the end of the closure, but outside of the 'for' loop. This way you will have the dictionary populated, and still be on the same thread.
Other options are - adding a completion block and creating a protocol (can't elaborate more on these two since not comfortable with them myself).



Related Topics



Leave a reply



Submit