ऑब्जेक्टिव-सी में, एक कस्टम नोटिफिकेशन सिर्फ एक सादा NSString है, लेकिन स्विफ्ट 3 के WWDC संस्करण में यह स्पष्ट नहीं है कि यह क्या होना चाहिए।
ऑब्जेक्टिव-सी में, एक कस्टम नोटिफिकेशन सिर्फ एक सादा NSString है, लेकिन स्विफ्ट 3 के WWDC संस्करण में यह स्पष्ट नहीं है कि यह क्या होना चाहिए।
जवाबों:
आप इसके लिए एक प्रोटोकॉल का उपयोग भी कर सकते हैं
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)
इस तरह से फाउंडेशन की ओर से नोटिफिकेशन के नाम डिक्लेय किए जाएंगे Notification.Name
। और Notification.Name
परिवर्तनों के कार्यान्वयन के मामले में आपको केवल अपने प्रोटोकॉल को संशोधित करना होगा ।
NotificationName
ताकि name
संपत्ति केवल उन प्रोटोकॉल में जोड़ी जाए जो प्रोटोकॉल के अनुरूप हैं।
extension NotificationName where Self: RawRepresentable, Self.RawValue == String {
इसे प्राप्त करने के लिए एक क्लीनर (मुझे लगता है) तरीका है
extension Notification.Name {
static let onSelectedSkin = Notification.Name("on-selected-skin")
}
और फिर आप इसे इस तरह से उपयोग कर सकते हैं
NotificationCenter.default.post(name: .onSelectedSkin, object: selectedSkin)
extension NSNotification.Name
के बजाय extension Notification.Name
। अन्यथा स्विफ्ट 3 शिकायतों के साथ'Notification' is ambiguous for type lookup in this context
अधिसूचना.पोस्ट को इस प्रकार परिभाषित किया गया है:
public func post(name aName: NSNotification.Name, object anObject: AnyObject?)
ऑब्जेक्टिव-सी में, अधिसूचना नाम एक सादा एनएसएसटृिंग है। स्विफ्ट में, इसे NSNotification.Name के रूप में परिभाषित किया गया है।
NSNotification.Name के रूप में परिभाषित किया गया है:
public struct Name : RawRepresentable, Equatable, Hashable, Comparable {
public init(_ rawValue: String)
public init(rawValue: String)
}
यह अजीब तरह का है, क्योंकि मैं उम्मीद करता हूं कि यह एक एनम होगा, और कुछ कस्टम संरचना के साथ प्रतीत नहीं होता है और अधिक लाभ।
NSNotification.Name के लिए अधिसूचना में एक टाइपियासिस है:
public typealias Name = NSNotification.Name
भ्रामक हिस्सा यह है कि अधिसूचना और NSNotification दोनों स्विफ्ट में मौजूद हैं
तो अपने स्वयं के कस्टम अधिसूचना को परिभाषित करने के लिए, जैसे किसी दिन करें:
public class MyClass {
static let myNotification = Notification.Name("myNotification")
}
फिर इसे कॉल करने के लिए:
NotificationCenter.default().post(name: MyClass.myNotification, object: self)
Notification.Name
कोई एनम होता, तो कोई भी नई सूचनाओं को परिभाषित करने में सक्षम नहीं होता। हम अन्यथा एनुम-जैसे प्रकारों के लिए संरचनाओं का उपयोग करते हैं जिन्हें नए सदस्यों को जोड़ने की अनुमति देने की आवश्यकता होती है। ( स्विफ्ट-इवोल्यूशन प्रस्ताव देखें ।)
Notification
एक मूल्य प्रकार (एक संरचना) है, जिससे कि यह स्विफ्ट के शब्दार्थ से मूल्य (im) के लिए लाभ हो सकता है। आमतौर पर, फाउंडेशन प्रकार स्विफ्ट 3 में अपने "एनएस" को गिरा रहे हैं, लेकिन जहां एक नया फाउंडेशन वैल्यू प्रकार इसे दबाने के लिए मौजूद है, पुराना संदर्भ प्रकार चारों ओर चिपक जाता है ("एनएस" नाम रखते हुए) ताकि आप अभी भी इसका उपयोग कर सकें आपको संदर्भ शब्दार्थ की आवश्यकता है या इसे उप-वर्ग करना है। प्रस्ताव देखें ।
आसान तरीका:
let name:NSNotification.Name = NSNotification.Name("notificationName")
NotificationCenter.default.post(name: name, object: nil)
आप 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)
case
एक एनम में केवल एस को ही उतारा जाना चाहिए, एनम को ही नहीं। टाइप नाम अपरकेस हैं, और एनम टाइप हैं।
मैं एक और विकल्प सुझा सकता हूं जो @CesarVarela के समान है।
extension Notification.Name {
static var notificationName: Notification.Name {
return .init("notificationName")
}
}
यह आपको सूचनाओं को आसानी से पोस्ट और सबस्क्राइब करने देगा।
NotificationCenter.default.post(Notification(name: .notificationName))
आशा है कि यह आपकी मदद करेगा।
मैंने अपने कार्यान्वयन को वहां और वहां से चीजों को मिलाकर किया, और इसे सबसे सुविधाजनक पाया। जो कोई भी दिलचस्पी हो सकती है, उसके लिए साझा करना:
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")
यह सिर्फ संदर्भ है
// 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)
एनम का उपयोग करने का लाभ यह है कि हमें यह जांचने के लिए कंपाइलर मिलता है कि नाम सही है। संभावित मुद्दों को कम करता है और रिफैक्टिंग को आसान बनाता है।
उन लोगों के लिए जो अधिसूचना नामों के लिए उद्धृत स्ट्रिंग्स के बजाय एनम का उपयोग करना पसंद करते हैं, यह कोड चाल करता है:
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)
}
}
तो आप इसे इस तरह से उपयोग कर सकते हैं:
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)
यदि आप स्ट्रिंग-केवल कस्टम सूचनाओं का उपयोग करते हैं, तो किसी भी वर्ग को विस्तारित करने का कोई कारण नहीं है लेकिन String
extension String {
var notificationName : Notification.Name{
return Notification.Name.init(self)
}
}
यदि आप चाहते हैं कि एक ऐसे प्रोजेक्ट में सफाई से काम किया जाए, जो एक ही समय में Objective-C और Swift दोनों का उपयोग करता है, तो मैंने पाया कि Objective-C में नोटिफिकेशन बनाना आसान है।
एक .m / .h फ़ाइल बनाएँ:
//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
(अपने प्रोजेक्ट के नाम पर) उन्हें स्विफ्ट के सामने लाने के लिए।
#import "CustomNotifications.h"
इस तरह Objective-C में अपनी सूचनाओं का उपयोग करें:
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(yourMethod:) name:yourNotificationName:nil];
और इस तरह स्विफ्ट (5) में:
NotificationCenter.default.addObserver(self, selector: #selector(yourMethod(sender:)), name: .yourNotificationName, object: nil)