web-dev-qa-db-fra.com

Problème NotificationCenter sur Swift 3

J'apprends Swift 3 et j'essaie d'utiliser NSNotificationCenter. Voici mon code:

func savePost(){
    let postData = NSKeyedArchiver.archivedData(withRootObject: _loadedpost)
    UserDefaults.standard().object(forKey: KEY_POST)
}
func loadPost(){
    if let postData = UserDefaults.standard().object(forKey: KEY_POST) as? NSData{
        if let postArray = NSKeyedUnarchiver.unarchiveObject(with: postData as Data) as? [Post]{
                _loadedpost = postArray
        }
    }
    //codeerror
    NotificationCenter.default().post(NSNotification(name: "loadedPost" as NSNotification.Name, object: nil) as Notification)
}

et voici l'observateur:

override func viewDidLoad() {
    super.viewDidLoad()
//codeerorr
    NotificationCenter.default().addObserver(self, selector: Selector(("onPostLoaded")), name: "loadedPost", object: nil)
}

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

Cela me donne toujours l'erreur "signal SIGBRT". Quand j'essaye de changer le nom dans l'observateur, ce n'est pas une erreur, mais évidemment, cela ne montre rien. Comment puis-je réparer ça?

91
RoccoBerry

Swift 3 & 4

Swift 3, et maintenant Swift 4, ont remplacé de nombreux API "typés de manière stricte" par struct "types d'encapsuleurs", comme c'est le cas avec NotificationCenter. Les notifications sont maintenant identifiées par un struct Notfication.Name plutôt que par String. Pour plus de détails, consultez le guide maintenant hérité Guide de la migration vers Swift

Utilisation de Swift 2.2 :

// Define identifier
let notificationIdentifier: String = "NotificationIdentifier"

// Register to receive notification
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(YourClassName.methodOfReceivedNotification(_:)), name: notificationIdentifier, object: nil)

// Post a notification
NSNotificationCenter.defaultCenter().postNotificationName(notificationIdentifier, object: nil)

Utilisation de Swift 3 & 4 :

// Define identifier
let notificationName = Notification.Name("NotificationIdentifier")

// Register to receive notification
NotificationCenter.default.addObserver(self, selector: #selector(YourClassName.methodOfReceivedNotification), name: notificationName, object: nil)

// Post notification
NotificationCenter.default.post(name: notificationName, object: nil)

// Stop listening notification
NotificationCenter.default.removeObserver(self, name: notificationName, object: nil)

Tous les types de notification système sont maintenant définis en tant que constantes statiques sur Notification.Name; c'est-à-dire .UIApplicationDidFinishLaunching, .UITextFieldTextDidChange, etc.

Vous pouvez étendre Notification.Name avec vos propres notifications personnalisées afin de rester cohérent avec les notifications système:

// Definition:
extension Notification.Name {
    static let yourCustomNotificationName = Notification.Name("yourCustomNotificationName")
}

// Usage:
NotificationCenter.default.post(name: .yourCustomNotificationName, object: nil)

Swift 4.2 utilisation:

Identique à Swift 4, sauf que les noms des notifications système font maintenant partie de UIApplication. Donc, pour rester cohérent avec les notifications du système, vous pouvez étendre UIApplication avec vos propres notifications personnalisées au lieu de Notification.Name:

// Definition:
UIApplication {
    public static let yourCustomNotificationName = Notification.Name("yourCustomNotificationName")
}

// Usage:
NotificationCenter.default.post(name: UIApplication.yourCustomNotificationName, object: nil)
325
Jeffrey Fulton

Pour tous ceux qui luttent avec le sélecteur # dans Swift 3 ou Swift 4, voici un exemple de code complet:

// WE NEED A CLASS THAT SHOULD RECEIVE NOTIFICATIONS
    class MyReceivingClass {

    // ---------------------------------------------
    // INIT -> GOOD PLACE FOR REGISTERING
    // ---------------------------------------------
    init() {
        // WE REGISTER FOR SYSTEM NOTIFICATION (APP WILL RESIGN ACTIVE)

        // Register without parameter
        NotificationCenter.default.addObserver(self, selector: #selector(MyReceivingClass.handleNotification), name: .UIApplicationWillResignActive, object: nil)

        // Register WITH parameter
        NotificationCenter.default.addObserver(self, selector: #selector(MyReceivingClass.handle(withNotification:)), name: .UIApplicationWillResignActive, object: nil)
    }

    // ---------------------------------------------
    // DE-INIT -> LAST OPTION FOR RE-REGISTERING
    // ---------------------------------------------
    deinit {
        NotificationCenter.default.removeObserver(self)
    }

    // either "MyReceivingClass" must be a subclass of NSObject OR selector-methods MUST BE signed with '@objc'

    // ---------------------------------------------
    // HANDLE NOTIFICATION WITHOUT PARAMETER
    // ---------------------------------------------
    @objc func handleNotification() {
        print("RECEIVED ANY NOTIFICATION")
    }

    // ---------------------------------------------
    // HANDLE NOTIFICATION WITH PARAMETER
    // ---------------------------------------------
    @objc func handle(withNotification notification : NSNotification) {
        print("RECEIVED SPECIFIC NOTIFICATION: \(notification)")
    }
}

Dans cet exemple, nous essayons d'obtenir des POST à ​​partir d'AppDelegate (ainsi, dans AppDelegate, implémentons ceci):

// ---------------------------------------------
// WHEN APP IS GOING TO BE INACTIVE
// ---------------------------------------------
func applicationWillResignActive(_ application: UIApplication) {

    print("POSTING")

    // Define identifiyer
    let notificationName = Notification.Name.UIApplicationWillResignActive

    // Post notification
    NotificationCenter.default.post(name: notificationName, object: nil)
}
18
LukeSideWalker

Les notifications semblent avoir de nouveau changé (octobre 2016).

// Inscrivez-vous pour recevoir une notification

NotificationCenter.default.addObserver(self, selector: #selector(yourClass.yourMethod), name: NSNotification.Name(rawValue: "yourNotificatioName"), object: nil)

// Publier une notification

NotificationCenter.default.post(name: NSNotification.Name(rawValue: "yourNotificationName"), object: nil)
17
David DelMonte

Je pense que cela a encore changé.

Pour poster cela fonctionne dans Xcode 8.2.

NotificationCenter.default.post(Notification(name:.UIApplicationWillResignActive)
5
Muge Cevik