You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 08:57:32