Wait for completion before executing next step - swift

I have a few processes that need to be completed in order when my TableView loads. I would expect that it would wait until the code completed before executing the next line of code, but it seems that's not the case. Is there a way to have these wait until completion before executing the next step?
override func viewDidLoad() {
super.viewDidLoad()
performTask1()
performTask2()
performTask3()
}
Thanks for all the help!

The typical example to make each of these methods take a completionHandler parameter, e.g.:
func perform1(completionHandler: () -> Void) {
doSomethingAsynchronously() {
completionHandler()
}
}
func perform2(completionHandler: () -> Void) {
doSomethingElseAsynchronously() {
completionHandler()
}
}
func perform3(completionHandler: () -> Void) {
doSomethingCompletelyDifferentAsynchronously() {
completionHandler()
}
}
Then you can run them like so:
override func viewDidLoad() {
super.viewDidLoad()
perform1 {
self.perform2 {
self.perform3 {
}
}
}
}

Related

UI testing functions within test Class

I am implementing UI testing and I have created a 900 lines test class. This file contains 16 different tests that I would like to have lest separately in the left pane so that I can run specific ones as required. However, when I include the 16 funcs there are no tests listed. When I comment out the 16 funcs, I can see (and run) all the tests as a single line.
Here is the structure of the 16 funcs.
import XCTest
class zeroCounts: XCTestCase {
override func setUp() {
super.setUp()
continueAfterFailure = false
XCUIApplication().launch()
}
override func tearDown() {
super.tearDown()
}
func tests() {
testsRun = 0
currentRow = 0
func case_0000() {
// Do stuff
}
func case_0001() {
// Do stuff
}
func case_0010() {
// Do stuff
}
func case_0011() {
// Do stuff
}
func case_0100() {
// Do stuff
}
func case_0101() {
// Do stuff
}
func case_0110() {
// Do stuff
}
func case_0111() {
// Do stuff
}
func case_1000() {
// Do stuff
}
func case_1001() {
// Do stuff
}
func case_1010() {
// Do stuff
}
func case_1011() {
// Do stuff
}
func case_1100() {
// Do stuff
}
func case_1101() {
// Do stuff
}
func case_1110() {
// Do stuff
}
func case_1111() {
// Do stuff
}
}
To fix this problem, rename your test functions to begin with test. The test runner will find those functions and show them in the navigation panel just like you want.
func test_1111() {
// Do stuff
}

Async tableview update in swift

What if i put my updater in viewWillAppear using dispatch_async? I don't know... it seems too simple. I can't understand this because in c# after my threads i used .Abort(). What about swift? Will my thread aborted after runtime?
override func viewWillAppear(animated: Bool)
{
super.viewWillAppear(animated)
let priority = DISPATCH_QUEUE_PRIORITY_DEFAULT
dispatch_async(dispatch_get_global_queue(priority, 0)) {
self.data = []
//some code with update
dispatch_async(dispatch_get_main_queue()) {
self.tableView.reloadData()
}
}
I would recommend something along these lines:
override func viewWillAppear(animated: Bool)
{
super.viewWillAppear(animated)
updateData()
}
func updateData() {
makeAsyncCall{ (data) -> () in
dispatch_async(dispatch_get_main_queue()) {
self.data = []
self.tableView.reloadData()
}
}
}
func makeAsyncCall(completion: ([DataType]) -> ()) {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
/* do data update */
completion(data)
}
}
It better breaks up the functionality, and as far as I know (untested) it shouldn't have any issues.

Unexpected defer behaviours

I have a function that does processing asynchronously:
func something(completion: [Something] -> Void) {
dispatch_async(queue) {
...
dispatch_async(dispatch_get_main_queue()) {
completion(something)
}
}
}
I thought it would be wise to use defer to guarantee that completion gets called every time, so I tried this:
func something(completion: [Something] -> Void) {
dispatch_async(queue) {
...
defer {
dispatch_async(dispatch_get_main_queue()) {
completion(something)
}
}
}
}
Working well. Then I tried to use a guard statement within the asynchronous dispatch that always failed, to see if defer will activate. It didn't:
func something(completion: [Something] -> Void) {
dispatch_async(queue) {
...
guard let shouldFail = ... else { return }
defer {
dispatch_async(dispatch_get_main_queue()) {
completion(something)
}
}
}
}
defer would not be called. Why?
Because you are using defer after returning. The compiler doesn't know that you specified defer instructions (because it returned already and didn't see any defer instructions in that point, so the next lines are not fired up). If you'd move defer {} before the guard, then it will be called.
guard will return before even getting to the defer. Try doing it the other way around:
func something(completion: [Something] -> Void) {
dispatch_async(queue) {
...
defer {
dispatch_async(dispatch_get_main_queue()) {
completion(something)
}
}
guard let shouldFail = ... else { return }
}
}

