Solar自定义Filter

本文介绍如何在Solar框架中自定义Filter组件,特别是针对手机号验证的Filter实现过程。

Solar自定义Filter

Solar Filter组织形式

我们就validateWord来说明Solar的Filter的组织形式,与其相关的文件有:

其中/Solar/Filter.php 是所有Filter的入口类,通过实例化Solar_Filter来执行相应的过滤器(比如validateWord)。

/Solar/Filter/Abstract.php 是一个抽象类,所有的过滤器都继承自它。

/Solar/Filter/ValidateWord.php 继承自Solar_Filter_Abstract

自定义Filter validateMobile

假设你建了一个Vendor为Admin,那么在/Admin下有一个文件Filter.php,该文件构造了一个空类,源码为:

光有这个类是没有用的,我们可以根据Solar的Filter的组织结构来构造属于自己的Filter。好的,我们创建Filter文件夹,在/Admin/Filter下有如下文件:

/Admin/Filter/Abstract.php 源码如下:

这个类只是简单的继承Solar_Filter_Abstract而已,现在我们要做的只有这些。

/Admin/Filter/ValidateMobile.php 源码如下:

我们还添加了Locale String本地化字符串,当验证不成功时,在这里得到错误信息,而不是简单的输出INVALID_MOBILE , en_US.php源码如下:

好的,我们已经成功了自定义了validateMobile的过滤器,so just enjoy it!

