Swift_Debug_Tip

本文介绍了一些Swift语言中的调试技巧,包括如何使用Thread.callStackSymbols获取调用堆栈信息,如何利用编译器提供的编译符号来简化日志输出,并讨论了如何在不同编译配置下控制日志的输出。

Swift 调试小技巧

调用堆栈

在调试阶段,除了打断点查看当前线程的调用堆栈外,也可以使用 Thread 的方法 callStackSymbols 来获取当前的调用堆栈符号。例如我们可以用下面的代码打印当前线程的调用堆栈:

for stackSymbol in Thread.callStackSymbols {
    print(stackSymbol)
}

打印当前代码的文件信息

有时候我们不仅需要打印指定的信息,而且需要打印当前文件名,当前方法的信息,如果手动书写这些信息将会非常麻烦,而且随着代码的改动,这些信息可能会频繁的改动。

在 Swift 中,编译器提供了几个编译符号来满足类似的需求,它们是:

符号类型描述
#fileString包含这个符号的文件的路径
#lineInt符号出现处的行号
#columnInt符号出现处的列
#functionString包含这个符号的方法名字

我们可以使用上面的编译符号写一个更好的 print 方法:

func printLog<T>(message: T,
                 file: String = #file,
                 method: String = #function,
                 line: Int = #line)
{
    print("\((file as NSString).lastPathComponent)[\(line)], \(method): \(message)")
}

对于 log 的输出更多的开发和调试阶段,过多的输出可能对性能有所影响,所以在 Realease 版本中关闭掉向控制台输出也是软件开发中一种常见的做法。通过条件编译的方法,我们可以添加条件,并设置合适的编译配置,使 printLog 的内容在 Release 时被去掉,从而成为一个空方法:

func printLog<T>(message: T,
                    file: String = #file,
                  method: String = #function,
                    line: Int = #line)
{
    #if DEBUG
    print("\((file as NSString).lastPathComponent)[\(line)], \(method): \(message)")
    #endif
}

新版本的 LLVM 编译器在遇到空方法时,会将整个方法去掉,完全不去调用它,从而实现零成本。

关键字的使用

在 Swift 语言中,会有一些关键字,比如:do, if, while, for 等等。在编码的时候,我们应该尽量避免使用关键字,但如果我们必须使用 Swift 中的关键字时,可以用反引号(`)将关键词包住。例如在 RxSwift 中,使用了关键字 do 作为方法名,具体定义如下:

public func `do`(onError: ((Swift.Error) throws -> Void)? = nil,
             onCompleted: (() throws -> Void)? = nil,
             onSubscribe: (() -> ())? = nil,
             onSubscribed: (() -> ())? = nil,
             onDispose: (() -> ())? = nil)
-> Completable {
    return Completable(raw: primitiveSequence.source.do(
        onError: onError,
        onCompleted: onCompleted,
        onSubscribe: onSubscribe,
        onSubscribed: onSubscribed,
        onDispose: onDispose)
    )
}

参考:

LOG 输出

我测试了一下,取消掉 super.tpbMakeConstraint()的注释,所有的view都能被加载,但是设备列表、scrollview、searchbar都叠到了一起,请仔细分析重新生成完整代码 import UIKit import SnapKit class DeviceListNewViewController: SurveillanceCommonTableController { // MARK: - 属性 private lazy var titleContainerView: UIView = { let view = UIView() view.backgroundColor = .red return view }() private lazy var titleLabel: UILabel = { let label = UILabel() label.text = "设备列表" label.font = .tpm20Medium() label.textColor = .tpbTextPrimary label.textAlignment = .center label.numberOfLines = 1 return label }() private lazy var searchBar: TPBSearchBar = { let bar = TPBSearchBar() bar.placeholder = "搜索" bar.backgroundColor = .clear bar.delegate = self return bar }() private lazy var searchContainerView: UIView = { let view = UIView() view.backgroundColor = UIColor(white: 0.96, alpha: 1.0) view.layer.cornerRadius = 22 view.clipsToBounds = true view.addSubview(searchBar) return view }() private lazy var tabScrollView: UIScrollView = { let scrollView = UIScrollView() scrollView.showsHorizontalScrollIndicator = false scrollView.backgroundColor = .clear scrollView.translatesAutoresizingMaskIntoConstraints = false return scrollView }() private lazy var tabButtons: [UIButton] = { return tabButtonTitles.enumerated().map { index, title in let btn = UIButton(type: .custom) btn.tag = index btn.setTitle(title, for: .normal) btn.titleLabel?.font = UIFont.tpr14Regular() btn.setTitleColor(.black, for: .normal) btn.setTitleColor(.tpbPrimary, for: .selected) btn.layer.borderWidth = 1 btn.layer.borderColor = UIColor(white: 0.85, alpha: 1.0).cgColor btn.layer.cornerRadius = 20 btn.contentEdgeInsets = UIEdgeInsets(top: 8, left: 16, bottom: 8, right: 16) btn.addTarget(self, action: #selector(onTabTapped(_:)), for: .touchUpInside) return btn } }() private let tabButtonTitles = ["所有设备", "收藏页面", "站点选择"] private var selectedTabIndex = 0 // MARK: - UICollectionView private var collectionView: UICollectionView! // MARK: - View Setup override func tpbSetupSubviews() { super.tpbSetupSubviews() setupNav() setupCollectionView() view.addSubviews([ titleContainerView, searchContainerView, tabScrollView, tableView ]) titleContainerView.addSubview(titleLabel) searchContainerView.addSubview(searchBar) updateTabSelection(index: selectedTabIndex) layoutTabButtonsInScrollView() } private func setupNav() { navigationItem.leftBarButtonItem = tpbCreateLeftBarButtonItem( with: TPImageLiteral("icon_back"), andTarget: self, andAction: #selector(onBack) ) navigationItem.rightBarButtonItem = tpbCreateRightBarButtonItem( with: TPImageLiteral("icon_settings"), andTarget: self, andAction: #selector(onSettings) ) navigationItem.title = "" } private func setupCollectionView() { let layout = UICollectionViewFlowLayout() layout.scrollDirection = .vertical layout.minimumLineSpacing = 10 layout.minimumInteritemSpacing = 10 layout.sectionInset = UIEdgeInsets(top: 10, left: 16, bottom: 10, right: 16) collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout) collectionView.backgroundColor = .tpbBackground collectionView.alwaysBounceVertical = true collectionView.layer.cornerRadius = 12 collectionView.clipsToBounds = true // 注册 cell(假设使用默认 UICollectionViewCell) collectionView.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "DeviceCell") } override func tpbMakeConstraint() { super.tpbMakeConstraint() titleContainerView.snp.makeConstraints { make in make.top.equalTo(view.safeAreaLayoutGuide).offset(8) make.leading.trailing.equalToSuperview().inset(16) make.height.equalTo(40) } titleLabel.snp.makeConstraints { make in make.center.equalToSuperview() make.leading.greaterThanOrEqualToSuperview().offset(20) make.trailing.lessThanOrEqualToSuperview().offset(-20) } searchContainerView.snp.makeConstraints { make in make.top.equalTo(titleContainerView.snp.bottom).offset(16) make.leading.trailing.equalToSuperview().inset(16) make.height.equalTo(44) } searchBar.snp.makeConstraints { make in make.edges.equalTo(searchContainerView).inset(UIEdgeInsets(top: 0, left: 16, bottom: 0, right: 16)) } tabScrollView.snp.makeConstraints { make in make.top.equalTo(searchContainerView.snp.bottom).offset(16) make.leading.trailing.equalToSuperview().inset(0) make.height.equalTo(40) } tableView.snp.remakeConstraints { make in make.top.equalTo(tabScrollView.snp.bottom) make.leading.trailing.equalToSuperview() make.bottom.equalTo(view.safeAreaLayoutGuide) } } // MARK: - 内联布局 Tab 按钮 private func layoutTabButtonsInScrollView() { tabScrollView.subviews.forEach { $0.removeFromSuperview() } var previousButton: UIButton? for button in tabButtons { tabScrollView.addSubview(button) button.snp.makeConstraints { make in make.centerY.equalToSuperview() make.height.equalTo(36) if let prev = previousButton { make.leading.equalTo(prev.snp.trailing).offset(8) } else { make.leading.equalTo(tabScrollView.contentLayoutGuide).offset(16) } make.width.greaterThanOrEqualTo(80) } previousButton = button } // 手动设置 contentSize DispatchQueue.main.async { var totalWidth: CGFloat = 16 for (i, btn) in self.tabButtons.enumerated() { totalWidth += btn.intrinsicContentSize.width + (i > 0 ? 8 : 0) } totalWidth += 16 self.tabScrollView.contentSize = CGSize(width: totalWidth, height: 40) } } // MARK: - 数据模型构建:现在把 UICollectionView 放入 cell private func reloadData() { var tempSectionArray = [TPBTableSectionModel]() // Section 0: 包含 titleView(已添加到主 view)、searchBar、tabScrollView let section0 = TPBTableSectionModel() var cellModels = [TPBBaseTableCellModel]() // Cell 1: Tab ScrollView(横向滚动按钮组) let tabCellModel = TPBBaseTableCellModel.customContent(with: tabScrollView) cellModels.append(tabCellModel) // Section 0 结束 section0.cellModelArray = cellModels tempSectionArray.append(section0) // Section 1: 真实的 UICollectionView let section1 = TPBTableSectionModel() let collectionCellModel = TPBBaseTableCellModel.customContent(with: collectionView) collectionCellModel.height = TPBTableElementHeight.customHeight(500) // 固定高度,内部可滚动 section1.cellModelArray = [collectionCellModel] tempSectionArray.append(section1) // 赋值并刷新 sectionArray = tempSectionArray tableView.reloadData() } // MARK: - 生命周期 override func viewDidLoad() { super.viewDidLoad() reloadData() // 绑定数据源(必须在 reloadData 后确保 collectionView 已加入视图层级) collectionView.dataSource = self collectionView.delegate = self } // MARK: - 点击事件 @objc private func onBack() { navigationController?.popViewController(animated: true) } @objc private func onSettings() { print("Settings tapped") } @objc private func onTabTapped(_ sender: UIButton) { guard sender.tag != selectedTabIndex else { return } tabButtons[selectedTabIndex].isSelected = false selectedTabIndex = sender.tag sender.isSelected = true print("Switched to tab: \(selectedTabIndex)") // TODO: 切换 tab 时刷新 collectionView 数据 } private func updateTabSelection(index: Int) { for (i, btn) in tabButtons.enumerated() { btn.isSelected = (i == index) } } } // MARK: - UICollectionViewDataSource extension DeviceListNewViewController: UICollectionViewDataSource { func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { return 20 // 模拟数据 } func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "DeviceCell", for: indexPath) cell.backgroundColor = .systemBlue return cell } } // MARK: - UICollectionViewDelegateFlowLayout extension DeviceListNewViewController: UICollectionViewDelegateFlowLayout { func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { let width = (collectionView.bounds.width - 32 - 10) / 2 // 两列,间距10 return CGSize(width: width, height: 80) } } // MARK: - TPBSearchBarDelegate extension DeviceListNewViewController: TPBSearchBarDelegate { func searchBar(_ searchBar: TPBSearchBar, textDidChange searchText: String) { // 可在此触发搜索过滤逻辑 } func searchBarTextDidBeginEditing(_ searchBar: TPBSearchBar) { addTapToDismissKeyboard() } func searchBarTextDidEndEditing(_ searchBar: TPBSearchBar) { removeTapToDismissKeyboard() } func searchBarSearchButtonClicked(_ searchBar: TPBSearchBar) { searchBar.resignFirstResponder() } } // MARK: - Keyboard Dismiss Gesture private extension DeviceListNewViewController { func addTapToDismissKeyboard() { let tap = UITapGestureRecognizer(target: self, action: #selector(dismissKeyboard)) tap.cancelsTouchesInView = false view.addGestureRecognizer(tap) objc_setAssociatedObject( self, &AssociatedKeys.searchBarTapGestureKey, tap, .OBJC_ASSOCIATION_RETAIN_NONATOMIC ) } func removeTapToDismissKeyboard() { guard let tap = objc_getAssociatedObject(self, &AssociatedKeys.searchBarTapGestureKey) as? UITapGestureRecognizer else { return } view.removeGestureRecognizer(tap) objc_setAssociatedObject(self, &AssociatedKeys.searchBarTapGestureKey, nil, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) } @objc func dismissKeyboard() { searchBar.resignFirstResponder() } } // MARK: - Associated Object Keys private struct AssociatedKeys { static var searchBarTapGestureKey: UInt8 = 0 } 同时我再发给你另一个同组件库的代码参考:import UIKit class AddOrganizationCheckDetailViewController: SurveillanceCommonTableController { // MARK: - 属性 private lazy var segmentControl: TPBSegmentedControl = { let segment = TPBSegmentedControl(segmentedStyle: .roundRect, itemArray: [LocalizedString(key: addOrganizationEssentialOrganization),LocalizedString(key: addOrganizationStandardOrganization)], initialIndex: 0) segment.indexDidChangeCallback = { [weak self] _ in self?.reloadView() } return segment }() private lazy var checkDetailView: AddOrganizationCheckDetailView = { let view = AddOrganizationCheckDetailView() view.updateWith(orgCategory: .essential) return view }() convenience init(orgCategory: TPSSVMSOrgCategory) { self.init() if orgCategory == .essential { self.segmentControl.selectedIndex = 0 } else { self.segmentControl.selectedIndex = 1 } } deinit { print("AddOrganizationCheckDetailViewController deinit") } // MARK: - View override func tpbSetupSubviews() { super.tpbSetupSubviews() setupNav() view.addSubview(segmentControl) } private func setupNav() { navigationItem.leftBarButtonItem = nil navigationItem.rightBarButtonItem = tpbCreateRightBarButtonItem(with: TPImageLiteral("common_close"), andTarget: self, andAction: #selector(clickBack)) navigationItem.title = LocalizedString(key: addOrganizationSelectOrgDetail) } override func tpbMakeConstraint() { // 暂不执行super不然会显示不了segment // super.tpbMakeConstraint() segmentControl.snp.makeConstraints { make in make.top.equalTo(view.safeAreaLayoutGuide).offset(8) make.leading.equalTo(view.safeAreaLayoutGuide).offset(16) make.trailing.equalTo(view.safeAreaLayoutGuide).offset(-16) make.height.equalTo(32) } tableView.snp.remakeConstraints { make in make.top.equalTo(segmentControl.snp.bottom) make.leading.trailing.equalTo(view.safeAreaLayoutGuide) make.bottom.equalTo(view) } } override func viewDidLoad() { super.viewDidLoad() reloadView() } private func reloadView() { reloadData() } // MARK: - dateModel private func reloadData() { var tempSectionArray = [TPBTableSectionModel]() // section0 let section0 = TPBTableSectionModel() var section0CellModelArray = [TPBBaseTableCellModel]() if segmentControl.selectedIndex == 0 { checkDetailView.updateWith(orgCategory: .essential) } else { checkDetailView.updateWith(orgCategory: .standard) } let detailCellModel = TPBBaseTableCellModel.customContent(with: checkDetailView) section0CellModelArray.append(detailCellModel) section0.cellModelArray = section0CellModelArray tempSectionArray.append(section0) sectionArray = tempSectionArray } // MARK: - 点击事件 @objc private func clickBack() { dismiss(animated: true) } } // 自定义view fileprivate class AddOrganizationCheckDetailLabel: TPBBaseView { // MARK: - 属性 private lazy var dotImageView: UIImageView = { let view = UIImageView(image: TPImageLiteral("thirdParty_dot_gray")) view.contentMode = .scaleAspectFit return view }() private lazy var titleLabel: UILabel = { let label = UILabel() label.numberOfLines = 0 label.font = .tpr14Regular() label.textColor = .tpbTextSecondaryContent label.textAlignment = .left label.lineBreakMode = .byWordWrapping return label }() // MARK: - View override func setupSubviews() { super.setupSubviews() backgroundColor = .clear addSubviews([dotImageView, titleLabel]) } override func makeConstraint() { super.makeConstraint() dotImageView.snp.makeConstraints { make in make.leading.equalToSuperview() make.top.equalToSuperview().offset(4) make.height.width.equalTo(8) } titleLabel.snp.makeConstraints { make in make.leading.equalTo(dotImageView.snp.trailing).offset(8) make.top.trailing.bottom.equalToSuperview() } } // MARK: - 更新函数 func updateWith(orgCategory: TPSSVMSOrgCategory, title: String) { if orgCategory == .essential { dotImageView.image = TPImageLiteral("thirdParty_dot_gray") } else { dotImageView.image = TPImageLiteral("number_diot") } titleLabel.text = title } } fileprivate class AddOrganizationCheckDetailView: TPBBaseView { // MARK: - 属性 private lazy var containerView: UIView = { let view = UIView() view.backgroundColor = .tpbCard view.layer.cornerRadius = 10 view.layer.masksToBounds = true return view }() private lazy var gradientLayer: CAGradientLayer = { // 加入底色 let layer = CAGradientLayer() layer.frame = CGRectMake(containerView.bounds.minX, containerView.bounds.minY, containerView.bounds.size.width, 112) layer.startPoint = CGPoint(x: 0, y: 0) layer.endPoint = CGPoint(x: 0, y: 1) layer.colors = [UIColor.tpbGreenLight.cgColor, UIColor.clear.cgColor] layer.isHidden = true return layer }() private lazy var rightLabelContainerView: UIView = { let view = UIView() view.backgroundColor = .tpbBlueLight view.layer.cornerRadius = 3 view.layer.maskedCorners = [.layerMinXMaxYCorner] return view }() private lazy var rightLabel: UILabel = { let label = UILabel() label.text = LocalizedString(key: addOrganizationSelectOrgFree) label.numberOfLines = 1 label.font = .tpr14Regular() label.textColor = .tpbBlue label.textAlignment = .left label.lineBreakMode = .byWordWrapping return label }() private lazy var titleLabel: UILabel = { let label = UILabel() label.numberOfLines = 0 label.font = .tpm20Medium() label.textColor = .tpbTextPrimary label.textAlignment = .center label.lineBreakMode = .byWordWrapping return label }() private lazy var subTitleLabel: UILabel = { let label = UILabel() label.text = LocalizedString(key: addOrganizationSelectOrgLicenseNeeded) label.numberOfLines = 0 label.font = .tpr16Regular() label.textColor = .tpbTextPrimary label.textAlignment = .center label.lineBreakMode = .byWordWrapping return label }() private lazy var networkImageView: UIImageView = { let view = UIImageView(image: TPImageLiteral("central_network_dis")) view.contentMode = .scaleAspectFit return view }() private lazy var networkLabel: UILabel = { let label = UILabel() label.text = LocalizedString(key: addOrganizationOmadaNetwork) label.numberOfLines = 0 label.font = .tpm16Medium() label.textColor = .tpbTextPrimary label.textAlignment = .left label.lineBreakMode = .byWordWrapping return label }() private lazy var guardImageView: UIImageView = { let view = UIImageView(image: TPImageLiteral("central_surveillance_dis")) view.contentMode = .scaleAspectFit return view }() private lazy var guardLabel: UILabel = { let label = UILabel() label.text = LocalizedString(key: shareSocialPlatformWebDetail) label.numberOfLines = 0 label.font = .tpm16Medium() label.textColor = .tpbTextPrimary label.textAlignment = .left label.lineBreakMode = .byWordWrapping return label }() private lazy var essentialPart1LabelList: [AddOrganizationCheckDetailLabel] = { var list = [AddOrganizationCheckDetailLabel]() for str in [LocalizedString(key: addOrganizationSelectOrgDetailPart1_Tip1), LocalizedString(key: addOrganizationSelectOrgDetailPart1_Tip2)] { let view = AddOrganizationCheckDetailLabel() view.updateWith(orgCategory: .essential, title: str) list.append(view) } return list }() private lazy var essentialPart2LabelList: [AddOrganizationCheckDetailLabel] = { var list = [AddOrganizationCheckDetailLabel]() for str in [LocalizedString(key: addOrganizationSelectOrgDetailNetwork_Essential_Tip1), LocalizedString(key: addOrganizationSelectOrgDetailNetwork_Essential_Tip2), LocalizedString(key: addOrganizationSelectOrgDetailNetwork_Essential_Tip3), LocalizedString(key: addOrganizationSelectOrgDetailNetwork_Essential_Tip4), LocalizedString(key: addOrganizationSelectOrgDetailNetwork_Essential_Tip5)] { let view = AddOrganizationCheckDetailLabel() view.updateWith(orgCategory: .essential, title: str) list.append(view) } return list }() private lazy var essentialPart3LabelList: [AddOrganizationCheckDetailLabel] = { var list = [AddOrganizationCheckDetailLabel]() for str in [LocalizedString(key: addOrganizationSelectOrgDetailGuard_Essential_Tip1), LocalizedString(key: addOrganizationSelectOrgDetailGuard_Essential_Tip2), LocalizedString(key: addOrganizationSelectOrgDetailGuard_Essential_Tip3), LocalizedString(key: addOrganizationSelectOrgDetailGuard_Essential_Tip4), LocalizedString(key: addOrganizationSelectOrgDetailGuard_Essential_Tip5), LocalizedString(key: addOrganizationSelectOrgDetailGuard_Essential_Tip6), LocalizedString(key: addOrganizationSelectOrgDetailGuard_Essential_Tip7)] { let view = AddOrganizationCheckDetailLabel() view.updateWith(orgCategory: .essential, title: str) list.append(view) } return list }() private lazy var standardPart1LabelList: [AddOrganizationCheckDetailLabel] = { var list = [AddOrganizationCheckDetailLabel]() for str in [LocalizedString(key: addOrganizationSelectOrgDetailPart1_Tip1), LocalizedString(key: addOrganizationSelectOrgDetailPart1_Tip2)] { let view = AddOrganizationCheckDetailLabel() view.updateWith(orgCategory: .standard, title: str) list.append(view) } return list }() private lazy var standardPart2LabelList: [AddOrganizationCheckDetailLabel] = { var list = [AddOrganizationCheckDetailLabel]() for str in [LocalizedString(key: addOrganizationSelectOrgDetailNetwork_Standard_Tip1), LocalizedString(key: addOrganizationSelectOrgDetailNetwork_Standard_Tip2), LocalizedString(key: addOrganizationSelectOrgDetailNetwork_Standard_Tip3), LocalizedString(key: addOrganizationSelectOrgDetailNetwork_Standard_Tip4), LocalizedString(key: addOrganizationSelectOrgDetailNetwork_Standard_Tip5)] { let view = AddOrganizationCheckDetailLabel() view.updateWith(orgCategory: .standard, title: str) list.append(view) } return list }() private lazy var standardPart3LabelList: [AddOrganizationCheckDetailLabel] = { var list = [AddOrganizationCheckDetailLabel]() for str in [LocalizedString(key: addOrganizationSelectOrgDetailGuard_Standard_Tip1), LocalizedString(key: addOrganizationSelectOrgDetailGuard_Standard_Tip2), LocalizedString(key: addOrganizationSelectOrgDetailGuard_Standard_Tip3)] { let view = AddOrganizationCheckDetailLabel() view.updateWith(orgCategory: .standard, title: str) list.append(view) } return list }() private lazy var part1StackView: UIStackView = { let view = UIStackView() view.axis = .vertical view.alignment = .leading view.spacing = 12 view.distribution = .equalSpacing return view }() private lazy var part2StackView: UIStackView = { let view = UIStackView() view.axis = .vertical view.alignment = .leading view.spacing = 12 view.distribution = .equalSpacing return view }() private lazy var part3StackView: UIStackView = { let view = UIStackView() view.axis = .vertical view.alignment = .leading view.spacing = 12 view.distribution = .equalSpacing return view }() // MARK: - View override func setupSubviews() { super.setupSubviews() addSubview(containerView) containerView.addSubviews([rightLabelContainerView, titleLabel, subTitleLabel, networkImageView, networkLabel, guardImageView, guardLabel, part1StackView, part2StackView, part3StackView]) rightLabelContainerView.addSubview(rightLabel) containerView.layer.addSublayer(gradientLayer) } override func makeConstraint() { super.makeConstraint() containerView.snp.remakeConstraints { make in make.edges.equalToSuperview() } rightLabelContainerView.snp.remakeConstraints { make in make.trailing.top.equalToSuperview() } rightLabel.snp.remakeConstraints { make in make.leading.equalToSuperview().offset(13) make.trailing.equalToSuperview().offset(-13) make.top.equalToSuperview().offset(2) make.bottom.equalToSuperview().offset(-2) } titleLabel.snp.remakeConstraints { make in make.leading.equalToSuperview().offset(16) make.trailing.equalToSuperview().offset(-16) make.top.equalToSuperview().offset(44) } subTitleLabel.snp.remakeConstraints { make in make.leading.trailing.equalTo(titleLabel) make.top.equalTo(titleLabel.snp.bottom).offset(8) } part1StackView.snp.remakeConstraints { make in make.leading.trailing.equalTo(titleLabel) if subTitleLabel.isHidden { make.top.equalTo(titleLabel.snp.bottom).offset(24) } else { make.top.equalTo(subTitleLabel.snp.bottom).offset(24) } } networkImageView.snp.remakeConstraints { make in make.leading.equalTo(titleLabel) make.centerY.equalTo(networkLabel) make.height.width.equalTo(18) } networkLabel.snp.remakeConstraints { make in make.leading.equalTo(networkImageView.snp.trailing).offset(8) make.trailing.equalTo(titleLabel) make.top.equalTo(part1StackView.snp.bottom).offset(24) } part2StackView.snp.remakeConstraints { make in make.leading.trailing.equalTo(titleLabel) make.top.equalTo(networkLabel.snp.bottom).offset(16) } guardImageView.snp.remakeConstraints { make in make.leading.equalTo(titleLabel) make.centerY.equalTo(guardLabel) make.height.width.equalTo(18) } guardLabel.snp.remakeConstraints { make in make.leading.equalTo(guardImageView.snp.trailing).offset(8) make.trailing.equalTo(titleLabel) make.top.equalTo(part2StackView.snp.bottom).offset(24) } part3StackView.snp.remakeConstraints { make in make.leading.trailing.equalTo(titleLabel) make.top.equalTo(guardLabel.snp.bottom).offset(16) make.bottom.equalToSuperview().offset(-24) } } // MARK: - 更新函数 func updateWith(orgCategory: TPSSVMSOrgCategory) { if orgCategory == .essential { gradientLayer.isHidden = true rightLabel.text = LocalizedString(key: addOrganizationSelectOrgFree) rightLabel.textColor = .tpbBlue rightLabelContainerView.backgroundColor = .tpbBlueLight titleLabel.text = LocalizedString(key: orgCategoryEssentials) subTitleLabel.isHidden = true networkImageView.image = TPImageLiteral("central_network_dis") guardImageView.image = TPImageLiteral("central_surveillance_dis") } else { gradientLayer.isHidden = false rightLabel.text = LocalizedString(key: addOrganizationSelectOrgLicense) rightLabel.textColor = .tpbTextWhite rightLabelContainerView.backgroundColor = .tpbPrimary titleLabel.text = LocalizedString(key: deviceSettingSmartWhiteLampModeAutoWTL) subTitleLabel.isHidden = false networkImageView.image = TPImageLiteral("central_network") guardImageView.image = TPImageLiteral("central_surveillance") } configStackView(orgCategory: orgCategory) makeConstraint() } override func layoutSubviews() { super.layoutSubviews() gradientLayer.frame = CGRectMake(containerView.bounds.minX, containerView.bounds.minY, containerView.bounds.size.width, 112) } private func configStackView(orgCategory: TPSSVMSOrgCategory) { for view in essentialPart1LabelList { view.removeFromSuperview() } for view in essentialPart2LabelList { view.removeFromSuperview() } for view in essentialPart3LabelList { view.removeFromSuperview() } for view in standardPart1LabelList { view.removeFromSuperview() } for view in standardPart2LabelList { view.removeFromSuperview() } for view in standardPart3LabelList { view.removeFromSuperview() } if orgCategory == .essential { for view in essentialPart1LabelList { part1StackView.addArrangedSubview(view) } for view in essentialPart2LabelList { part2StackView.addArrangedSubview(view) } for view in essentialPart3LabelList { part3StackView.addArrangedSubview(view) } } else { for view in standardPart1LabelList { part1StackView.addArrangedSubview(view) } for view in standardPart2LabelList { part2StackView.addArrangedSubview(view) } for view in standardPart3LabelList { part3StackView.addArrangedSubview(view) } } } }
12-02
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值