2016-03-25 41 views
0

以下は私のコードです。コアデータのManagedObjectContext.ExecuteFetchRequestを非同期で非同期にする方法

私に問題を与えている行はlet fetchRequest = try moc.executeFetchRequest(fetchRequest) as! [AppSettings]が非同期に読み込まれているように見えますが、それを同期的にロードして、ユーザー名レコードが正しくチェックされるようにします。

どうすればよいですか?

私はプログラムをいつでも起動して停止すると、エンティティが時間の約80%、ランダムに20%の時間が見つからないため、非同期で読み込まれることが分かります。 (私は常に、プログラムを起動し、停止していますので)他に何も実体を変えていないので、それはコードが、私は、コマンド

guard let appSettingsArrayItem = fetchRequest.first where fetchRequest.count>0 else { 
       print ("no entities found...") 
       return false 
      } 

を使用するときにそれはいずれかを見つけることができないasynchrnously実行されているという意味になるだろう時々エンティティ。チェックログイン機能

import UIKit 
import CoreData 

class LoginViewController: UIViewController, UITextFieldDelegate { 

    @IBOutlet weak var usernameField: UITextField! 
    @IBOutlet weak var passwordField: UITextField! 

    var isLoggedIn = false 

    let moc = DataController().managedObjectContext 

    @IBAction func SignUpButtonPressed(sender: UIButton) { 
     print("sign up") 
    } 

    func textFieldShouldReturn(textField: UITextField) -> Bool { 
     textField.resignFirstResponder() 
     return true 
    } 

    func textFieldShouldEndEditing(textField: UITextField) -> Bool { 
     textField.resignFirstResponder() 
     return true 
    } 


    override func viewDidLoad() { 
     super.viewDidLoad() 

     let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: "dismissKeyboard") 
     view.addGestureRecognizer(tap) 

     print("view loaded, check if already signed in here") 

     let loggedIn = checkIfLoggedInAlready() //checks database to see 

     if(loggedIn){ 
      print("was logged in!") 
      isLoggedIn = true 

      self.performSegueWithIdentifier("loginSegue", sender: self) 
     } 
    } 

    func checkIfLoggedInAlready() -> Bool{ 
     let fetchRequest = NSFetchRequest(entityName: "AppSettings") 
     //let deleteRequest = NSBatchDeleteRequest(fetchRequest: fetchRequest) //Deletes ALL appsettings entities 

     do { 

      let fetchRequest = try moc.executeFetchRequest(fetchRequest) as! [AppSettings] 

      guard let appSettingsArrayItem = fetchRequest.first where fetchRequest.count>0 else { 
       print ("no entities found...") 
       return false 
      } 

      guard let username = (appSettingsArrayItem as AppSettings).username else{ 
       print ("username not found") 
       return false 
      } 

      print("number Of AppSetting Entities =\(fetchRequest.count)") 
      print(username) 

      //The following code deletes ALL the entities! 
      //try moc.persistentStoreCoordinator!.executeRequest(deleteRequest, withContext: moc) 

      //To delete just '1' entry use the code below. 

      //moc.deleteObject(appSettingsArrayItem) 
      //try moc.save()//save deletion change. 

      //print("deleted particular entity item") 

      return true 
     } catch{ 
      fatalError("bad things happened \(error)") 
     } 


    } 

    func dismissKeyboard() { 
     //Causes the view (or one of its embedded text fields) to resign the first responder status. 
     view.endEditing(true) 
    } 

    override func didReceiveMemoryWarning() { 
     super.didReceiveMemoryWarning() 
     // Dispose of any resources that can be recreated. 
    } 

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) { 
     // Get the new view controller using segue.destinationViewController. 
     // Pass the selected object to the new view controller. 
     print("prepare seque") 
    } 

    func displayErrorMessage(errorMessage: String){ 
     print("show error console with Error:"+errorMessage) 
     let alert = UIAlertController(title: "Error", message: errorMessage, preferredStyle: UIAlertControllerStyle.Alert) 
     alert.addAction(UIAlertAction(title: "Ok", style: UIAlertActionStyle.Default, handler: nil)) 
     self.presentViewController(alert, animated: true, completion: nil) 
    } 

    override func shouldPerformSegueWithIdentifier(identifier: String, sender: AnyObject?) -> Bool { 
     switch(identifier){ 
      case "loginSegue": 
       print("Is the user already logged in?") 
       if(isLoggedIn){ 
        print("Detected as YES") 
        return true 
       } 
       print("Detected as NO, so checking username and password fields next...") 

       guard let password = passwordField.text!.stringByAddingPercentEncodingWithAllowedCharacters(.URLHostAllowedCharacterSet()) where !password.isEmpty else { 
        displayErrorMessage("Password can not be empty!") 
        return false 
       } 

       guard let username = usernameField.text!.stringByAddingPercentEncodingWithAllowedCharacters(.URLHostAllowedCharacterSet()) where !username.isEmpty else{ 
        displayErrorMessage("Username can not be empty!") 
        return false 
       } 

       let url = "http://distribution.tech/restapi/v1/userlogin?email="+username+"&password="+password 
       print(url) 

       let json = JSON(url:url) 
       print(json) 

       if(json["status"].asInt==1){ 

        let entity = NSEntityDescription.insertNewObjectForEntityForName("AppSettings", inManagedObjectContext: moc) as! AppSettings 

        entity.setValue(username, forKey: "username") 
        entity.setValue(password, forKey: "password") 
        entity.setValue(json["tokenid"].asString, forKey: "token") 
        entity.setValue(json["roleid"].asInt, forKey: "roleid") 
        entity.setValue(json["role"].asString, forKey: "role") 
        entity.setValue(json["companyid"].asInt , forKey: "companyid") 
        entity.setValue(json["isdev"].asInt, forKey: "isdev") 

        //save token and other details to database. 
        do { 
         try moc.save() 
         print("saved to entity") 
        }catch{ 
         fatalError("Failure to save context: \(error)") 
        } 

//     token 
//     roleid int 
//     role 
//     companyid int 
//      
//     { 
//      "companyid": 3, 
//      "userid": 2, 
//      "tokenid": "804febae26ddbd0292b3d2c66b30afd5028d5ba9", 
//      "status": 1, 
//      "roleId": 1, 
//      "role": "super_admin", 
//      "isdev": 0 
//     } 

        //Save to disk using our own method, as COREDATA is unreliable! 

        return true //login succesfull 
       }else{ 
        displayErrorMessage("Incorrect Username or Email") 
        return false//failed 
       } 

     default: 
      displayErrorMessage("Unknown Error Related To Segue Not Found") 
     } 
     return false //if it gets to this point assume false 
    } 


} 

