Swift中无法从UIViewController访问自定义视图问题求助
从你的错误截图和代码来看,主要有几个关键问题导致无法访问自定义类GymCreditCardScanner,我来一步步帮你解决:
1. 视图控制器未遵守代理协议
你的PaymentDetailsVC实现了代理方法,但没有明确声明遵守GymCreditCardScannerViewDelegate协议,编译器无法识别这些方法的归属,还会影响代理的赋值逻辑。
修正方案:
class PaymentDetailsVC: UIViewController, GymCreditCardScannerViewDelegate { // 添加协议遵守声明 var scanner: GymCreditCardScanner? //MARK: Credit card scanning @IBAction func scanCreditCard(_ sender: Any) { cardField.resignFirstResponder() scanner = GymCreditCardScanner.initIntoView(view, withDelegate: self) as? GymCreditCardScanner // 显式类型转换 } func creditCardScannerDidCancel(_ scanner: Any?) { guard let scanner = scanner as? GymCreditCardScanner else { return } scanner.remove() self.scanner = nil } func creditCardScanner(_ scanner: Any?, scannedNumber number: String?) { guard let scanner = scanner as? GymCreditCardScanner else { return } scanner.remove() self.scanner = nil numberField.text = number } }
2. 初始化方法返回类型不匹配
你的initIntoView方法返回类型是Any?,但你把它赋值给GymCreditCardScanner?类型的变量,这会导致类型不兼容。推荐直接修改方法返回类型,或者在赋值时显式转换(上面代码已做转换)。
修正GymCreditCardScanner的initIntoView方法:
func initIntoView(_ superView: UIView?, withDelegate delegate: Any?) -> GymCreditCardScanner? { // 修改返回类型 let frame = CGRect(x: 0, y: 0, width: superView?.frame.size.width ?? 0.0, height: superView?.frame.size.height ?? 0.0) self.scannerdelegate = delegate as? GymCreditCardScannerViewDelegate screenFrame = frame // 剩余原有代码保持不变... return self }
3. Selector语法过时且不安全
你使用了字符串形式的Selector(("handleCancelPress:")),这种写法在Swift中容易因方法名拼写错误导致运行时崩溃,应该使用#selector语法:
修正GymCreditCardScanner中的按钮点击绑定:
// 替换cancelButton的target绑定代码 cancelButton?.addTarget(self, action: #selector(handleCancelPress(_:)), for: .touchUpInside) // 替换doneButton的target绑定代码 doneButton?.addTarget(self, action: #selector(handleDonePress(_:)), for: .touchUpInside)
同时给点击方法加上@objc标记(Selector需要暴露给OC运行时):
@objc func handleCancelPress(_ sender: Any?) { scannerdelegate?.creditCardScannerDidCancel(self) } @objc func handleDonePress(_ sender: Any?) { scannerdelegate?.creditCardScanner(self, scannedNumber: number) }
4. 可选优化:变量命名规范
你的代理属性命名scannerdelegate不符合Swift驼峰命名规范,建议改成scannerDelegate以提升代码可读性:
weak var scannerDelegate: GymCreditCardScannerViewDelegate?
记得同步修改所有用到该属性的代码位置,比如self.scannerDelegate = delegate as? GymCreditCardScannerViewDelegate等。
完成以上修改后,你就能正常访问自定义类GymCreditCardScanner,信用卡扫描功能也可以正常工作了。
内容的提问来源于stack exchange,提问作者Siva

