Swift - 初始化UIViewController

5

我有一个在UIViewController中初始化参数的问题。我有一个类:

class ViewController: UIViewController {
   @IBOutlet var cardButtons: Array<UIButton>

   var flipCount = 0
   var game: CardMatchingGame
   var backCardImage: UIImage
   var frontCardImage: UIImage

   required init(coder aDecoder: NSCoder) {
      self.backCardImage = UIImage(named: "back")
      self.frontCardImage = UIImage(named: "front")
      self.game = CardMatchingGame(count: cardButtons.count, deck: createDeck())

      super.init(coder: aDecoder)
  }

  @IBAction func touchCardButton(sender: UIButton) {
      var cardButtonsArray = cardButtons as NSArray
      var chosenButtonIndex = cardButtonsArray.indexOfObject(sender)
      game.chooseCardAtIndex(chosenButtonIndex)
  }

  func createDeck() -> Deck {
      return PlayingCardDeck()
  }

}

but I've got a error in

count: cardButtons.count >> Variable 'self.cardButtons' used before being initialized/Property 'self.cardButtons' not initialized at super.init call

并且

deck: createDeck() >> 'self' used before super.init call

我该如何修复这个问题,以正确初始化UIViewController?
谢谢你的帮助。

你是否尝试在使用cardButtons之前,将super.init(coder: aDecoder)这一行放在前面?因为目前情况下,在类正确初始化之前,你正在使用它。 - holex
4个回答

3
你想要重写 awakeFromNib 并在那里访问outlet,而不是在初始化器中访问。 "nib-loading" 基础架构会发送一个 "awakeFromNib" 消息到从nib归档中重新创建的每个对象,但只有在归档中的所有对象都被加载和初始化后才会发送。当一个对象接收到 "awakeFromNib" 消息时,保证其所有outlet和action连接已经建立。 所以我建议使用类似以下的代码:
class ViewController: UIViewController {
   @IBOutlet var cardButtons: Array<UIButton>!

   var flipCount = 0
   var game: CardMatchingGame!
   var backCardImage: UIImage
   var frontCardImage: UIImage

   required init(coder aDecoder: NSCoder) {
      self.backCardImage = UIImage(named: "back")
      self.frontCardImage = UIImage(named: "front")

      super.init(coder: aDecoder)
  }

  override func awakeFromNib() {
      super.awakeFromNib()
      self.game = CardMatchingGame(count: cardButtons.count, deck: createDeck())
  }

  @IBAction func touchCardButton(sender: UIButton) {
      var cardButtonsArray = cardButtons as NSArray
      var chosenButtonIndex = cardButtonsArray.indexOfObject(sender)
      game.chooseCardAtIndex(chosenButtonIndex)
  }

  func createDeck() -> Deck {
      return PlayingCardDeck()
  }
}

你好,感谢您的回答,但是我在super.init(coder: aDecoder)这一行仍然遇到了错误。这次我得到了一个'self.game'未在super.init中初始化的错误。 - LakaLe_
你是否将它声明为隐式解包可选项,使用感叹号 (var game: CardMatchingGame!)? 如果是这样,你就不会收到那个错误。 - Mike Pollard

0

你可以将该方法设为静态的:

static func createDeck() -> Deck {
    return PlayingCardDeck()
}

并像这样使用它:

required init(coder aDecoder: NSCoder) {
    self.backCardImage = UIImage(named: "back")
    self.frontCardImage = UIImage(named: "front")
    self.game = CardMatchingGame(count: cardButtons.count, deck: ViewController.createDeck())

    super.init(coder: aDecoder)
}

0

在包含插座的视图加载完成之前,插座集合中的插座将无法完全使用。一旦视图完全加载到内存中,您的视图控制器的viewDidLoad()函数将被调用。此时,对视图的引用,如您的插座集合,应该可以使用。

因此,它看起来会像这样:

override func viewDidLoad()
{
    super.viewDidLoad()
    self.game = CardMatchingGame(count: cardButtons.count, deck: createDeck())
}

关于viewDidLoad()的更多信息,请参考苹果开发者网站:viewDidLoad


-1
如此规定,所有变量在调用super.init之前都应该被初始化。
由于@IBOutlet是由Interface Builder初始化的,感叹号应该没问题:

@IBOutlet var cardButtons: Array!

您可能还需要添加strong: https://dev59.com/g4Dba4cB1Zd3GeqPDV9d#24686602

嗨,感谢您的回答。我已将super.init()移动到初始化程序的第一行,但之后我又遇到了另一个错误:“在super.init调用时self.game未初始化”。 - LakaLe_

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接