我是 iOS 开发的新手,所以如果我遗漏了一些明显的东西,请原谅我。我有一个 View Controller ,其中包含一个 subview ,我在其中创建了一个小键盘,目前我想为小键盘 View 提供它自己的 UIView 子类,因为我想用它做一些不同的事情。现在小键盘只是从按下的键创建一个字符串,我已经设置了一个委托(delegate)来将该字符串传递到我想使用它的任何其他地方(尽管我也尝试过直接在 View 中访问原始输入带有 let a = subview(); label.text = a.rawInput 的 Controller )。
每当我尝试将 View Controller 中的 UILabel 文本设置为 subview 的原始输入时,无论是通过委托(delegate)还是直接,都会发现 UILabel 为 nil 并在标题中抛出错误。
我尝试过的事情:
我被难住了。这是我相关的小键盘代码:
import UIKit
protocol NumpadDelegate {
func updateInput(input: String)
}
class Numpad: UIView {
// MARK: UI outlets
@IBOutlet weak var decButton: UIButton!
// MARK: Properties
var rawInput: String = ""
var visibleInput: String = ""
var calcInput: String = ""
var operandReady = 1
var percentWatcher = 0
var delegate: NumpadDelegate? = BudgetViewController()
// MARK: Functions
func handleRawInput(str: String) {
rawInput += str
print("numpad input is \(rawInput)")
delegate?.updateInput(rawInput)
}
这是 View Controller 代码:
import UIKit
class BudgetViewController: UIViewController, NumpadDelegate {
// MARK: Properties
//@IBOutlet weak var transactionValueField: UITextField!
@IBOutlet weak var remainingCashForIntervalLabel: UILabel!
@IBOutlet weak var intervalDenoterLabel: UILabel!
@IBOutlet weak var currencyDenoterLabel: UILabel!
@IBOutlet weak var mainDisplayView: TransactionType!
@IBOutlet weak var inactiveInputView: InactiveInput!
@IBOutlet weak var numpadView: Numpad!
@IBOutlet weak var rawInputLabel: UILabel!
var remainingCashForInterval = 40
let display = TransactionType()
var testInput = "" {
didSet {
viewDidLoad()
}
}
override func viewDidLoad() {
super.viewDidLoad()
// let numpad = Numpad()
// numpad.delegate = self
// print("\(numpad.delegate)")
self.rawInputLabel.text = testInput
}
func updateInput(input: String) {
print("view controller now has \(input)")
display.mainInput = input
testInput = input
}
作为旁注,如果您注意到我的协议(protocol)不是类类型,出于某种原因向它添加 : class 并将我的委托(delegate)声明为弱变量会阻止委托(delegate)工作。有什么建议吗?
最佳答案
您像这样分配委托(delegate):
var delegate: NumpadDelegate? = BudgetViewController()
这并没有引用呈现场景的 View Controller ,而是一个新的空白 View Controller 。这就是为什么当你使用 weak ,它被释放的原因(因为 View Controller 的孤立实例没有对它的强引用)。
您应该将协议(protocol)定义为 class协议(protocol),并定义 delegate成为:
weak var delegate: NumpadDelegate?
然后,在 View Controller 的 viewDidLoad 中,取消注释设置该委托(delegate)的行:
numpadView.delegate = self
但是,不要取消注释 numpad = Numpad() 行;这是不正确的,因为它会创建另一个 Numpad实例。但是您确实想设置现有 Numpad 的委托(delegate), 不过。
这两个问题(即,获取对将成为 Numpad View 委托(delegate)的 View Controller 的引用;以及获取对 Storyboard呈现的 Numpad View 的引用)表明对呈现 Storyboard场景的过程。
基本流程如下:
view ,以及该场景的所有 subview 都将为您实例化; IBOutlet场景基类中对您创建的 socket 的引用;和viewDidLoad被称为。这过于简单化了,但这是基本过程。
但关键是 Storyboard场景中引用的所有这些 View Controller 和 View 都是为您创建的。您不想尝试自己创建任何这些(并且 () 或 BudgetViewController() 末尾的 Numpad() 表示“创建 x 的新实例”,这不是我们想要在这里做的)。
因此,当我们需要获取对 View Controller 的引用时,我们可以通过编程方式指定 delegate对于其中一个 View ,您可以在 viewDidLoad 中执行此操作,此时self引用 Storyboard为我们实例化的 View Controller 。我们不想实例化一个新的。同样,当您想要引用 Numpad 时 Storyboard为我们实例化(为了连接它的 delegate ),您使用 IBOutlet您连接到 Interface Builder,而不是以编程方式实例化一个新的 Numpad与 Numpad() .
关于ios - Swift 2.2 - 更新 UILabel 抛出 "unexpectedly found nil while unwrapping an optional value",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38554768/