2016-10-30 61 views
0

我已将我的应用升级到Swift 3和Xcode 8.1。在此更新之后有一个令人困惑的错误,注意:FriendsViewController.swift上的Command failed due to signal: Segmentation fault: 11,但没有其他错误指示​​。Xcode 8.1命令由于信号失败:分段错误:11

这怎么解决?

更新:新增FriendsViewController代码

import UIKit 
import Contacts 
import ContactsUI 
import Firebase 
import FBSDKCoreKit 

// Allowing clean removal of objects 
extension RangeReplaceableCollection where Iterator.Element : Equatable { 

    // Remove first collection element that is equal to the given `object`: 
    mutating func removeObject(_ object : Iterator.Element) { 
     if let index = self.index(of: object) { 
      self.remove(at: index) 
     } 
    } 
} 

// For searching 
extension FriendsViewController: UISearchResultsUpdating { 

    // must implement to conform to the UISearchResultsUpdating protocol. 
    // As well as the scope narrowing 
    func updateSearchResults(for searchController: UISearchController) { 
     let searchBar = searchController.searchBar 
     let scope = searchBar.scopeButtonTitles![searchBar.selectedScopeButtonIndex] 
     filterContentForSearchText(searchController.searchBar.text!, scope: scope) 
    } 
} 

extension FriendsViewController: UISearchBarDelegate { 
    // This delegate methods gets called when the user switches the scope in the scope bar. 
    // When that happens, you want to redo the filtering, 
    func searchBar(_ searchBar: UISearchBar, selectedScopeButtonIndexDidChange selectedScope: Int) { 
     filterContentForSearchText(searchBar.text!, scope: searchBar.scopeButtonTitles![selectedScope]) 
    } 
} 

class FriendsViewController: UITableViewController, CNContactPickerDelegate { 

    // MARK: Properties 
    var firebaseMainURL: String! 
    @IBOutlet weak var menuButton: UIBarButtonItem! 
    var contacts = [CNContact]() 
    var friends: [Friend] = [] 
    var mappedFriends: [Friend] = [] 
    var filterMappedFriends: [Friend] = [] 
    var feastGlobalRef = FeastGlobal.sharedInstance 
    let rootRef = FIRDatabase.database().reference() 

    // Ensuring Serial queue 
    let queue = DispatchQueue(label: "DISPATCH_QUEUE_SERIAL", attributes: []) 

    // Adding search 
    let searchController = UISearchController(searchResultsController: nil) 

    override func viewDidLoad() { 
     super.viewDidLoad() 

     if revealViewController() != nil { 
      menuButton.target = revealViewController() 
      menuButton.action = #selector(SWRevealViewController.revealToggle(_:)) 
      view.addGestureRecognizer(self.revealViewController().panGestureRecognizer()) 

     } 

     // Creating the search bar, decides when to show and hide results 
     searchController.searchResultsUpdater = self 
     searchController.dimsBackgroundDuringPresentation = false 
     definesPresentationContext = true 
     tableView.tableHeaderView = searchController.searchBar 

     // Adding the scope bar and buttons: 
     searchController.searchBar.scopeButtonTitles = ["All", "Friend", "A User", "Not User"] 
     searchController.searchBar.delegate = self 

     // Main mapping action 
     self.mapContactsToPresentFriends(feastGlobalRef.userID) 

    } 

    override func viewWillAppear(_ animated: Bool) { 
     //self.clearsSelectionOnViewWillAppear = self.splitViewController!.collapsed 
     super.viewWillAppear(animated) 
    } 

    func findContacts() -> [CNContact] { 
     let store = CNContactStore() 

     let keysToFetch = [CNContactFormatter.descriptorForRequiredKeys(for: .fullName), 
          CNContactImageDataKey, 
          CNContactPhoneNumbersKey] as [Any] 

     let fetchRequest = CNContactFetchRequest(keysToFetch: keysToFetch as! [CNKeyDescriptor]) 

     var contacts = [CNContact]() 

     do { 
      try store.enumerateContacts(with: fetchRequest, usingBlock: { (contact, stop) -> Void in 
       contacts.append(contact) 
      }) 
     } 
     catch let error as NSError { 
      print(error.localizedDescription) 
     } 

     return contacts 
    } 