// // MessageCenterMainCell.swift // SurveillanceHome // // Created by duxuying on 2025/9/26. // Copyright © 2025 tplink. All rights reserved. // import Foundation import SnapKit class MessageCenterMainCell: TPBBaseTableViewCell { private lazy var messageIcon: UIImageView = { let view = UIImageView() view.image = TPImageLiteral("") return view }() private lazy var badgeView: UIView = { let view = UIView() view.backgroundColor = .clear return view }() private lazy var badgeImageView: UIImageView = { let imageView = UIImageView() imageView.image = TPImageLiteral("messageManager_notification_Single") return imageView }() private lazy var badgeNumberLabel: UILabel = { let label = UILabel() label.text = "" label.font = UIFont.tpr10Regular() label.textColor = .white label.numberOfLines = 1 label.lineBreakMode = .byTruncatingTail return label }() private lazy var titleLabel: UILabel = { let label = UILabel() label.text = "" label.font = UIFont.tpr17Regular() label.textColor = UIColor.tpbTextPrimary label.numberOfLines = 1 label.lineBreakMode = .byTruncatingTail return label }() private lazy var detailLabel: UILabel = { let label = UILabel() label.text = "" label.font = UIFont.tpr14Regular() label.textColor = UIColor.tpbTextSecondaryContent label.numberOfLines = 1 label.lineBreakMode = .byTruncatingTail return label }() private lazy var messageTimeLabel: UILabel = { let label = UILabel() label.text = "" label.font = UIFont.tpr12Regular() label.textColor = UIColor.tpbTextSecondaryContent label.numberOfLines = 1 label.lineBreakMode = .byTruncatingTail return label }() private lazy var unreadIconImageView: UIImageView = { let imageView = UIImageView() imageView.image = TPImageLiteral("messageManager_notification_not show") return imageView }() private lazy var indicatorView: UIImageView = { let view = UIImageView() view.image = TPImageLiteral("messageManager_nextList_nor") return view }() private var badgeImageWidthConstraint: Constraint? func hidePointImage() { if !unreadIconImageView.isHidden { unreadIconImageView.isHidden = true } // if !badgeView.isHidden { // badgeView.isHidden = true // } } override func setupSubviews() { super.setupSubviews() self.contentView.addSubviews([messageIcon, badgeView, titleLabel, detailLabel, messageTimeLabel, indicatorView, unreadIconImageView]) badgeView.addSubviews([badgeImageView, badgeNumberLabel]) contentView.backgroundColor = UIColor.tpbCard self.backgroundColor = .clear self.layer.backgroundColor = UIColor.clear.cgColor TPUIUtils.setCornerFor(contentView, corner: .allCorners, radius: kBorderRadius) badgeView.isHidden = true let selectedView = UIView() selectedView.backgroundColor = UIColor.clear self.selectedBackgroundView = selectedView badgeView.isHidden = true } override func makeConstraint() { super.makeConstraint() messageIcon.snp.remakeConstraints({ make in make.height.width.equalTo(28) make.centerY.equalToSuperview() make.leading.equalToSuperview().offset(22) make.top.equalToSuperview().offset(22) }) unreadIconImageView.snp.remakeConstraints({ make in make.bottom.equalTo(messageIcon).offset(2) make.trailing.equalTo(messageIcon).offset(2) make.height.width.equalTo(10) }) badgeView.snp.remakeConstraints({ make in make.leading.equalTo(messageIcon).offset(19) make.top.equalTo(messageIcon).offset(19) make.height.equalTo(14) make.width.equalTo(24) }) badgeImageView.snp.remakeConstraints({ make in make.leading.equalToSuperview() make.centerY.top.equalToSuperview() make.height.equalTo(20) badgeImageWidthConstraint = make.width.equalTo(24).constraint }) badgeImageWidthConstraint?.isActive = true badgeNumberLabel.snp.makeConstraints { make in make.centerY.equalToSuperview() make.leading.equalToSuperview().offset(4) } indicatorView.snp.makeConstraints { make in make.top.equalToSuperview().offset(12) make.trailing.equalToSuperview().offset(-12) } messageTimeLabel.snp.makeConstraints { make in make.centerY.equalTo(indicatorView) make.trailing.equalTo(indicatorView.snp.leading).offset(-4) } titleLabel.snp.makeConstraints { make in make.centerY.equalTo(indicatorView) make.leading.equalTo(messageIcon.snp.trailing).offset(16) make.trailing.lessThanOrEqualTo(messageTimeLabel.snp.leading).offset(-8) } detailLabel.snp.makeConstraints { make in make.leading.equalTo(titleLabel) make.top.equalTo(titleLabel.snp.bottom).offset(6) make.trailing.lessThanOrEqualToSuperview().offset(-16) } } private var unreadNumber = 0 { didSet { badgeView.isHidden = true if unreadNumber <= 0 { unreadIconImageView.isHidden = true } else { unreadIconImageView.isHidden = false } // if unreadNumber <= 0 { // badgeView.isHidden = true // badgeImageWidthConstraint?.update(offset: 0) // } else if (unreadNumber > 0 && unreadNumber <= 9) { // badgeView.isHidden = false // badgeImageView.image = TPImageLiteral("messageManager_notification_Single").render(tintColor: .tpbRed) // badgeImageWidthConstraint?.update(offset: 14) // badgeNumberLabel.text = String(unreadNumber) // } else if (unreadNumber > 9 && unreadNumber <= 99) { // badgeView.isHidden = false // badgeImageView.image = TPImageLiteral("messageManager_notification_Ten").render(tintColor: .tpbRed) // badgeImageWidthConstraint?.update(offset: 21) // badgeNumberLabel.text = String(unreadNumber) // } else { // badgeView.isHidden = false // badgeImageView.image = TPImageLiteral("messageManager_notification_Hundred").render(tintColor: .tpbRed) // badgeImageWidthConstraint?.update(offset: 25) // badgeNumberLabel.text = "99+" // } self.layoutIfNeeded() } } func setCellBy(messageType: TPSSMessageOverType, message: TPSSMessage?, unreadUnm: Int){ if let tMessage = message { unreadNumber = 0 self.unreadNumber = unreadUnm if TPSSAppContext.shared.isCloudVMSLogin { let eventDate = Date.init(timeIntervalSince1970: TimeInterval(tMessage.creatTime/1000))//毫秒转秒再转日期 let destinationDateNow: Date = Date.init(timeInterval: TimeInterval(MessageManagerPublic.getTimeZoneDifferenceInterval()), since: eventDate) let formatter = DateFormatter.standard formatter.setLocalizedDateFormatFromTemplate(MessageManagerPublic.messageDetailDateFormat) let latestLocalTime = formatter.string(from: destinationDateNow) messageTimeLabel.text = MessageManagerPublic.getTimeString(TimeInterval(tMessage.creatTime), latestLocalTime, isNewList: true) } else { var eventDate = NSDate(timeIntervalSince1970: Double(tMessage.devTimeInSecond)) eventDate = NSDate(timeInterval: MessageManagerPublic.getTimeZoneDifferenceInterval(), since: eventDate as Date) let formatter = DateFormatter.standard formatter.dateFormat = MessageManagerPublic.messageDetailDateFormat let latestLocalTime = formatter.string(from: eventDate as Date) messageTimeLabel.text = MessageManagerPublic.getTimeString(Double(tMessage.devTimeInSecond), latestLocalTime, isNewList: true) } var eventName = "" var deviceName = "" if TPSSAppContext.shared.isVmsLogin { eventName = TPSSMessageManager.getVmsMessageName(by: tMessage) if tMessage.channelID < 0 { //IPC不展示channel deviceName = tMessage.eventAlias } else { deviceName = String(format: "%@ %@-%@", tMessage.parentName, String(format: LocalizedString(key: deviceListChannelWithoutName), tMessage.channelID + 1), tMessage.eventAlias) } } detailLabel.text = String(format: "[%@] %@", eventName, deviceName) if messageType == .event { titleLabel.text = LocalizedString(key: settingConfig_SectionContents_warningInform_title) messageIcon.image = TPImageLiteral("messageCenterEventMessageImg") } else if messageType == .status { if message?.deviceType == .NVR { messageIcon.image = TPImageLiteral("message_filter_nvr") } else if message?.deviceType == .solar { messageIcon.image = TPImageLiteral("message_filter_solar") } else { messageIcon.image = TPImageLiteral("message_filter_ipc") } titleLabel.text = LocalizedString(key: solar_DeviceList_Device_Status) } else { titleLabel.text = LocalizedString(key: messageManagerSettingConfig_SectionContents_systemSetting_title) messageIcon.image = TPImageLiteral("messageCenterSystemMessageImg") } } else { //空cell badgeView.isHidden = true unreadIconImageView.isHidden = true indicatorView.isHidden = false messageTimeLabel.text = "" if messageType == .event { titleLabel.text = LocalizedString(key: settingConfig_SectionContents_warningInform_title) messageIcon.image = TPImageLiteral("messageCenterEventMessageImg") } else if messageType == .status { titleLabel.text = LocalizedString(key: solar_DeviceList_Device_Status) messageIcon.image = TPImageLiteral("messageCenterStatusMessageImg") } else { titleLabel.text = LocalizedString(key: messageManagerSettingConfig_SectionContents_systemSetting_title) messageIcon.image = TPImageLiteral("messageCenterSystemMessageImg") } detailLabel.text = LocalizedString(key: deviceListNVRManagerVCArmingNoLog) } } }
最新发布
11-06
感谢你提供了完整的 `MessageCenterMainCell` 代码。经过仔细分析,**问题的根本原因已经找到了!** --- ## ✅ 核心问题:你设置了 `selectedBackgroundView`,但背景是 `.clear` 在你的 `setupSubviews()` 方法中有这样一段代码: ```swift let selectedView = UIView() selectedView.backgroundColor = UIColor.clear // ⚠️ 这里是透明色! self.selectedBackgroundView = selectedView ``` ### ❌ 错误解释: - 虽然你设置了 `selectedBackgroundView`,但它的背景颜色是 **透明的(`.clear`)** - 即使 cell 被选中了,系统也会显示这个“透明背景”,所以你看不到任何变化 - 这相当于:**有高亮逻辑,但视觉上完全不可见** > 🛑 这就是为什么你点击 cell 没有任何反应的原因 —— 实际上它已经被选中了,只是你看不见! --- ## ✅ 解决方案:将 `selectedBackgroundView` 的背景改为灰色或其他颜色 ### ✅ 修改方式如下: ```swift // 在 setupSubviews() 中修改这一段: let selectedView = UIView() selectedView.backgroundColor = UIColor.systemGray4.withAlphaComponent(0.1) // ✅ 浅灰色高亮 self.selectedBackgroundView = selectedView ``` 或者使用 iOS 默认的灰色高亮样式(更简单): ```swift override func setupSubviews() { super.setupSubviews() // ... 其他代码保持不变 ... // ✅ 删除你自己创建的 clear 背景 view // let selectedView = UIView() // selectedView.backgroundColor = UIColor.clear // self.selectedBackgroundView = selectedView // ✅ 改为使用系统默认高亮样式 self.selectionStyle = .gray // 会自动使用浅灰背景 } ``` --- ## 🔁 推荐最终修复方案(二选一) ### ✅ 方案一:使用系统 `.gray` 高亮(推荐初学者) 只需删除那几行设置透明背景的代码,并启用 `selectionStyle`: ```swift override func setupSubviews() { super.setupSubviews() self.contentView.addSubviews([messageIcon, badgeView, titleLabel, detailLabel, messageTimeLabel, indicatorView, unreadIconImageView]) badgeView.addSubviews([badgeImageView, badgeNumberLabel]) contentView.backgroundColor = UIColor.tpbCard self.backgroundColor = .clear self.layer.backgroundColor = UIColor.clear.cgColor TPUIUtils.setCornerFor(contentView, corner: .allCorners, radius: kBorderRadius) badgeView.isHidden = true // 🔥 删除以下三行 ❌ // let selectedView = UIView() // selectedView.backgroundColor = UIColor.clear // self.selectedBackgroundView = selectedView // ✅ 添加这行 👇 让系统提供灰色高亮 self.selectionStyle = .gray } ``` 然后确保在 `cellForRowAt` 中不要再设置 `.none`。 --- ### ✅ 方案二:自定义选中背景(更灵活美观) 如果你想控制颜色和圆角等细节: ```swift override func setupSubviews() { super.setupSubviews() // ... 原有 addSubview 等操作 ... contentView.backgroundColor = UIColor.tpbCard self.backgroundColor = .clear TPUIUtils.setCornerFor(contentView, corner: .allCorners, radius: kBorderRadius) // ✅ 自定义选中背景(带圆角适配) let selectedBG = UIView() selectedBG.backgroundColor = UIColor.systemGray4.withAlphaComponent(0.1) // 如果你需要圆角也高亮生效,可以这样设置: selectedBG.layer.cornerRadius = kBorderRadius selectedBG.layer.masksToBounds = true self.selectedBackgroundView = selectedBG badgeView.isHidden = true } ``` > 💡 注意:`selectedBackgroundView` 是插入到 cell 内容底层的一个 view,它不会影响布局。 --- ## 🧪 补充建议:测试是否真的被选中 在 `didSelectRowAt` 加日志验证: ```swift func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { print("✅ Selected: \(indexPath)") if let cell = tableView.cellForRow(at: indexPath) { print("👉 isSelected: \(cell.isSelected)") // 应该为 true print("👉 selectionStyle: \(cell.selectionStyle)") } // 暂时注释跳转逻辑,先看高亮效果 // navigationController?.pushViewController(...) } ``` 如果你看到 `isSelected = true` 但没视觉变化 → 就说明是背景颜色问题(你现在的情况正是如此) --- ## ✅ 最终总结 | 问题 | 原因 | 解决方法 | |------|------|---------| | 点击 cell 没有高亮反馈 | `selectedBackgroundView` 背景色为 `.clear` | 改成灰色或使用 `selectionStyle = .gray` | | 自定义 cell 忽略选中状态 | 手动覆盖了 `selectedBackgroundView` | 删除错误设置或正确配置颜色 | --- ## ✅ 你现在应该做的 1. 打开 `MessageCenterMainCell.swift` 2. 找到这段代码: ```swift let selectedView = UIView() selectedView.backgroundColor = UIColor.clear self.selectedBackgroundView = selectedView ``` 3. **删除这三行** 4. 添加: ```swift self.selectionStyle = .gray ``` 5. 回到 `cellForRowAt`,确认没有再设置 `cell.selectionStyle = .none` ✅ 运行 → 点击 cell → 应该能看到明显的灰色高亮并持续保留! --- ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值