Async Download of Information from server

I want to download data from my server to be displayed on a map. Therefore I use async methods to get the data. The goal is to have an array of annotation objects to be displayed.
Therefore I first download Information A and then Information B. As both are async methods, I guess I need to wait for the completionHandler to return true so I know the data is loaded. This is easy for one method. But how do I handle to wait for both methods before the completionHandler of getInformationFromServer returns true and triggers therefore the addition of annotations?
override func viewWillAppear(animated: Bool) {
self.customizeInterface()
self.getInformationFromServer { (completed) -> Void in
if(completed) {
self.mapView.addAnnotations(self.annotationArray)
}
}
}
func getInformationFromServer(completionHandler: (completed: Bool) -> Void) {
getInformationFromServerA { (downloadCompleted) -> Void in
completionHandler(completed: downloadCompleted)
}
// HOW DO I MANAGE TO ONLY RETURN THE COMPLETION HANDLER TRUE WHEN
// BOTH FUNCTIONS RETURNED TRUE?
}
func getInformationFromServerA(completionHandler: (downloadCompleted: Bool) -> Void) {
Server().getJsonInformationFromServer(url: "aeds", completionHandler: { (response) -> Void in
self.parseAEDInformationToAnnotation(response["data"])
completionHandler(downloadCompleted: true)
})
}
func getInformationFromServerB(completionHandler: (downloadCompleted: Bool) -> Void) {
Server().getJsonInformationFromServer(url: "aeds", completionHandler: { (response) -> Void in
self.parseAEDInformationToAnnotation(response["data"])
completionHandler(downloadCompleted: true)
})
}
You may use a dispatch group to wait until both downloads finish.
func getInformationFromServer(completionHandler: (completed: Bool) -> Void) {
let dispatchGroup = dispatch_group_create()
var downloadCompletedA: Bool = false
dispatch_group_enter(dispatchGroup)
getInformationFromServerA { (downloadCompleted) -> Void in
downloadCompletedA = downloadCompleted
dispatch_group_leave(dispatchGroup)
}
var downloadCompletedB: Bool = false
dispatch_group_enter(dispatchGroup)
getInformationFromServerB { (downloadCompleted) -> Void in
downloadCompletedB = downloadCompleted
dispatch_group_leave(dispatchGroup)
}
// wait until both downloads are finished
dispatch_group_wait(dispatchGroup, DISPATCH_TIME_FOREVER)
completionHandler(downloadCompletedA && downloadCompletedB)
}
See Apple's Concurrency Programming Guide:
Dispatch groups are a way to block a thread until one or more tasks
finish executing. You can use this behavior in places where you cannot
make progress until all of the specified tasks are complete.
Another solution which I can recommend for you and it's not so "complex" as solution with dispatch_group_wait:
func getInformationFromServer(completionHandler: (completed: Bool) -> Void) {
getInformationFromServerA { [weak self] (downloadCompleted: Bool) -> Void in
if downloadCompleted {
self?.getInformationFromServerB({ (downloadCompleted: Bool) -> Void in
completionHandler(completed: downloadCompleted)
})
}
else {
completionHandler(completed: downloadCompleted)
}
}
}

How can I call this function in viewDidLoad() in iOS8

I want to call this function in viewDidLoad but I don't know how one would do this. Can you please help me?
func loginWithFacebook(withcompletionHandler: (success:Bool) ->()){
var permissions : Array = [ "user_location","public_profile"]
PFFacebookUtils.logInInBackgroundWithReadPermissions(permissions, {
(user: PFUser?, error: NSError?) -> Void in
if let user = user {
if user.isNew {
println("User SIGNED UP and logged in through Facebook!")
self.fetchUserInforFromFacebook(withcompletionHandler)
println("User logged in through Facebook!")
withcompletionHandler(success: true)
}
} else {
println("Uh oh. The user cancelled the FACEBOOK LOGIN.")
self.showErrorMessage(error!)
withcompletionHandler(success: false)
}
})
}
If you call function with in function
override func viewDidLoad() {
super.viewDidLoad()
self.loginWithFacebook { (success) -> () in
// Your code.
}
}
if you want call it in same function then
override func viewDidLoad() {
super.viewDidLoad()
loginWithFacebook { (success) -> () in
// Your code.
}
}
override func viewDidLoad() {
super.viewDidLoad()
self.loginWithFacebook { (success) -> () in
if success { //succeeded } else { //failed } }
}
}
So in order to call your method, add this to your viewDidLoad:
override func viewDidLoad() {
super.viewDidLoad()
self.loginWithFacebook { (success) -> () in
// Your code.
}
}