Swift 在尝试获取价值时得到 Nil

Posted

技术标签:

【中文标题】Swift 在尝试获取价值时得到 Nil【英文标题】:Swift getting Nil when attempting to get value 【发布时间】:2021-03-11 20:35:51 【问题描述】:

我不确定为什么我在尝试打印时在 optional 上收到此 nil 错误。有人可以提供任何输入吗?我能够从 aplicationContext 输出值是没有意义的,但是当我尝试从 applicationContext["hearRate"] 获取值时,我得到了 nil。

    func session(_ session: WCSession, didReceiveApplicationContext applicationContext: [String : Any]) 
        print("didReceiveApplicationContext\n\t\(applicationContext)")
        let hrValue = applicationContext["heartRate"] as? String
        print(applicationContext["hearRate"])
        print(hrValue)
        //heartRate.text = hrValue
    
console - output
2021-03-10 18:41:04.623716-0700 Trainer+[1824:759737] Metal API Validation Enabled
session active state
didReceiveApplicationContext
    ["heartRate": 00BPM]
nil
Optional("00BPM")
Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value: file Trainer_/ViewController.swift, line 57
2021-03-10 18:41:04.999001-0700 Trainer+[1824:759754] Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value: file Trainer_/ViewController.swift, line 57

更新 - 忽略错字,发现 IBOutlet 存在问题

    func session(_ session: WCSession, didReceiveApplicationContext applicationContext: [String : Any]) 
        print("didReceiveApplicationContext\n\t\(applicationContext)")
        let hrValue = applicationContext["heartRate"] as? String
        print(applicationContext["heartRate"])
        print(hrValue)
        //heartRate.text = hrValue
        heartRate.text = "test"
    
2021-03-11 12:45:05.482464-0700 Trainer+[1873:817768] Metal API Validation Enabled
session active state
didReceiveApplicationContext
    ["heartRate": 91BPM]
Optional(91BPM)
Optional("91BPM")
Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value: file Trainer_/ViewController.swift, line 58
2021-03-11 12:45:05.887523-0700 Trainer+[1873:817966] Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value: file Trainer_/ViewController.swift, line 58

来自 watchconnectivity 的 func session(didReceiveApplicationContext) 正在按预期工作。我相信我的问题来自于我将 heartRate 标签移动到“视图容器”。我在移动标签的同时添加了 watchconnectivity,并认为它会起作用。

这可能需要一个不同的问题,不确定,我如何通过同时可见的多个视图控制器传递数据。因为我在 ViewController 上创建会话,所以我还不知道如何在不将 ViewController 的完整“自我”引用传递给 DetailViewController 的情况下将数据传递给其他视图控制器。来自 Java 和 php,我觉得这不是好的编码习惯。

我正在考虑扩展/委托和原型。我稍微了解它们,但我目前正在开发一个应用程序,我的主要目标是拥有一个工作原型。我会回来重构代码修复并修复任何漏洞。如果任何有经验的机构可以为我提供任何可靠的资源。厌倦了点击谷歌的下一页,因为我找不到我正在寻找的答案,哈哈。

更新 #3

class ViewController: UIViewController, WCSessionDelegate 
    
    @IBOutlet weak var cont: DetailViewController!

    override func viewDidLoad() 
        super.viewDidLoad()
        
        if WCSession.isSupported() 
            connectivitySession = WCSession.default
            connectivitySession?.delegate = self
            connectivitySession?.activate()
        
    
    func session(_ session: WCSession, didReceiveApplicationContext applicationContext: [String : Any]) 
        print("didReceiveApplicationContext\n\t\(applicationContext)")
        let hrValue = applicationContext["heartRate"] as? String
        print(applicationContext["heartRate"])
        print("container\n\t\(cont.heart.text)")
        cont.heart.text = "test"
    
    ******


// class assigned to 'view container' in ViewController in SB
class DetailViewController: UIView 
    
    @IBOutlet weak var heart: UILabel!
    //    @IBOutlet weak var hearRate: UILabel!
    @IBOutlet weak var sessionTimer: UILabel!
    @IBOutlet weak var currentActivity: UILabel!
    @IBOutlet weak var startButton: UIButton!
    @IBOutlet weak var activityTimer: UILabel!


