Search code examples
iosswiftsqlclient

SqlClient on ios executes after all other code in function


I am writing IOS application that uses this project: https://github.com/martinrybak/SQLClient . I have a problem with communicating with SQL with code below. It doesn't execute first time it meets connect function. It goes to next lines and after all code is made in viewDidLoad it goes back to my connect method, connects succesfuly. How to make it to execute it's code first and all other code before? Is it something in swift and ios programming i don't understand yet?

  override func viewDidLoad() {
            super.viewDidLoad()

            let client = SQLClient.sharedInstance()


            client?.connect(Constants.serwerAdress, username: Constants.userName, password: Constants.password, database: Constants.databaseName) {
                success in

                if success {
                    client?.execute("select A FROM B") {
                        results in

                        for table in results as AnyObject! as! NSArray {
                            for row in table as AnyObject! as! NSArray {

                                for column in row as! NSDictionary {

                                    print("\(column.key) = \(column.value)")
                                }
                            }
                        }
                        client?.disconnect()
                    }
                }
            }

    DoSomethingElse()

        }

Solution

  • Move your DoSomethingElse to connect success closure.

    override func viewDidLoad() {
                super.viewDidLoad()
    
                let client = SQLClient.sharedInstance()
    
    
                client?.connect(Constants.serwerAdress, username: Constants.userName, password: Constants.password, database: Constants.databaseName) {
                    success in
    
                    if success {
                        client?.execute("select A FROM B") {
                            results in
    
                            for table in results as AnyObject! as! NSArray {
                                for row in table as AnyObject! as! NSArray {
    
                                    for column in row as! NSDictionary {
    
                                        print("\(column.key) = \(column.value)")
                                    }
                                }
                            }
                            client?.disconnect()
                            DoSomethingElse()
                        }
                    }
                }
    
            }
    

    Methods in your code like connect, execute takes closure as argument. Which clearly indicates that these functions are async in nature and will execute the args asynchronously. So obviously you cant write it as next line to connect and execute once connect finishes executing.

    EDIT:

    Is calling DoSomethingElse() inside connect/execute is the only way to handle this scenario? Nope.

    Possible solutions to consider which I can think off:

    1. You can use KVO. : Set the observer to your data source when connect/execute updates the data source you can call your DoSomethingElse. If you ask me I prefer more cleaner approach :)

    2. Use Semaphores or dispatch_semaphores (better compared to semaphores) to block thread : Not at all a suggested solution!!. Blocking the main thread with semaphore/dispatch_semaphores might lead to iOS killing ur app for being non responsive and might provide worst user experience.

    3. Use Dispatch_Group : Dispatch_Group is used to monitor the completion of independent blocks. This Can be considered. But I prefer calling method from inside the closure. Keeps code cleaner :)