Подтвердить что ты не робот

Как создавать пользовательские уведомления в Swift 3?

В Objective-C пользовательское уведомление представляет собой просто NSString, но это не очевидно в версии WWDC для Swift 3, что именно должно быть.

4b9b3361

Ответ 1

Вы также можете использовать протокол для этого

protocol NotificationName {
    var name: Notification.Name { get }
}

extension RawRepresentable where RawValue == String, Self: NotificationName {
    var name: Notification.Name {
        get {
            return Notification.Name(self.rawValue)
        }
    }
}

И затем укажите свои имена уведомлений как enum в любом месте. Например:

class MyClass {
    enum Notifications: String, NotificationName {
        case myNotification
    }
}

И используйте его как

NotificationCenter.default.post(name: Notifications.myNotification.name, object: nil)

Таким образом, имена уведомлений будут отделены от Foundation Notification.Name. И вам придется изменить свой протокол только в том случае, если будет изменена реализация для Notification.Name.

Ответ 2

Существует более чистый (я думаю) способ его достижения

extension Notification.Name {

    static let onSelectedSkin = Notification.Name("on-sekected-skin")
}

И тогда вы можете использовать его так:

NotificationCenter.default.post(name: .onSelectedSkin, object: selectedSkin)

Ответ 3

Notification.post определяется как:

public func post(name aName: NSNotification.Name, object anObject: AnyObject?)

В Objective-C имя уведомления является простым NSString. В Swift он определяется как NSNotification.Name.

NSNotification.Name определяется как:

public struct Name : RawRepresentable, Equatable, Hashable, Comparable {
    public init(_ rawValue: String)
    public init(rawValue: String)
}

Это немного странно, поскольку я ожидаю, что это будет Enum, а не какая-то пользовательская структура, которая, казалось бы, не принесет больше пользы.

В Notification для NSNotification.Name: typealias.Name:

public typealias Name = NSNotification.Name

Запутанная часть состоит в том, что как уведомление, так и NSNotification существуют в Swift

Итак, чтобы определить собственное уведомление, сделайте следующее:

public class MyClass {
    static let myNotification = Notification.Name("myNotification")
}

Затем назовем это:

NotificationCenter.default().post(name: MyClass.myNotification, object: self)

Ответ 4

Простой способ:

let name:NSNotification.Name = NSNotification.Name("notificationName")
NotificationCenter.default.post(name: name, object: nil)

Ответ 5

Вы можете добавить пользовательский инициализатор в NSNotification.Name

extension NSNotification.Name {
    enum Notifications: String {
        case foo, bar
    }
    init(_ value: Notifications) {
        self = NSNotification.Name(value.rawValue)
    }
}

Использование:

NotificationCenter.default.post(name: Notification.Name(.foo), object: nil)

Ответ 6

NSNotification.Name(rawValue: "myNotificationName")

Ответ 7

Это просто ссылка

// Add observer:
NotificationCenter.default.addObserver(self,
    selector: #selector(notificationCallback),
    name: MyClass.myNotification,
    object: nil)

    // Post notification:
    let userInfo = ["foo": 1, "bar": "baz"] as [String: Any]
    NotificationCenter.default.post(name: MyClass.myNotification,
        object: nil,
        userInfo: userInfo)

Ответ 8

Я сделал свою собственную реализацию, смешивая вещи оттуда и там, и считаю это самым удобным. Обмен для тех, кто может быть заинтересован:

public extension Notification {
    public class MyApp {
        public static let Something = Notification.Name("Notification.MyApp.Something")
    }
}

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        NotificationCenter.default.addObserver(self,
                                               selector: #selector(self.onSomethingChange(notification:)),
                                               name: Notification.MyApp.Something,
                                               object: nil)
    }

    deinit {
        NotificationCenter.default.removeObserver(self)
    }

    @IBAction func btnTapped(_ sender: UIButton) {
        NotificationCenter.default.post(name: Notification.MyApp.Something,
                                      object: self,
                                    userInfo: [Notification.MyApp.Something:"foo"])
    }

    func onSomethingChange(notification:NSNotification) {
        print("notification received")
        let userInfo = notification.userInfo!
        let key = Notification.MyApp.Something 
        let something = userInfo[key]! as! String //Yes, this works :)
        print(something)
    }
}

Ответ 9

Преимущество использования перечислений состоит в том, что мы получаем компилятор для проверки правильности имени. Уменьшает потенциальные проблемы и упрощает рефакторинг.

Для тех, кому нравится использовать перечисления вместо цитированных строк для имен уведомлений, этот код выполняет трюк:

enum MyNotification: String {
    case somethingHappened
    case somethingElseHappened
    case anotherNotification
    case oneMore
}

extension NotificationCenter {
    func add(observer: Any, selector: Selector, 
             notification: CheckoutNotification, object: Any? = nil) {
        addObserver(observer, selector: selector, 
                    name: Notification.Name(notification.rawValue),
                    object: object)
    }
    func post(notification: MyNotification, 
              object: Any? = nil, userInfo: [AnyHashable: Any]? = nil) {
        post(name: NSNotification.Name(rawValue: notification.rawValue), 
             object: object, userInfo: userInfo)
    }
}

Затем вы можете использовать его следующим образом:

NotificationCenter.default.post(.somethingHappened)

Несмотря на то, что он не связан с вопросом, то же самое можно сделать с помощью раскадров, чтобы избежать ввода цитируемых строк:

enum StoryboardSegue: String {
    case toHere
    case toThere
    case unwindToX
}

extension UIViewController {
    func perform(segue: StoryboardSegue) {
        performSegue(withIdentifier: segue.rawValue, sender: self)
    }
}

Затем на вашем контроллере просмотра вызовите его так:

perform(segue: .unwindToX)

Ответ 10

если вы используете пользовательские уведомления только для строк, нет причин для расширения каких-либо классов, но String

    extension String {
        var notificationName : Notification.Name{
            return Notification.Name.init(self)
        }
    }