Output 
2021-03-11 15:22:15.294727-0700 Trainer+[1938:854826] Metal API Validation Enabled
2021-03-11 15:22:15.628977-0700 Trainer+[1938:854826] *** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<Trainer_.ViewController 0x102e04ec0> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key menuContainer.'
*** First throw call stack:
(0x1986ad9d8 0x1aca33b54 0x1985be6e4 0x19986aca8 0x19a84f6a4 0x19ab5f254 0x198598298 0x19ab5b218 0x19a856d88 0x19a857114 0x19a8577e8 0x19af56448 0x19af55c5c 0x19af56af0 0x19af67730 0x19b17aba0 0x19a434be4 0x19af19ca0 0x19af1a044 0x19aa59ab8 0x1a79d7704 0x1a79ff130 0x1a79e4e60 0x1a79fee44 0x101291528 0x1012949f0 0x1a7a23e60 0x1a7a23b28 0x1a7a23ffc 0x19862dbf0 0x19862daf0 0x19862ce9c 0x1986273e0 0x198626ba0 0x1af38f598 0x19af182f4 0x19af1d874 0x1abda7b54 0x100f75a08 0x100f75980 0x100f75a4c 0x198305568)
libc++abi.dylib: terminating with uncaught exception of type NSException
*** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<Trainer_.ViewController 0x102e04ec0> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key menuContainer.'
terminating with uncaught exception of type NSException
(lldb) 

【问题讨论】:

您好,感谢您的提问,请阅读问题,并注意第二组代码和输出,以及我添加的附加信息。如果我需要为您澄清任何事情,请告诉我。感谢建设性的评论。] 我想我现在明白你的评论了。原始问题是我问题的更新部分之前的所有内容,我编辑了原始问题,但注意到它已关闭并且其他人无法回答。用所有以前的内容创建了这个新的,所以我和如果其他人有类似的问题,可以得到答案,而不必跳过帖子。 老兄,我不知道如何回答你的问题,而不是听起来讽刺或矛​​盾?你看过第二个代码块吗?或者至少阅读更新行? 是的,我知道它是如何令人困惑的,我只是认为没有人会为已关闭的帖子而烦恼。 你检查 heartRate 不是 nil 吗?这可能来自不正确的 IBOutlet 定义。尝试打印心率。您也可以将这一行写为:heartRate?.text = htvValue 【参考方案1】:

通过从 uiviewcontroller 更改为自定义类的名称来回答我自己的问题。

这适用于在同一屏幕上使用多个视图控制器的 iphone 的基本手表连接会话。

委托、扩展等不是必需的。需要设置您的 segue、辅助控制器和连接。

class ViewController: UIViewController, WCSessionDelegate 
    
    var variable: Any? // Your variable type
    
    var sessionVariable: WCSession?
    
    var secondVC: SecondViewController!
    
    override func viewDidLoad() 
        super.viewDidLoad()
        
        // start session
        if WCSession.isSupported() 
            sessionVariable = WCSession.default
            sessionVariable?.delegate = self
            sessionVariable?.activate()
        
    
    
    
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) 
        // using segue.identifier, save live ViewController to your variable
        if segue.identifier == "Storyboard Segue Identifier" 
            if let destinationVC = segue.destination as? SecondViewController 
                secondVC = destinationVC
            
        
    

    func session(_ session: WCSession, activationDidCompleteWith activationState: WCSessionActivationState, error: Error?) 
        print("session active state")
    
    
    //using dispatchqueue, to update label on main thread, use self.secondVC.variable to update.
    func session(_ session: WCSession, didReceiveApplicationContext applicationContext: [String : Any]) 
        let contextValue = applicationContext["context"] as? String
        DispatchQueue.main.async 
            self.secondVC.variable.text = contextValue
        
    


class HealthViewController: UIViewController 
    
    
    @IBOutlet weak var varialble: UILabel!
    
    override func viewDidLoad() 
        super.viewDidLoad()
    

【讨论】:

以上是关于Swift 在尝试获取价值时得到 Nil的主要内容,如果未能解决你的问题,请参考以下文章

Swift:尝试查询 api 时得到 nil

当我尝试重新加载日期时,Swift 5 TableView 在 ViewController 中发现 nil

在展开可选值 uint32 swift 时意外发现 nil

Swift 中的可选类型错误:致命错误:在展开可选值时意外发现 nil

在 Swift 中访问 NSManagedObject 属性

当我尝试获取边界时,为啥 previewLayer 返回 nil?