swift 条件函数 return

swift conditional function return

我想知道如何在 swift 中管理条件 return。例如,我 return 根据调用的 collectionview 委托创建一个自定义 UICollectionViewCell:

    func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
      if (collectionView.isEqual(collectionView1)) {
         var cell = self.epgCollectionView.dequeueReusableCellWithReuseIdentifier("Cell1", forIndexPath: indexPath) as Cell1
         return cell
      }
      else if (collectionView.isEqual(collectionView2)) {
        var cell = self.epgCollectionView.dequeueReusableCellWithReuseIdentifier("Cell2", forIndexPath: indexPath) as Cell2
        return cell
      }
}

编译器说 "Missing return statement in a function expeted to return UICollectionViewCell",即使在这两种情况下我都在 returning 一个单元格。

我添加

解决了
return UICollectionViewCell()

在函数的底部,但我认为这不是正确的方法。

我知道我可以在第一个 'if' 上方声明单元格,修改它并在 'if' 之外的函数末尾 return,然后 [=29] =] 呼叫挂起。

谢谢大家

因为你需要 return 一个 UICollectionViewCell,如果你为它创建一个单一的 var 和 return 它会更好(我不喜欢写多个return 方法中的语句)因此您可以将其更改为:

func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell
{
      var cell = UICollectionViewCell()
      if (collectionView.isEqual(collectionView1))
      {
         cell = self.epgCollectionView.dequeueReusableCellWithReuseIdentifier("Cell1", forIndexPath: indexPath) as Cell1
      }
      else if (collectionView.isEqual(collectionView2))
      {
         cell = self.epgCollectionView.dequeueReusableCellWithReuseIdentifier("Cell2", forIndexPath: indexPath) as Cell2
      }
      return cell
}

为了解释@MidhunMP 的回答,现在您的代码可以在没有任何 return 值的情况下结束。例如,看看这段代码,它与您的相似:

func myFunc() -> Int {
    let myNumber = random() % 3
    if myNumber == 0 {
        return 0
    }
    else if myNumber == 1 {
        return 1
    }
}

如果 myNumber 是 2 怎么办?函数结束时没有任何 return 值,这是不可能发生的。

要么将 return 语句移到代码末尾,要么添加一个 else 子句。两者都确保您的函数在任何情况下都会 return 一个值。

您将需要:

func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
    var cell = UICollectionViewCell()
    if (collectionView.isEqual(collectionView1)){
        cell = self.epgCollectionView.dequeueReusableCellWithReuseIdentifier("Cell1", forIndexPath: indexPath) as Cell1
    } else if (collectionView.isEqual(collectionView2)){
        cell = self.epgCollectionView.dequeueReusableCellWithReuseIdentifier("Cell2", forIndexPath: indexPath) as Cell2
    }
    return cell
}

或者,

func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
    var cell = UICollectionViewCell()
    if (collectionView.isEqual(collectionView1)){
        cell = self.epgCollectionView.dequeueReusableCellWithReuseIdentifier("Cell1", forIndexPath: indexPath) as Cell1
    return cell
    } else if (collectionView.isEqual(collectionView2)){
        cell = self.epgCollectionView.dequeueReusableCellWithReuseIdentifier("Cell2", forIndexPath: indexPath) as Cell2
    return cell
    } else {
        return cell;
    }
}

不过,还是用第一个吧,因为它更优雅,也更容易理解它的意思。

编译器无法知道 collectionView 将永远是 collectionView1collectionView2 在您的程序中,因此它会给出一条错误消息。

您可以做的是添加一个 else 案例来让编译器满意。 如果一切顺利,else 案例将永远不会被执行。如果有逻辑 你的程序出错,两个 if 条件不匹配,那么(在 "Debug" 配置)程序将中止并显示错误消息。

  if (collectionView.isEqual(collectionView1)) {
       let cell = self.epgCollectionView.dequeueReusableCellWithReuseIdentifier("Cell1", forIndexPath: indexPath) as Cell1
       // set cell properties ... 
       return cell
  }
  else if (collectionView.isEqual(collectionView2)) {
      let cell = self.epgCollectionView.dequeueReusableCellWithReuseIdentifier("Cell2", forIndexPath: indexPath) as Cell2
      // set cell properties ... 
      return cell
  }
  else {
      assertionFailure("unexpected collectionView")
      return UICollectionViewCell()
  }

或者(这只是前两个答案的微小变体), 将 cell 声明为 if 块之外的隐式解包选项:

func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
    var cell : UICollectionViewCell!
    if (collectionView.isEqual(collectionView1)){
        cell = self.epgCollectionView.dequeueReusableCellWithReuseIdentifier("Cell1", forIndexPath: indexPath) as Cell1
        // set cell properties ... 
    } else if (collectionView.isEqual(collectionView2)){
        cell = self.epgCollectionView.dequeueReusableCellWithReuseIdentifier("Cell2", forIndexPath: indexPath) as Cell2
        // set cell properties ... 
    }
    return cell
}

如果 none 个条件匹配,则返回 nil 运行时异常。

首先,给大家回答,请不要使用var。 其次,当然这是编译器方面的正确错误,因为委托方法不能确保 collectionView 是您定义的方法之一,并且要求您 return 是一个有效的单元格,所以如果您想要要在代码中明确保留这两种情况,那么您还需要定义一个有效但从未使用过的情况。 另请注意,将单元格转换为正确的 subclass 在这里是无用的,因为它们仍然被实例化为正确的 class 并且仍然 returned 作为 UICollectionViewCell 作为委托方法签名建议。

这是一个 Swifter 的实现方式:

/// define this in any .swift file included in your project
func ~=<T: AnyObject>(lhs: T, rhs: T) -> Bool {
    return lhs === rhs
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
    let reuseIdentifier = cellReuseIdentifierForCollectionView(collectionView)
    return epgCollectionView.dequeueReusableCellWithReuseIdentifier(reuseIdentifier, forIndexPath: indexPath)
}

private func cellReuseIdentifierForCollectionView(collectionView: UICollectionView) -> String {
    switch collectionView {
    case collectionView1:
        return "Cell1"
    case collectionView2:
        return "Cell2"
    default:
        return "" // this never happens but is still a bit of a code smell
    }
}

我找到解决办法了!比看起来更容易。只需将 "else if" 替换为 "else":

func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
  if (collectionView.isEqual(collectionView1)) {
     var cell = self.epgCollectionView.dequeueReusableCellWithReuseIdentifier("Cell1", forIndexPath: indexPath) as Cell1
     return cell
  }
  else (collectionView.isEqual(collectionView2)) {
    var cell = self.epgCollectionView.dequeueReusableCellWithReuseIdentifier("Cell2", forIndexPath: indexPath) as Cell2
    return cell
  }

}

现在可以了。谢谢大家!