    // MARK: - Table View 

    override func numberOfSections(in tableView: UITableView) -> Int { 
     return 1 
    } 

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 

     if searchController.isActive && searchController.searchBar.text != "" { 
      return filterMappedFriends.count 
     } 

     return self.mappedFriends.count 
    } 

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 
     let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) 
     let friend: Friend 

     //let contact = contacts[indexPath.row] as CNContact 
     let contact = mappedFriends[indexPath.row] as Friend 

     // Getting phone number (default to first phone number present): 
     let phoneNumber = contact.phoneNumber 

     // If searching, then replace 
     if searchController.isActive && searchController.searchBar.text != "" { 
      friend = filterMappedFriends[indexPath.row] 
     } else { 
      friend = mappedFriends[indexPath.row] 
     } 

     // Conditional given relationship: 
     var status: String! 

     status = { 
      switch friend.statusSort { 
      case 0: 
       return "Invite to Feast" 
      case 1: 
       return "Friend them" 
      default: 
       return "" // they are a friend 
      } 
     }() 

     // Update the rows with the proper object 
     cell.textLabel!.text = "\(friend.name) \(friend.userName)" 
     cell.detailTextLabel?.text = "\(status)" 
     return cell 
    } 

    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 

     // Ensure controller knows which dataset to pull from, 
     // so detail view is correct 
     var friendChat: Friend! 
     if searchController.isActive && searchController.searchBar.text != "" { 
      friendChat = filterMappedFriends[indexPath.row] 
     } else { 
      friendChat = mappedFriends[indexPath.row] 
     } 

     // Now set the conditional cases: if a friend then chat, if user then friend request if not user then can invite them: 
     if(friendChat.statusSort == 2) { 

      self.performSegue(withIdentifier: "showIndividualChat", sender: self) 

     } else if (friendChat.statusSort == 1) { 

      let formatterShortDate = Date().dateStringWithFormat("yyyy-MM-dd HH:mm:ss") 

      let myFriendPath = rootRef.child("friends").child(FeastGlobal.sharedInstance.userID) 

      let friendFriendsPath = rootRef.child("friends").child(friendChat.userID) 

      let friendInviteSync = rootRef.child("friendInviteNeedSync").child(friendChat.userID) 

      // 
      let friendsObject = [ 
       "confirmed" : true, 
       "phoneNumber" : friendChat.phoneNumber, 
       "selfSendRequest" : true, 
       "timeInvited": formatterShortDate, 
       "userName": friendChat.userName 
      ] 


      let myObject = [ 
       "confirmed" : true, 
       "phoneNumber" : FeastGlobal.sharedInstance.phoneNumber, 
       "selfSendRequest" : false, 
       "timeInvited": formatterShortDate, 
       "userName": FeastGlobal.sharedInstance.userName 
      ] 

      let friendInviteObject = [ 
       FeastGlobal.sharedInstance.userID : FeastGlobal.sharedInstance.userName 
      ] 

      queue.async { 
       myFriendPath.child(friendChat.userID).setValue(friendsObject) 
       friendFriendsPath.child(FeastGlobal.sharedInstance.userID).setValue(myObject) 
       friendInviteSync.setValue(friendInviteObject) 

      } 

      queue.async { 
       friendFriendsPath.child(FeastGlobal.sharedInstance.userID).setValue(myObject) 
      } 

      queue.async { 
       self.mapContactsToPresentFriends(self.feastGlobalRef.userID) 
      } 


      print("Can invite to be friend") 

     } else if (friendChat.statusSort == 0) { 

      print("Invite to Feast") 

     } 
    } 


    func contactPicker(_ picker: CNContactPickerViewController, didSelect contactProperty: CNContactProperty) { 
     let contact = contactProperty.contact 
     let phoneNumber = contactProperty.value as! CNPhoneNumber 

     print(contact.givenName) 
     print(phoneNumber.stringValue) 
    } 

    // Method to match contacts with Firebase db friends: 
    func mapContactsToPresentFriends(_ usersSyncID: String) { 

     // Reset the data: 
     self.mappedFriends.removeAll() 
     self.friends.removeAll() 

     // Use the queue (defined above) and "dispatch_async" to schedule the async actions, synchornously 
     // First 
     queue.async { 
      print("start 1") 

       self.contacts = self.findContacts() 

      print("end 1") 

     } 

     // Second 
     queue.async { 

      let friendsURL = self.rootRef.child("friends").child(usersSyncID) // Firebase(url: firebaseMainURL + "friends/" + usersSyncID) 

      var contactNumber: String? 

      friendsURL.observeSingleEvent(of: .value, with: { snapshot in 

       print("start 2") 
       for oneSnapshot in snapshot.children { 

        for oneContact in self.contacts { 

         for oneContactPhoneNum in oneContact.phoneNumbers { 

          let phoneNumber = oneContactPhoneNum.value 

          contactNumber = phoneNumber.stringValue 

          // Clean the number 
          let stringArray = contactNumber!.components(
           separatedBy: CharacterSet.decimalDigits.inverted) 
          let newString = "1" + stringArray.joined(separator: "") 

          let firebaseFriendNumber = (oneSnapshot as AnyObject).value["phoneNumber"] as! String 
          print("Contacts number: " + newString) 

          print("Firebase number: " + firebaseFriendNumber) 

          if newString == firebaseFriendNumber { 
           print("friend added") 

           self.friends.append(Friend(userName: oneSnapshot.value["userName"] as! String,phoneNumber: firebaseFriendNumber, status: "Friend", statusSort: 2, name: oneContact.givenName, userID: oneSnapshot.key)) 

           // Remove that contact 
           self.contacts.removeObject(oneContact) 
          } 
         } 
        } 
       } 
       print("end 2") 

       print("start 3") 
       // Now do the users search: 
       for oneContact in self.contacts { 

        var contactNumber: String 

        let phoneNumber = oneContact.phoneNumbers[0].value 

        contactNumber = phoneNumber.stringValue 

        let stringArray = contactNumber.components(
         separatedBy: CharacterSet.decimalDigits.inverted) 
        let newString = "1" + stringArray.joined(separator: "") 

        //let usersURL: Firebase! = Firebase(url: firebaseMainURL + "presentUserIDUserNameByPhoneNumber/" + newString) 
        let usersURL = self.rootRef.child("presentUserIDUserNameByPhoneNumber").child(newString) 

        // Check db: 
        usersURL.observeSingleEvent(of: .value, with: { snapshot in 
         print("start 3") 

         if snapshot.childrenCount > 1 { 

          // They are users (but not your friends), and remove yourself: 
          if(snapshot.value!["userID"] as! String != FeastGlobal.sharedInstance.userID) { 

           self.friends.append(Friend(userName: snapshot.value!["userName"] as! String, phoneNumber: snapshot.key, status: "A User", statusSort: 1, name: oneContact.givenName, userID: snapshot.value!["userID"] as! String)) 

           let userName = snapshot.value!["userName"] as! String 

           print("Friends name: " + userName) 

          } 

         } else { 

          self.friends.append(Friend(userName: "", phoneNumber: phoneNumber.stringValue, status: "Not User", statusSort: 0, name: oneContact.givenName, userID: "")) 

         } 

         // Remove that contact 
         self.contacts.removeObject(oneContact) 

         // If all done, then sort and load main screen 
         if self.contacts.isEmpty { 

          self.mappedFriends = self.friends.sorted(by: {$0.statusSort > $1.statusSort}) 

          self.tableView.reloadData() 

         } 

         print("end 3") 

        }) 
       } 
      }) 
     } 
    } 

    func indexOfObject(_ object : AnyObject) -> NSInteger { 
     return self.indexOfObject(object) 
    } 

    func friendRequestAction() { 

     // TODO: Should siply be button to add friend, or request to feast. 


    } 

    // Results of search 
    func filterContentForSearchText(_ searchText: String, scope: String = "All") { 
     filterMappedFriends = mappedFriends.filter { Friend in 
      let categoryMatch = (scope == "All") || (Friend.status == scope) 
      return categoryMatch && Friend.name.lowercased().contains(searchText.lowercased()) 
     } 

     tableView.reloadData() 
    } 

    // MARK: - Segues 
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) { 

     if let indexPath = tableView.indexPathForSelectedRow { 

      // Ensure controller knows which dataset to pull from, 
      // so detail view is correct 
      let friendChat: Friend 
      if searchController.isActive && searchController.searchBar.text != "" { 
       friendChat = filterMappedFriends[indexPath.row] 
      } else { 
       friendChat = mappedFriends[indexPath.row] 
      } 

      // Now set the conditional cases: if a friend then chat, if user then friend request if not user then can invite them: 

      if segue.identifier == "showIndividualChat" { 

       let controller = segue.destination as! IndividualChatController 
       controller.friendChat = friendChat 
       controller.senderId = FeastGlobal.sharedInstance.userID 
       controller.senderDisplayName = FeastGlobal.sharedInstance.userName 
      } 
     } 
    } 


    func getFriends() { 

     let parametersfriend = ["fields": "name,picture.type(normal),gender"] 

     FBSDKGraphRequest(graphPath: "me/friends", parameters: parametersfriend).start(completionHandler: { (connection, user, requestError) -> Void in 
      if requestError != nil { 
       print(requestError) 
       return 
      } 

      print(user) 

     }) 

    } 
} 

