zoukankan      html  css  js  c++  java
  • Swift 正确使用CFNotificationCenterAddObserver w /回调

    Swift - 正确使用CFNotificationCenterAddObserver w /回调

    问题描述

    in'ViewController.swift'



    创建此回调:

     func callback(cf:CFNotificationCenter !,  ump:UnsafeMutablePointer< Void>, cfs:CFString !,  up:UnsafePointer< Void> ;,  cfd:CFDictionary! - >无效{ }  

    使用此观察者:

     CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), nil, self.callback,myMESSage,  CFNotificationSuspensionBehavior.DeliverImmediately) 

    导致此编译器错误:
    AC函数指针只能通过引用一个'func'或一个文字闭包而形成



    想法?

    只有一个全局函数或一个闭包(不捕获任何状态),$ b
    c中的CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(),
    nil,
    {(_,observer,name,_,_)print(received notification:\(name) $ b},
    myMessage,
    nil,
    .DeliverImmediately)


    $ b b

    但是因为闭包不能捕获上下文,所以没有直接引用 self 及其属性和实例方法。
    例如,您不能添加

     self.label.stringValue =got it //错误:不能从捕获上下文的闭包形成C函数指针 

    当一个通知到达时,UI。



    有一个解决方案,但由于
    Swift的严格类型系统,它有点复杂。
    类似于 Swift 2 - UnsafeMutablePointer< Void>到对象,你可以将指针转换为
    self 为void指针,传递 observer 参数
    到注册,并将其转换回
    中的对象指针回调。

     class YourClass {  func callback(name:String){ print(received notification:\(name))}   func registerObserver(){  //指向`self`的void指针: let observer = UnsafePointer< Void>(Unmanaged.passUnretained(self).toOpaque())  CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), observer, {(_,observer,name,_,_) - > Void in   //提取指针从void指针到`self`: let mySelf = Unmanaged< YourClass> .fromOpaque( COpaquePointer(observer))。takeUnretainedValue() //调用实例方法: mySelf .callback(name as String)},myMessage, nil, .DeliverImmediately)}   // .. }  

    闭包作为实例方法的trampoline / p>

    指针是一个未保存的引用,因此必须确保
    在释放对象之前被移除。






    更新Swift 3:

     class YourClass {  func callback(_ name:String){ print(received notification:\(name))}   func registerObserver(){  //指向`self`的指针: let observer = UnsafeRawPointer(Unmanaged.passUnretained(self).toOpaque())  CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), observer, {(_,observer,name,_,_) - > 如果let observer = observer,则let name = name {  // void void指针指向`self`指针: let mySelf =非托管< YourClass> .fromOpaque (观察者).takeUnretainedValue() //调用实例方法: mySelf.callback(name.rawValue as String)} },myMessageas CFString, nil, .deliverImmediately)}   // ... }  

    in 'ViewController.swift'

    Creating this callback:

    func callback(cf:CFNotificationCenter!, 
        ump:UnsafeMutablePointer<Void>, 
        cfs:CFString!, 
        up:UnsafePointer<Void>, 
        cfd:CFDictionary!) -> Void {
    
    }
    

    Using this observer:

    CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), 
        nil, 
        self.callback, 
        "myMESSage", 
        nil, 
        CFNotificationSuspensionBehavior.DeliverImmediately)
    

    Results in this compiler error: "A C function pointer can only be formed from a reference to a 'func' or a literal closure"

    Thoughts?

    解决方案

    The callback is a pointer to a C function, and in Swift you can pass only a global function or a closure (which does not capture any state), but not an instance method.

    So this does work:

        CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(),
            nil,
            { (_, observer, name, _, _) in
                print("received notification: \(name)")
            },
            "myMessage",
            nil,
            .DeliverImmediately)
    

    But since the closure cannot capture context, you have no direct reference to self and its properties and instance methods. For example, you cannot add

               self.label.stringValue = "got it"
               // error: a C function pointer cannot be formed from a closure that captures context
    

    inside the closure to update the UI when a notification arrived.

    There is a solution, but it is a little bit complicated due to Swift's strict type system. Similarly as in Swift 2 - UnsafeMutablePointer<Void> to object, you can convert the pointer to self to a void pointer, pass that as the observer parameter to the registration, and convert it back to an object pointer in the callback.

    class YourClass { 
    
        func callback(name : String) {
            print("received notification: \(name)")
        }
    
        func registerObserver() {
    
            // Void pointer to `self`:
            let observer = UnsafePointer<Void>(Unmanaged.passUnretained(self).toOpaque())
    
            CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(),
                observer,
                { (_, observer, name, _, _) -> Void in
    
                    // Extract pointer to `self` from void pointer:
                    let mySelf = Unmanaged<YourClass>.fromOpaque(
                            COpaquePointer(observer)).takeUnretainedValue()
                    // Call instance method:
                    mySelf.callback(name as String)
                },
                "myMessage",
                nil,
                .DeliverImmediately)
        }
    
        // ...
    }
    

    The closure acts as a "trampoline" to the instance method.

    The pointer is an unretained reference, therefore you must ensure that the observer is removed before the object is deallocated.


    Update for Swift 3:

    class YourClass {
    
        func callback(_ name : String) {
            print("received notification: \(name)")
        }
    
        func registerObserver() {
    
            // Void pointer to `self`:
            let observer = UnsafeRawPointer(Unmanaged.passUnretained(self).toOpaque())
    
            CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(),
                observer,
                { (_, observer, name, _, _) -> Void in
                    if let observer = observer, let name = name {
    
                        // Extract pointer to `self` from void pointer:
                        let mySelf = Unmanaged<YourClass>.fromOpaque(observer).takeUnretainedValue()
                        // Call instance method:
                        mySelf.callback(name.rawValue as String)
                    }
                },
                "myMessage" as CFString,
                nil,
                .deliverImmediately)
        }
    
        // ...
    }

    Update for Swift 5:

    发送通知

    sendNotificationForMessageWithIdentifier(identifier: "broadcastStarted")

    func sendNotificationForMessageWithIdentifier(identifier : String) {

            let center : CFNotificationCenter = CFNotificationCenterGetDarwinNotifyCenter()

    //        let userInfo : CFDictionary = CFDictionary(info)

            let identifierRef : CFNotificationName = CFNotificationName(identifier as CFString)

            CFNotificationCenterPostNotification(center, identifierRef, nil, nil, true)

        }

    ///通知回调

        func callback(_ name : String) {

            print("received notification: \(name)")

            mainView.vedioV.uploadBtn.isHidden = false

            ///视频预览

            DispatchQueue.main.asyncAfter(deadline: .now() + 1) { [weak self] in

                let userDefault = UserDefaults.init(suiteName: "group.dc.record")

                let pathstr = userDefault?.object(forKey: "videoFilePath")

                guard let path = pathstr else {

                    return

                }

                self?.vm.urlVedioString = URL(fileURLWithPath: path as! String)

                self?.mainView.vedioV.loadImageReview(url: URL(fileURLWithPath: path as! String))

            }

        }

        

        ///通知注册

        func registerObserver() {

            let observer = UnsafeRawPointer(Unmanaged.passUnretained(self).toOpaque())

            CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(),

                                            observer,

                                            { (_, observer, name, _, _) -> Void in

                if let observer = observer, let name = name {

                    // Extract pointer to `self` from void pointer:

                    let mySelf = Unmanaged<OTCAppealVC>.fromOpaque(observer).takeUnretainedValue()

                    // Call instance method:

                    mySelf.callback(name.rawValue as String)

                }

            },

                                            "broadcastFinished" as CFString,

                                            nil,

                                            .deliverImmediately)

        }

    通知移除

    deinit {

            let observer = UnsafeRawPointer(Unmanaged.passUnretained(self).toOpaque())

            let cfName: CFNotificationName = CFNotificationName("broadcastFinished" as CFString)

            CFNotificationCenterRemoveObserver(CFNotificationCenterGetDarwinNotifyCenter(), observer, cfName, nil)

        }

    每天都有不一样的太阳
  • 相关阅读:
    【树状数组】bzoj2743 [HEOI2012]采花
    【二分答案】bzoj1639 [Usaco2007 Mar]Monthly Expense 月度开支
    【二分答案】【最短路】bzoj1614 [Usaco2007 Jan]Telephone Lines架设电话线
    【二分答案】【Heap-Dijkstra】bzoj2709 [Violet 1]迷宫花园
    【二分答案】【字符串哈希】bzoj2084 [Poi2010]Antisymmetry
    【二分答案】【最大流】bzoj1305 [CQOI2009]dance跳舞
    【计算几何】【二分答案】【最大流】bzoj1822 [JSOI2010]Frozen Nova 冷冻波
    【二分答案】【最大流】bzoj3130 [Sdoi2013]费用流
    【动态规划】bzoj3992 [Sdoi2015]序列统计 10分
    【二分答案】【最大流】bzoj3993 [Sdoi2015]星际战争
  • 原文地址:https://www.cnblogs.com/YangFuShun/p/15776787.html
Copyright © 2011-2022 走看看