VCBoss
以简单和安全的方式以模态方式呈现 UIViewControllers。不再会有 致命异常:NSInvalidArgumentException 应用尝试以模态方式呈现活动控制器 ...
错误。轻松呈现、关闭、替换和交换正在呈现的 UIViewController。
为什么?
在我的 iOS 应用中,我喜欢以模态方式呈现、关闭、替换和交换 UIViewControllers。这是向用户呈现子视图并与主 UI 交互的好方法。
然而,管理所有这些呈现的 UIViewControllers 存在风险。如果我已经在向用户展示一个 UIViewController,我想要在此之后显示另一个,怎么办?如果我想要在用户按下“接受”按钮后用新的 UIViewController 替换当前显示的 UIViewController,怎么办?VCBoss 可用于很多用例。在一个呈现场景的 UIViewController 中手动管理所有这些用例会很快变得痛苦。
特点
VCBoss 包含您已经 accustomed 的基本功能
- 以模态方式呈现 UIViewController。
- 关闭之前以模态方式呈现的 UIViewController。
很简单,对吧?但是,这里就是 VCBoss 让我开心的地方
- 立即以模态方式呈现 UIViewController(如果呈现场景的 UIViewController 不是正在呈现 UIViewController)或将它添加到待展示的栈的末尾以等待将来展示。
- 强制显示UIViewController,如果有当前显示的UIViewController,将先将其销毁,然后显示新的UIViewController。请放心,如果有被销毁的UIViewController,在强制显示的UIViewController销毁后,它将再次被显示。就像有人插队。
- 如果有当前显示的UIViewController,用新的UIViewController替换它。
- 销毁一个UIViewController,并自动显示下一个等待的UIViewController。
- 销毁堆栈中所有显示的和即将显示的UIViewControllers。
所有这些操作都只需一行代码,而不会因尝试一次性显示2个或更多UIViewControllers而引发错误:fatal exception:NSInvalidArgumentException Application tried to present modally an active controller。
如何实现?
VCBoss使用一个非常熟悉的API。
- 立即以上模态方式显示新的UIViewController(如果当前显示的UIViewController没有正在显示的UIViewController)或添加到将来要显示的视图控制器堆栈的末尾,在VCBoss消毁之前的视图控制器后显示
self.vcboss.present(newViewController, animated: true, completion: nil)
- 销毁一个UIViewController
presentedViewController.vcboss.dismiss(animated: true, completion: nil)
或者
presentingViewController.vcboss.dismiss(presentedViewController, animated: true, completion: nil)
这将是您在代码中已熟悉的两个函数。要开始使用VCBoss,您只需要将所有实例的`self.present()`替换为`self.vcboss.present()`,将所有实例的`viewController.dismiss()`替换为`viewController.vcboss.dismiss()`。只需添加扩展即可。
为了使操作更简单,请参阅如何确定您已经使用了何处Self.present()和viewController.dismiss()以替换为VCBoss的部分。
以下是添加的UIKit没有提供但VCBoss提供的功能。
- 替换当前显示的UIViewController为新的UIViewController
self.vcboss.replace(with: newViewController, animated: true, completion: nil)
- 立即显示新的UIViewController,如果有显示的UIViewController,则将其销毁,并在新的UIViewController销毁后再次显示
self.vcboss.present(newViewController, animated: true, completion: nil, force: true)
- 如果没有正在显示的UIViewController,则显示新的UIViewController
self.vcboss.presentOnlyIfNothingAlreadyShown(newViewController, animated: true, completion: nil)
- 销毁当前显示的UIViewController,并停止显示之前可能添加的任何视图。清除堆栈以从头开始。
self.vcboss.dismissAll(animated: true, completion: nil)
- 如果您需要获取当前显示的UIViewControllers数量加上在当前显示的UIViewControllers销毁后将要显示的UIViewControllers堆栈中的人数
self.vcboss.numViewControllersPresenting
文档
示例
运行示例 iOS 应用
- 克隆仓库。
- 在
Example/
目录下运行pod install
。 - 通过打开
VCBoss
工作空间在 XCode 中运行应用。
安装
VCBoss 可通过 CocoaPods 获得。要安装它,只需将以下行添加到您的 Podfile 中
pod 'VCBoss', '~> version-here'
SwiftLint
如果使用 self.present()
和 self.dismiss()
来显示/隐藏 UIViewControllers,则 VCBoss 可能无法正常工作(它将尽力而为,但不能保证任何事情)。您必须使用 VCBoss 类来进行所有显示和隐藏操作。
但,我们都是人。很容易在您的应用中使用您的习惯,并使用 self.present()
。为了帮助您,我建议您使用 SwiftLint 在您使用这两种方法中的任何一种时抛出错误。当您尝试编译代码时,SwiftLint 将抛出 XCode 错误,不允许您继续,直到修复您的代码。
要使用 SwiftLint,您只需做以下操作
- 将 SwiftLint 安装到您的 iOS 项目中(非常简单。我使用 此方法)。
- 将以下内容添加到您的
.swiftlint.yml
文件中
custom_rules:
use_vcboss_present:
included: ".*\\.swift"
excluded: ".*Test\\.swift"
regex: "(self\.present\()"
message: "Use self.vcboss.present() instead."
severity: error
use_vcboss_dismiss:
included: ".*\\.swift"
excluded: ".*Test\\.swift"
regex: "(self\.dismiss\()"
message: "Use self.vcboss.dismiss() instead."
severity: error
作者
开发
文档
cocoapods自动为cocoadocs生成和托管文档。
使用命令 jazzy --podspec VCBoss.podspec
通过jazzy生成文档(假设已安装jazzy。如果没有:gem install jazzy
)
许可
VCBoss遵循MIT许可。详细信息请参阅LICENSE文件。
致谢
-
头部图片:由rawpixel.com发布在Unsplash
-
一些API的灵感来自Kingfisher。我尝试编写易于使用且与现有UIKit代码向后兼容的库,Kingfisher的API通过使用扩展和使用简便的代码看起来非常适合。