管理対象オブジェクトは、そのファイルは以下ここでDataControllerで作成されたを含む

チェックログイン機能

func checkIfLoggedInAlready() -> Bool{ 
     let fetchRequest = NSFetchRequest(entityName: "AppSettings") 
     //let deleteRequest = NSBatchDeleteRequest(fetchRequest: fetchRequest) //Deletes ALL appsettings entities 

     do { 

      let fetchRequest = try moc.executeFetchRequest(fetchRequest) as! [AppSettings] 

      guard let appSettingsArrayItem = fetchRequest.first where fetchRequest.count>0 else { 
       print ("no entities found...") 
       return false 
      } 

      guard let username = (appSettingsArrayItem as AppSettings).username else{ 
       print ("username not found") 
       return false 
      } 

      print("number Of AppSetting Entities =\(fetchRequest.count)") 
      print(username) 

      //The following code deletes ALL the entities! 
      //try moc.persistentStoreCoordinator!.executeRequest(deleteRequest, withContext: moc) 

      //To delete just '1' entry use the code below. 

      //moc.deleteObject(appSettingsArrayItem) 
      //try moc.save()//save deletion change. 

      //print("deleted particular entity item") 

      return true 
     } catch{ 
      fatalError("bad things happened \(error)") 
     } 


    } 

全体LoginViewController。それは時間のエンティティのほとんどを検索していた場合、エンティティ&コンソール時には

enter image description here

イメージ参照を発生することがありますエンティティ&コンソールエラーの

import UIKit 
import CoreData 

class DataController: NSObject { 
    var managedObjectContext: NSManagedObjectContext 
    override init() { 
     // This resource is the same name as your xcdatamodeld contained in your project. 
     guard let modelURL = NSBundle.mainBundle().URLForResource("AppSettings", withExtension:"momd") else { 
      fatalError("Error loading model from bundle") 
     } 
     // The managed object model for the application. It is a fatal error for the application not to be able to find and load its model. 
     guard let mom = NSManagedObjectModel(contentsOfURL: modelURL) else { 
      fatalError("Error initializing mom from: \(modelURL)") 
     } 
     let psc = NSPersistentStoreCoordinator(managedObjectModel: mom) 
     self.managedObjectContext = NSManagedObjectContext(concurrencyType: .MainQueueConcurrencyType) 
     self.managedObjectContext.persistentStoreCoordinator = psc 
     dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0)) { 
      let urls = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask) 
      let docURL = urls[urls.endIndex-1] 
      /* The directory the application uses to store the Core Data store file. 
      This code uses a file named "DataModel.sqlite" in the application's documents directory. 
      */ 
      let storeURL = docURL.URLByAppendingPathComponent("AppSettings.sqlite") 
      do { 
       try psc.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: storeURL, options: nil) 
      } catch { 
       fatalError("Error migrating store: \(error)") 
      } 
     } 
    } 
} 

イメージ参照

enter image description here

+2

基本的には、フェッチ要求と同じ変数名を結果に与えることを強くお勧めします。 'executeFetchRequest'は同期的に動作します。 – vadian

+1

これは同期です。そうでない場合は、完了時(委任、ブロック、通知など)に通知するメカニズムがあります。 –

+0

なぜ時々エンティティを取得し、時にはその同期がないのでしょうか?それを引き起こす原因となるものは本当に混乱しています。 –

答えて

関連する問題