ios - 使用 Swift 3 和 Obj C 通过 NSNotificationCenter 将通知数据从 App Delegate 传递到 View Controller

标签 ios objective-c swift

我已成功从 AppDelegate 中的远程通知负载 userInfo 接收数据。现在我尝试从 Storyboard推送到 View Controller ,将数据传递给它,并使用 NSNotificationCenter 更新变量,但收到错误:

Fatal error: unexpectedly found nil while unwrapping an Optional values

viewDidLoad中。谢谢参观!

(ObjC)AppDelegate.m

- (void)userNotificationCenter:(UNUserNotificationCenter *)center
didReceiveNotificationResponse:(UNNotificationResponse *)response
         withCompletionHandler:(void (^)())completionHandler
{
    NSDictionary *userInfo = response.notification.request.content.userInfo;
    NSDictionary *roomKey = [[[userInfo objectForKey:@"custom"] objectForKey:@"a"] objectForKey:@"roomKey"];
    NSLog(@"%@", roomKey);
    // Successfully prints correct roomKey, now need to pass to view controller and update variable. 

    [[NSNotificationCenter defaultCenter] postNotificationName:@"pushToFollowers" object:nil userInfo:roomKey];

    self.window = [[UIWindow alloc] initWithFrame:UIScreen.mainScreen.bounds];
    UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"main" bundle:nil];
    UIViewController *viewController = [storyboard instantiateViewControllerWithIdentifier:@"audience"];
    self.window.rootViewController = viewController;

    // line below is involved in optional crash
    [self.window makeKeyAndVisible];
}

(Swift 3)VC:

import UIKit
import SocketIO
import IHKeyboardAvoiding

@objc class AudienceViewController: UIViewController {

    @IBOutlet weak var previewView: UIView!
    @IBOutlet weak var statusLabel: UILabel!

    var room: Room!

    var player: IJKFFMoviePlayerController!
    let socket = SocketIOClient(socketURL: URL(string: Config.serverUrl)!, config: [.log(true), .forcePolling(true)])

    var overlayController: LiveOverlayViewController!

    override func viewDidLoad() {
        super.viewDidLoad()
        NotificationCenter.default.addObserver(self, selector: #selector(self.notificationArrived(_:)), name: NSNotification.Name(rawValue: "pushToFollowers"), object: nil)
        // Optional error occurs on next line
        let urlString = Config.rtmpPlayUrl + room.key
        player = IJKFFMoviePlayerController(contentURLString: urlString, with: IJKFFOptions.byDefault())
        player.view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
        player.view.frame = previewView.bounds
        previewView.addSubview(player.view)
        player.prepareToPlay()
        socket.on("connect") {[weak self] data, ack in
            self?.joinRoom()
        }
    }

    // function isn't firing
    @objc func notificationArrived(_ notification: NSNotification) {
        print(notification.userInfo!)
        if let custom = notification.userInfo?["custom"] as? [String: Any] {
            if let a = custom["a"] as? NSDictionary {
                if let roomKey = a["roomKey"] as? String {
                    print(roomKey)
                    room.key = (roomKey) as String
                }
            }
        }
    }
}

最佳答案

您在 View Controller 调用 viewDidLoad() 之前发布通知方式并成为观察者。这就是 notificationArrived(_:) 的原因。方法不会触发。 但崩溃实际上是因为您没有初始化room而发生的。属性,然后再尝试使用它。

所以当它尝试访问room.key时不但键值没有设置,room也没有启动。

你可以做的是创建一个 Room实例并将其传递给 AudienceViewController从 Storyboard 中实例化它后,通过属性,然后然后在 Controller View 加载后使用它。

AppDelegate.m

UIViewController *viewController = [storyboard instantiateViewControllerWithIdentifier:@"audience"];
Room *room = ... ; // create a room
room.key = roomKey;
viewController.room = room;

AudienceViewController

@objc class AudienceViewController: UIViewController {

    ...

    @objc var room: Room!

    ...

    override func viewDidLoad() {
        super.viewDidLoad()
        // if you are not planning on reusing this view controller for other rooms
        // then there's no reason for it to become an observer 
        let urlString = Config.rtmpPlayUrl + room.key
        ...
    }

    // notificationArrived(_:) is not needed anymore
}

关于ios - 使用 Swift 3 和 Obj C 通过 NSNotificationCenter 将通知数据从 App Delegate 传递到 View Controller,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46009705/

相关文章:

ios - UIAlertView Action 没有 swift 发生

objective-c - 通过 iOS 的 Facebook 实例显示用户的个人资料名称和图像

ios - 如何使用 UIBarButtonItem 作为菜单按钮将其作为图像移动到左侧?

ios arc内存释放如何处理

swift - 如何断言结构符合协议(protocol)?

swift - 如何使用 Swift 2 以编程方式从按钮打开 View Controller ?

c++ - UIImage 到 cv::Mat CV_8UC3

ios - 试图从 firebase Swift 获取数据

ios - 从任何其他类的 Controller 中删除 View ?

objective-c - 计算数组中特定月份的日期数