Swift - 顶部弹出框封装
抽空把项目里的顶部弹出框封装了一下。
效果大概是这个样子:
代码
自定义弹出框:
1 | // |
调用方式:
1 | //Swift 调用 |
一些思考
如上文所见,基本逻辑相对简单,首先编写一个继承自 UIView
的类,重写 init
方法用来自定义这个 view
,为了方便调用,用拓展写了两个类方法 showMessageView()
,让后通过定义的枚举来展示不同风格的提示框。虽然作为一个自定义 View
,上面的代码可能不是最优写法,但勉强算最适合我当前项目的写法。
也考虑到这个自定义 View
,并不对多数人适用。所以想分享一下我在封装这个 View
时所做的一些思考,主要有两点:
- 1.如何写好一个自定义 View?
- 2.我们应该如何设定自定义 View 的调用方式?
那么关于这两个问题的答案从哪里可以找到呢?其实总的来说也就是老生常谈的三个方向:
- 官方文档。
- 阅读源码。
- 技术博客。
展开来说,自定义 View
的官方文档,其实就是去看看 UIButton
、UIView
官方是怎么写的。但因为苹果是不开源的,看不到——虽然网上也有反推的实现,但毕竟有作者个人风格,而且有些还是用 C++
实现的,要模仿着写比较费劲。所以这条先搁置。
然后退而求其次,阅读 GitHub 上 Star 数量较多的自定义视图开源库,学学他们的写法。这里推荐两个库:
在封装消息提示框的时候我也考虑过对外开放的接口做成 MBProgressHUD
中调用方法返回一个单例,或者是和 SwiftMessages
将视图定义和使用分开。但最终因为图省事就选了一个简单的方式。另外还想到一个把 MessageView
用枚举来定义,然后通过实现关联值方法来直接显示,如果换这种实现的话,上面的调用方式可能就会变成这样:
1 | KKHeadMessageView.success.showMessageView("😊这是一个测试的弹窗。") |
看起来有点像工厂模式的产物😊。
最后是技术博客。在 Google 上搜,一大推的教你怎么自定义 View
,这里推荐两篇我觉得比较好的,有概念讲解,有源码示范,值得参考:
最后还有几个小疑惑备注在这里:
- 在自定义
View
中,我们通常在setSubUI
方法里面设置子视图,在里面写一大堆类似于这种代码:在 iOS应用架构谈 view层的组织和调用方案 中看到说建议把这种初始化都丢进1
2
3
4
5
6let label_mes = UILabel.init(frame: CGRect(x: 10, y: self.frame.height - textSize.height - 5, width: textSize.width, height: textSize.height))
label_mes.font = UIFont.init(name: "PingFangSC-Medium", size: 14)
label_mes.textColor = .white
label_mes.text = message
self.label_mes = label_mes
self.addSubview(self.label_mes)getter
里面,而且 getter 和 setter 全部都放在最后。另外配合Swift
中的extension
可以让代码布局更好看,但也看到唐巧的iOS 开发中的争议(一)中说:在类中完全使用 _property 的方式来访问私有成员变量,是不会有内存管理上的问题的。但是使用 self.property 的方式来访问私有变量是不是也是一样不会有内存管理上的问题呢?确实也是,但是有一点需要注意:我们最好不要在 init 和 dealloc 中使用 self.property 的方式来访问成员变量。
那么 setSubUI
的写法最优解是什么呢?
- 一个自定义
View
的展现形式通常有:
1)外部初始化后,外部手动添加到视图,比如一些嵌入视图
2)外部初始化后,自动添加到UIWindow
或者当前显示Controller
,比如一些弹出框视图。
3)也看到一自定义 View 会定义这种初始化方法initWith:(NSString*)Message ToRootView:(UIView*)View
。外部传入父视图,然后自己在内部添加自己。
以上三种方式,除了根据实际需求,就把自己添加到父视图上,还有什么更好的方式吗?
以上。