Ich habe meine App auf Swift 3 und Xcode 8.1 aktualisiert. Es gibt einen verblüffenden Fehler nach dieser Aktualisierung noting: Command failed due to signal: Segmentation fault: 11
auf der FriendsViewController.swift
, aber es gibt keine anderen Anzeichen von Fehler.Xcode 8.1 Befehl fehlgeschlagen wegen Signal: Segmentierungsfehler: 11
Wie kann das gelöst werden?
Aktualisiert: Added FriendsViewController-Code
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)
})
}
}
Spezifische Objekte:
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
]
Können Sie Screenshots oder etwas Nützliches anhängen, um diesen Fehler zu beheben? – sohnryang
@sohnryang Ich habe den Fehler – Sauron
hinzugefügt die Typen sind nicht korrekt, auf den Objekten friendsObject und myObject-Wörterbuch. Abhängig von Ihrer letzten Version von Swift haben sie es geändert und Ihr Code geht wahrscheinlich davon aus, dass der Wert dieses Objekts etwas anderes ist. Sie müssen den Wörterbuchwert jetzt explizit in das umsetzen, was Sie erwarten. Wenn Sie den Code aus dem FriendsViewController veröffentlichen, wird es Ihnen helfen, Ihnen zu sagen, wie man die Objekte richtig darstellt – JustinM