特定对象:

let friendsObject = [ 
    "confirmed" : true, 
    "phoneNumber" : friendChat.phoneNumber, 
    "selfSendRequest" : true, 
    "timeInvited": formatterShortDate, 
    "userName": friendChat.userName 
] 


let myObject = [ 
    "confirmed" : true, 
    "phoneNumber" : FeastGlobal.sharedInstance.phoneNumber, 
    "selfSendRequest" : false, 
    "timeInvited": formatterShortDate, 
    "userName": FeastGlobal.sharedInstance.userName 
] 
+0

你可以附上截图或有用的东西来解决这个错误吗? – sohnryang

+0

@sohnryang我在friendsObject和myObject字典对象上添加了错误 – Sauron

+0

的类型不正确。根据你最后一个工作版本的Swift,他们改变了它,你的代码可能假设该对象的价值是别的。您现在需要明确地将字典值转换为您期望从中获得的值。如果你从FriendsViewController发布代码,它会告诉你如何正确投射对象 – JustinM

回答

0

与SWIFT的类型安全,现在你上面的目的类型[字符串:任何]。当你尝试使用这些对象时,你需要告诉编译器你期望的类型是什么。

let friendsObject: [String:Any] = [ 
     "confirmed" : true, 
     "phoneNumber" : friendChat.phoneNumber, 
     "selfSendRequest" : true, 
     "timeInvited": formatterShortDate, 
     "userName": friendChat.userName 
    ] 


    func doSomethingWith(FriendsObj: [String:Any] { 
     guard let confirmed = friendsObject["confirmed"] as? Bool, 
     let phone = friendsObject["phoneNumber"] as? Int, 
     let sendRequest = friendsObject["selfSendRequest"] as? Bool else { return } 

    //Now you can access confirmed, phone, and sendRequest as their native types. 
} 
+0

谢谢你的回答,但我没有把它们用在'myFriendPath.child(friendChat.userID).setValue(friendsObject)'旁边,这里没有其他调用 – Sauron

+0

好吧,抱歉,我无法提供更多帮助。你应该重新发布错误,所以如果有其他人出现,他们将会从错误中解脱出来。 – JustinM

+0

进一步的研究注意到这可能是Xcode版本中的一个错误。没有理由,这应该失败... – Sauron

相关问题