我已成功从 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/