В Objective-C пользовательское уведомление представляет собой просто NSString, но это не очевидно в версии WWDC для Swift 3, что именно должно быть.
Как создавать пользовательские уведомления в Swift 3?
Ответ 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)
}
}