답변:
이를 위해 프로토콜을 사용할 수도 있습니다.
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
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 for NSNotification.Name에는 typealias가 있습니다.
public typealias Name = NSNotification.Name
혼란스러운 부분은 알림과 NSNotification이 모두 Swift에 존재한다는 것입니다.
따라서 고유 한 사용자 지정 알림을 정의하려면 다음과 같이하십시오.
public class MyClass {
static let myNotification = Notification.Name("myNotification")
}
그런 다음 그것을 부릅니다.
NotificationCenter.default().post(name: MyClass.myNotification, object: self)
Notification
값 형식 (구조체)가이 값 (IM) 가변성에 대한 스위프트의 의미 혜택을 누릴 수 있도록한다. 일반적으로 Foundation 유형은 Swift 3에서 "NS"를 삭제하지만이를 대체하기 위해 새로운 Foundation Value 유형 중 하나가 존재하는 경우 이전 참조 유형이 계속 유지되므로 ( "NS"이름 유지) 다음과 같은 경우에도 계속 사용할 수 있습니다. 참조 의미 체계 또는 하위 클래스가 필요합니다. 제안을 참조하십시오 .
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
열거 형 자체가 아니라 열거 형 의 s 만 소문자 여야합니다. 유형 이름은 대문자이고 열거 형은 유형입니다.
@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)
질문과 관련이 없지만 따옴표로 묶인 문자열을 입력하지 않도록 스토리 보드 segues에서도 동일한 작업을 수행 할 수 있습니다.
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];
그리고 Swift (5)에서는 다음과 같습니다.
NotificationCenter.default.addObserver(self, selector: #selector(yourMethod(sender:)), name: .yourNotificationName, object: nil)