【问题标题】:how to safely unwrapped header value如何安全地解开标头值
【发布时间】:2018-03-25 10:39:15
【问题描述】:

我的应用程序崩溃,因为它在解开值“header”时发现 nil 我尝试使用保护 let 语句,虽然它不起作用,安全解开这个值的最佳方法是什么?

override func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {

    self.headerOpen = true

    if self.headerOpen == true {

      let header = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: headerId, for: indexPath) as! HomePageHeader

    header.currentUser = self.currentUser
    header.usersLocation = self.usersLocation
    header.delegate = self

    reloadInputViews()

    } else if headerOpen == false {


        print("header open is false")

        }




    return header!

}

【问题讨论】:

    标签: swift collections view


    【解决方案1】:

    if let ...guard let ... 可以帮助您。例如:

    if let header = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: headerId, for: indexPath) as? HomePageHeader {
        print("header unwrapped")
    }
    

    guard let header = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: headerId, for: indexPath) as? HomePageHeader else { print("header not unwrapped") }
    print("header unwrapped")
    

    【讨论】:

    • 如果 let 或 guard 似乎不起作用,我得到错误;条件绑定的初始化程序必须具有 Optional 类型,而不是 'HomePageHeader'
    • 尝试将!替换为?
    【解决方案2】:

    我尝试使用 guard let 语句,但它不起作用

    因为您使用的是as!,所以! 表示值的强制解包,它忽略了可选类型,如果UICollectionReusableView 不符合HomePageHeader,您的应用程序将崩溃。

    你必须使用as? 来保证这个安全,就像这样

    guard let header = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: headerId, for: indexPath) as? HomePageHeader else {
        return UICollectionReusableView()
    }
    
    // do stuff with the header
    header.currentUser = self.currentUser 
    

    【讨论】:

      【解决方案3】:

      Swift 中,您可以使用以下方式之一unwrap an optional

      1. 使用 ! 强制解开 optional 值。要使用!,您必须确保optional 不包含nil。使用! 有点冒险,因为解开nil 值会导致runtime exception

      let header = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: headerId, for: indexPath) as! HomePageHeader
      

      在上面的代码中,您强制解包,即as! HomePageHeader

      collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: headerId, for: indexPath) 必须返回一个 nil,然后您将其解包,结果您的应用程序崩溃了。

      2. 另一个可用于获取展开值的选项是使用 Optional Binding,即 if let 语句。 p>

      您使用可选绑定来确定可选是否包含 值,如果是,则使该值可用作临时常量 或变量。可选绑定可以与 if 和 while 语句一起使用 检查可选值中的值,并提取该值 作为单个操作的一部分,转换为常量或变量。

      在您的代码中,您可以像这样使用它:

      if let header = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: headerId, for: indexPath) as? HomePageHeader
      {
         header.currentUser = self.currentUser
         header.usersLocation = self.usersLocation
         header.delegate = self
      }
      

      Optional Binding 仅适用于 optionals。这就是为什么我使用as? HomePageHeader 而不是as! HomePageHeader

      3.您也可以使用guard语句来处理optional的值。

      守卫语句,如 if 语句,执行语句取决于 关于表达式的布尔值。您使用警卫声明 要求条件必须为真,以便后面的代码 要执行的保护语句。与 if 语句不同,守卫 语句总是有一个 else 子句—— else 子句中的代码是 条件不成立时执行。

      在你的代码中,你可以像这样使用它:

      guard let header = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: headerId, for: indexPath) as? HomePageHeader else
      {
         return
      }
      header.currentUser = self.currentUser
      header.usersLocation = self.usersLocation
      header.delegate = self
      

      如果您仍然遇到任何问题,请告诉我。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-07-12
        • 2018-06-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多