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

如何在UIView中初始化自定义参数?解决SampleSkinsCollectionView报错

解决UIView中自定义参数的初始化问题

错误原因分析

你遇到的两个Xcode错误本质是Swift初始化规则的约束:

  • 'self' used in property access 'frame' before 'super.init' call:调用super.init前self未完成初始化,不能访问self.frame属性
  • Property 'self.currentMenuItem' not initialized at super.init call:currentMenuItem是非可选存储属性,必须在调用父类初始化方法super.init前完成赋值

修正SampleSkinsCollectionView的初始化逻辑

调整初始化方法顺序,确保非可选存储属性在super.init前完成赋值,同时避免提前访问self:

import UIKit

final class SampleSkinsCollectionView: UIView {

    // MARK: - Dependencies
    var handlerCellDelegate: IHandlerCellDelegate?
    var currentMenuItem: MenuItem

    // MARK: - Private properties
    private lazy var collectionCardMaps = createCollectionView()
    private var modelForDisplay: [SkinsModel] = []

    // MARK: - Initializator
    // 主初始化方法:接收必要参数,frame设默认值
    init(currentMenuItem: MenuItem, frame: CGRect = .zero) {
        // 先初始化自身非可选属性
        self.currentMenuItem = currentMenuItem
        // 再调用父类初始化
        super.init(frame: frame)
        // 初始化完成后执行配置逻辑
        addUIView()
        setupConfiguration()
        setupLayout()
    }

    // 禁用系统默认frame初始化(如果只允许通过带currentMenuItem的方法创建)
    override init(frame: CGRect) {
        fatalError("Use init(currentMenuItem:frame:) instead")
    }

    // 便利初始化:同时传入代理和必要参数
    convenience init(currentMenuItem: MenuItem, handlerCellDelegate: IHandlerCellDelegate?, frame: CGRect = .zero) {
        self.init(currentMenuItem: currentMenuItem, frame: frame)
        self.handlerCellDelegate = handlerCellDelegate
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    // MARK: - Public methods
    func reloadModel(viewModel: [SkinsModel]) {
        self.modelForDisplay = viewModel
        collectionCardMaps.reloadData()
    }
}

修正父视图控制器代码

创建SampleSkinsCollectionView时传入currentMenuItem:

final class MainSecondViewController: HeaderMenuViewController {

    // MARK: - Dependencies
    var iterator: IMainIterator?
    var handlerCardCellDelegate: IHandlerCellDelegate?

    // MARK: - Private properties
    private var currentMenuItem: MenuItem?
    // 延迟初始化,确保currentMenuItem赋值后再创建视图
    private lazy var collectionCardSkins = SampleSkinsCollectionView(
        currentMenuItem: currentMenuItem!,
        handlerCellDelegate: self
    )

    override init(delegate: IMenuDelegate, currentMenuItem: MenuItem) {
        super.init(delegate: delegate, currentMenuItem: currentMenuItem)
        self.currentMenuItem = currentMenuItem
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    // MARK: - Public methods
    override func viewDidLoad() {
        super.viewDidLoad()
        setupConfiguration()
        addUIView()
    }

    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        setupLayout()
    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        navigationController?.setNavigationBarHidden(true, animated: false)
    }
}

private extension MainSecondViewController {
    func setupConfiguration() {
        collectionCardSkins.translatesAutoresizingMaskIntoConstraints = false
    }
}

关键注意点

  1. Swift初始化顺序:所有非可选存储属性必须在super.init调用前完成初始化
  2. 避免提前访问self:super.init完成前,不能访问self的任何属性或方法
  3. 统一初始化链:设计一个主初始化方法,其他初始化方法通过调用主方法实现逻辑复用

内容的提问来源于stack exchange,提问作者Steven Kirke

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 17:37:01