Objective-C'de, özel bir bildirim yalnızca basit bir NSString'dir, ancak Swift 3'ün WWDC sürümünde tam olarak ne olması gerektiği açık değildir.
Objective-C'de, özel bir bildirim yalnızca basit bir NSString'dir, ancak Swift 3'ün WWDC sürümünde tam olarak ne olması gerektiği açık değildir.
Yanıtlar:
Bunun için bir protokol de kullanabilirsiniz.
protocol NotificationName {
var name: Notification.Name { get }
}
extension RawRepresentable where RawValue == String, Self: NotificationName {
var name: Notification.Name {
get {
return Notification.Name(self.rawValue)
}
}
}
Ve sonra bildirim adlarınızı enum
istediğiniz yerde tanımlayın . Örneğin:
class MyClass {
enum Notifications: String, NotificationName {
case myNotification
}
}
Ve gibi kullan
NotificationCenter.default.post(name: Notifications.myNotification.name, object: nil)
Bu şekilde, bildirim adları Vakıftan ayrılacaktır Notification.Name
. Ve Notification.Name
değişikliklerin uygulanması durumunda sadece protokolünüzü değiştirmeniz gerekecektir .
NotificationName
yüzden name
özellik yalnızca protokole uyan çeteleler eklenir.
extension NotificationName where Self: RawRepresentable, Self.RawValue == String {
Bunu başarmanın daha temiz (bence) bir yolu var
extension Notification.Name {
static let onSelectedSkin = Notification.Name("on-selected-skin")
}
Ve sonra bunu böyle kullanabilirsin
NotificationCenter.default.post(name: .onSelectedSkin, object: selectedSkin)
extension NSNotification.Name
yerine extension Notification.Name
. Aksi takdirde Swift 3 ile ilgili şikayetler'Notification' is ambiguous for type lookup in this context
Notification.post şu şekilde tanımlanır:
public func post(name aName: NSNotification.Name, object anObject: AnyObject?)
Objective-C'de, bildirim adı düz bir NSString'dir. Swift'de NSNotification.Name olarak tanımlanır.
NSNotification.Name şu şekilde tanımlanır:
public struct Name : RawRepresentable, Equatable, Hashable, Comparable {
public init(_ rawValue: String)
public init(rawValue: String)
}
Bu biraz tuhaf, çünkü onun bir Enum olmasını beklerdim ve görünüşte daha fazla yararı olmayan özel bir yapı değil.
Notification for NSNotification'da bir tür takma adı vardır.
public typealias Name = NSNotification.Name
Kafa karıştıran kısım, Swift'de hem Bildirim hem de NSNotification'ın mevcut olmasıdır.
Bu nedenle, kendi özel bildiriminizi tanımlamak için aşağıdakilere benzer bir şey yapın:
public class MyClass {
static let myNotification = Notification.Name("myNotification")
}
Sonra onu aramak için:
NotificationCenter.default().post(name: MyClass.myNotification, object: self)
Notification.Name
olsaydı, hiç kimse yeni bildirimler tanımlayamazdı. Yeni üyelerin eklenmesine izin vermesi gereken, aksi takdirde enum benzeri türler için yapılar kullanıyoruz. ( Hızlı evrim önerisine bakın .)
Notification
bir değer türüdür (yapı), böylece Swift'in değer (im) değişkenliği için anlambiliminden faydalanabilir. Genel olarak, Temel türleri Swift 3'te "NS" değerlerini düşürüyor, ancak yerini almak için yeni Temel Değer Türlerinden birinin mevcut olduğu durumlarda, eski referans türü ("NS" adını koruyarak) etrafta kalır, böylece yine de kullanabilirsiniz. referans semantiğine veya alt sınıflara ihtiyacınız var. Teklife bakın .
Daha kolay yol:
let name:NSNotification.Name = NSNotification.Name("notificationName")
NotificationCenter.default.post(name: name, object: nil)
NSNotification.Name'e özel bir başlatıcı ekleyebilirsiniz.
extension NSNotification.Name {
enum Notifications: String {
case foo, bar
}
init(_ value: Notifications) {
self = NSNotification.Name(value.rawValue)
}
}
Kullanımı:
NotificationCenter.default.post(name: Notification.Name(.foo), object: nil)
case
kendisi değil, yalnızca bir numaralandırmadaki s'ler küçük harfle yazılmalıdır. Tür adları büyük harfle yazılır ve numaralandırmalar türlerdir.
@CesarVarela'nın önerdiğine benzer başka bir seçenek önerebilirim.
extension Notification.Name {
static var notificationName: Notification.Name {
return .init("notificationName")
}
}
Bu, bildirimleri kolayca yayınlamanıza ve abone olmanıza olanak tanır.
NotificationCenter.default.post(Notification(name: .notificationName))
Umarım bu sana yardımcı olur.
Her şeyi oradan oraya karıştırarak kendi uygulamamı yaptım ve bunu en uygun olarak buldum. Kimin ilgisini çekebileceğini paylaşmak:
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)
}
}
NSNotification.Name(rawValue: "myNotificationName")
Bu sadece referans
// 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)
Numaralandırmanın avantajı, derleyicinin adın doğru olup olmadığını kontrol etmesini sağlamamızdır. Olası sorunları azaltır ve yeniden düzenlemeyi kolaylaştırır.
Bildirim adları için alıntılanmış dizeler yerine numaralandırmaları kullanmayı sevenler için bu kod hile yapar:
enum MyNotification: String {
case somethingHappened
case somethingElseHappened
case anotherNotification
case oneMore
}
extension NotificationCenter {
func add(observer: Any, selector: Selector,
notification: MyNotification, 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)
}
}
O zaman bunu şu şekilde kullanabilirsiniz:
NotificationCenter.default.post(.somethingHappened)
Soruyla alakasız olsa da, alıntılanan dizeleri yazmaktan kaçınmak için aynı şey film şeridi bölümleri için de yapılabilir:
enum StoryboardSegue: String {
case toHere
case toThere
case unwindToX
}
extension UIViewController {
func perform(segue: StoryboardSegue) {
performSegue(withIdentifier: segue.rawValue, sender: self)
}
}
Ardından, görünüm denetleyicinizde şöyle adlandırın:
perform(segue: .unwindToX)
Yalnızca dizeli özel bildirimler kullanırsanız, herhangi bir sınıfı genişletmeniz gerekmez, ancak String
extension String {
var notificationName : Notification.Name{
return Notification.Name.init(self)
}
}
Aynı anda hem Objective-C hem de Swift kullanan bir projede bunun temiz çalışmasını istiyorsanız, Objective-C'de bildirim oluşturmanın daha kolay olduğunu buldum.
Bir .m / .h dosyası oluşturun:
//CustomNotifications.h
#import <Foundation/Foundation.h>
// Add all notifications here
extern const NSNotificationName yourNotificationName;
//CustomNotifications.m
#import "CustomNotifications.h"
// Add their string values here
const NSNotificationName yourNotificationName = @"your_notification_as_string";
MyProject-Bridging-Header.h
Onları Swift'e ifşa etmek için (projenizin adını taşıyan).
#import "CustomNotifications.h"
Bildirimlerinizi Objective-C'de şu şekilde kullanın:
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(yourMethod:) name:yourNotificationName:nil];
Ve Swift'de (5) şöyle:
NotificationCenter.default.addObserver(self, selector: #selector(yourMethod(sender:)), name: .yourNotificationName, object: nil)