Crash DispatchQueue async with swift

时间:2019-03-19 14:54:51

标签: swift

Hello the following code generates this exception for me, this app connect to remote node.js api rest server and get value for setup application. These values ​​are used to build a custom menu based on the rest calls made to node.js the values ​​are verified with return calls boolean type value the strange thing is that it generates an app crash on the threads

Error:

Main Thread Checker: UI API called on a background thread: -..
2019-03-19 15:52:03.255375+0100 myapp[441:34081] [reports] Main Thread Checker: UI API called on a background thread: -[UIApplication delegate]
PID: 441, TID: 34081, Thread name: (none), Queue name: com.apple.root.user-interactive-qos, QoS: 33
Backtrace:
4   myapp                               0x00000001005ca3ac $S5myapp8DatabaseC12GetServerURLSSyF + 112
5   myapp                               0x00000001005c66a4 $S5myapp4JSONC15GetSingleString6Router10ValueArray10completionySS_SDySSypGySSctF + 608
6   myapp                               0x0000000100617a08 $S5myapp9UserModelC16VerificaPermesso09TipologiaE010completionySS_ySSctFyycfU_ + 456
7   myapp                               0x0000000100566510 $SIeg_IeyB_TR + 52
8   libdispatch.dylib                   0x00000001017f7824 _dispatch_call_block_and_release + 24
9   libdispatch.dylib                   0x00000001017f8dc8 _dispatch_client_callout + 16
10  libdispatch.dylib                   0x000000010180a330 _dispatch_root_queue_drain + 716
11  libdispatch.dylib                   0x000000010180abc8 _dispatch_worker_thread2 + 156
12  libsystem_pthread.dylib             0x000000018404d17c _pthread_wqthread + 472
13  libsystem_pthread.dylib             0x000000018404fcec start_wqthread + 4

Code:

DispatchQueue.main.async {
            //Controllo permesso accesso cantieri
            self.u = User()


            //Controllo permesso accesso Clienti
            self.u.VerificaPermesso(TipologiaPermesso: "clienti", completion: { result in
                DispatchQueue.main.async {
                    if(result == "false") {
                        viewControllerList.remove(at: 4)
                        self.viewControllers = viewControllerList
                    }
                }
            });

            //Controllo permesso accesso Articoli
            self.u.VerificaPermesso(TipologiaPermesso: "articoli", completion: { result in
                DispatchQueue.main.async {
                    if(result == "false") {
                        viewControllerList.remove(at: 2)
                        self.viewControllers = viewControllerList
                    }
                }
            });

            //Controllo permesso accesso Magazzino
            self.u.VerificaPermesso(TipologiaPermesso: "magazzino", completion: { result in
                DispatchQueue.main.async {
                    if(result == "false") {
                        viewControllerList.remove(at: 5)
                        self.viewControllers = viewControllerList
                    }
                }
            });

            self.u.VerificaPermesso(TipologiaPermesso: "cantieri", completion: { result in
                DispatchQueue.main.async {
                    if(result == "false") {
                        viewControllerList.remove(at: 1)
                        self.viewControllers = viewControllerList
                    }
                }
            });


        }

GetServerUrl Code:

func GetServerURL() -> String {

        let appDelegate = UIApplication.shared.delegate as! AppDelegate

        let context = appDelegate.persistentContainer.viewContext
        let request = NSFetchRequest<NSFetchRequestResult>(entityName: "Setup")
        request.returnsObjectsAsFaults = false;
        do {
            let result = try context.fetch(request)
            if result.count > 0
                {
                for result in result as! [NSManagedObject] {
                    if let server = result.value(forKey: "server")as? String
                        {
                        self.serverSet = server

                    }

                    if let port = result.value(forKey: "port") as? Int32
                        {
                        self.portSet = "\(port)"
                    }
                }
            }
        }
        catch {
            print("Errore caricamento Parametri DB \(error)")

        }
        var ret = "\(serverSet):\(portSet)"
        if(serverSet == "" || portSet == "") {
            ret = ""
        }
        return ret

    }

1 个答案:

答案 0 :(得分:1)

According to your crashlog inside of myapp.Database.GetServerURL you trying to access UIApplication.shared.delegate which is UIKit api and should be performed on main thread.
Possible solutions:

  • Wrap this call in DispatchQueue.main.sync { ... }.
    This will fix your error, but code smell and design error will stay and could hit you again in future
  • Move this code from AppDelegate to model dependent layer.
    Since it's database related call, consider moving it inside separate Database service that maybe singleton (DB is good example of possible usage of singletons)
相关问题