program tip

Swift 3에서 사용자 지정 알림을 어떻게 생성합니까?

radiobox 2020. 8. 8. 12:17
반응형

Swift 3에서 사용자 지정 알림을 어떻게 생성합니까?


Objective-C에서 사용자 지정 알림은 단순한 NSString 일 뿐이지 만 WWDC 버전의 Swift 3에서는 그것이 무엇인지 명확하지 않습니다.


이를 위해 프로토콜을 사용할 수도 있습니다.

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변경 되는 경우에만 프로토콜을 수정해야합니다 .


그것을 달성하는 더 깨끗한 (내 생각에) 방법이 있습니다

extension Notification.Name {

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

그런 다음 이렇게 사용할 수 있습니다

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

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)

더 쉬운 방법 :

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)

@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)

The advantage of using enums is that we get the compiler to check that the name is correct. Reduces potential issues and makes refactoring easier.

For those who like using enums instead of quoted strings for notification names, this code does the trick:

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)
    }
}

Then you can use it like this:

NotificationCenter.default.post(.somethingHappened)

Though unrelated to the question, the same can be done with storyboard segues, to avoid typing quoted strings:

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

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

Then, on your view controller, call it like:

perform(segue: .unwindToX)

if you use string-only custom notifications, there's no reason to extend any classes but String

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

@CesarVarela's answer is good, but to make the code slightly cleaner, you can do the following:

extension Notification.Name {
    typealias Name = Notification.Name

    static let onSelectedSkin = Name("on-selected-skin")
    static let onFoo = Name("on-foo")
}

참고URL : https://stackoverflow.com/questions/37899778/how-do-you-create-custom-notifications-in-swift-3

반응형