SwiftyPickerPopover 避坑指南:iOS 9 兼容、循环引用等 6 大常见问题全解析
SwiftyPickerPopover 避坑指南iOS 9 兼容、循环引用等 6 大常见问题全解析【免费下载链接】SwiftyPickerPopoverA more convenient way to display a popover with a built-in picker, on iPhone/iPad of iOS9.项目地址: https://gitcode.com/gh_mirrors/sw/SwiftyPickerPopoverSwiftyPickerPopover 是一款能在 iPhone / iPadiOS 9上以弹窗形式展示内置选择器的开源 Swift 库几行代码即可弹出字符串选择器、日期选择器、倒计时选择器和多列选择器。然而很多新手在接入 SwiftyPickerPopover 时都会遇到循环引用导致的内存泄漏、iOS 9 上按钮消失、选择器行号错位等隐形坑。本文结合源码逐一拆解 6 大高频问题及解决方案帮你彻底避坑、快速上手。一、循环引用闭包捕获导致的隐性内存泄漏问题表现使用 SwiftyPickerPopover 后页面退出却迟迟不释放deinit 不打印内存持续上涨。根因分析查看 AbstractPopover.swift 可以发现baseViewController与contentViewController虽然都声明为weak但 ViewController 内部如StringPickerPopoverViewController会强持有anyPopover。当你在属性中保存 popover 实例又在setDoneButton(action:)或setValueChange(action:)闭包里捕获了self页面控制器时就会形成控制器 → popover → 闭包 → 控制器的循环引用。快速解决方案闭包内使用[weak self]如setDoneButton(action: { [weak self] popover, row, value in ... })popover 尽量作为局部变量使用不要长期保存在属性中弹出结束后调用disappear()并及时释放引用。二、iOS 9 / iOS 10 兼容导航栏按钮神秘消失问题表现在 iOS 9、iOS 10 真机上弹窗顶部的 Cancel / Done 按钮消失或错位而 iOS 11 正常。根因分析在 StringPickerPopoverViewController.swift 和 DatePickerPopoverViewController.swift 中都有这样的逻辑if #available(iOS 11.0, *) { } else { navigationItem.leftBarButtonItem nil; navigationItem.rightBarButtonItem nil }低版本系统必须清空后重新设置按钮才能正确显示。快速解决方案务必在 iOS 9/10 模拟器或真机上回归测试弹窗按钮若按钮缺失检查是否自定义了 Storyboard 覆盖见第六点不要用 iOS 11 的UIBarButtonItem新 API 去修改弹窗内部按钮。另外该库在 AbstractPickerPopoverViewController.swift 中通过adaptivePresentationStyle返回.none让 iPhone 上也能保持真正的弹窗形态而不是被系统改成全屏这一行为在低版本上同样需要验证。三、setClearButton 会偷偷修改 choices行号整体错位问题表现调用setClearButton后setSelectedRow(0)选中的不是你以为的第一项点击完成拿到的值也对不上。根因分析这是最容易被忽略的坑查看 StringPickerPopover.swift 的setClearButton实现如果choices.first不是空字符串它会在数组第 0 位自动插入一个空字符串用于表示已清除状态。同理ColumnStringPickerPopover的setClearButton会在每一列都插入空串所有原始索引全部 1。快速解决方案先调用setClearButton再调用setSelectedRow保证索引计算正确或者干脆在构造choices时手动把空字符串放在第 0 位注意当选中值正好是空串时Clear 按钮会处于禁用状态见enableClearButtonIfNeeded逻辑。四、setMinuteInterval 在 .date 模式下不生效问题表现给日期选择器设置了setMinuteInterval(5)但滚轮上分钟仍然是 1 分钟一档。根因分析看 DatePickerPopoverViewController.swift 的刷新逻辑只有这一行条件if picker.datePickerMode ! .date { picker.minuteInterval popover.minuteInterval }。也就是说分钟间隔只在.time或.countDownTimer模式下才会被应用.date年月日模式直接忽略该设置。快速解决方案设置setDateMode(.time)或.countDownTimer后再配合setMinuteInterval使用同时设置setPermittedArrowDirections(.down)可以控制弹窗箭头方向让倒计时、时间选择在窄屏上更美观。五、originView 没有 superview弹窗箭头位置错乱或无法弹出问题表现从 CollectionView 的 cell、动态创建的视图或UIBarButtonItem弹出时箭头指向错误位置甚至直接不弹出。根因分析在 AbstractPopover.swift 的configureNavigationController中锚点是这样计算的sourceView originView.superview ?? baseViewWhenOriginViewHasNoSuperview ?? baseViewController.view sourceRect originView.frame如果originView还没有被加入视图层级superview 为 nil又没有传baseViewWhenOriginViewHasNoSuperview箭头位置就会基于整个控制器视图计算表现异常。另外通过UIBarButtonItem弹出时底层用的是item.value(forKey: view)这种 KVC 方式取视图取不到时也会静默失败。快速解决方案从 cell 弹出时务必传baseViewWhenOriginViewHasNoSuperview:参考 SampleViewController.swift 中collectionView(_:didSelectItemAt:)的写法从UIBarButtonItem弹出优先使用appear(barButtonItem:baseViewController:)重载方法自定义视图在viewDidAppear之后再触发弹窗确保已加入层级。六、自定义 Storyboard 覆盖失败改了个寂寞问题表现按文档复制了DatePickerPopover.storyboard到主工程并修改运行时却毫无变化。根因分析看 AbstractPopover.swift 的加载顺序会优先从主 BundleBundle.main查找同名 storyboardc找不到才回退到框架自身的 Bundle。所以放进主工程只是第一步还必须满足三个条件文件名与原始完全一致、勾选 Copy items if needed、在 Identity Inspector 中把 Module 显式指定为SwiftyPickerPopover取消 Inherit From Target。快速解决方案严格按 README 的四步操作找到原始 Storyboard → 同名加入主工程 → 修改 Module → 再自定义想覆盖多语言文案时需要在 App 工程中提供同名.strings本地化文件项目内置Base.lproj与ja.lproj可作参考否则界面文字仍是英文。总结SwiftyPickerPopover 避坑清单最后把 6 大坑浓缩成一张自查清单接入时逐项核对常见问题一句话解决方案循环引用闭包加[weak self]popover 不长期持有iOS 9 按钮消失低版本真机回归勿依赖 iOS 11 特性Clear 改变索引先设 Clear 再设选中行或手动置空首项分钟间隔无效仅.time/.countDownTimer模式生效箭头位置错乱传baseViewWhenOriginViewHasNoSuperviewStoryboard 不生效同名、Copy、显式指定 Module 三要素想本地跑一遍官方 Demo 快速验证可以克隆仓库git clone https://gitcode.com/gh_mirrors/sw/SwiftyPickerPopoverSwiftyPickerPopover 本身的 API 设计非常简洁链式调用、回调完善、iPhone/iPad 通用只要避开上面这些细节就能在 iOS 9 上稳定、优雅地实现各种选择器弹窗。遇到问题优先查看源码SwiftyPickerPopover/目录下的 Popover 类与 ViewController 类很多玄学其实都有明确答案。祝接入顺利 【免费下载链接】SwiftyPickerPopoverA more convenient way to display a popover with a built-in picker, on iPhone/iPad of iOS9.项目地址: https://gitcode.com/gh_mirrors/sw/SwiftyPickerPopover创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考