Swift范型应用
引言:对于不同种类的对象,如果存在共同特性,就可以抽象出一个协议,让对象的类遵守该协议,可以用尽量少的代码实现一些重复性高但又不是完全相同的需求
应用场景举例
在a页面使用Person数据展示点赞标签列表,在b页面使用Category数据展示分类标签列表,在c页面使用Product数据展示产品列表
根据标签列表视图需要用到的数据,可以将三类数据进行抽象,定义一个有共同特征的Tag协议
protocol Tag {
//变量声明为只读
//要求在遵守本协议的类中,实现变量的get方法
var title: String? {get}
var img_path: String? {get}
}
定义三个数据模型类,并遵守Tag协议
class Person: NSObject, Tag {
var name: String?
var mobile: String?
var icon_path: String?
var title: String? {
return name
}
var img_path: String? {
return icon_path
}
}
class Category: NSObject, Tag {
var c_name: String?
var bg_path: String?
var title: String? {
return c_name
}
var img_path: String? {
return bg_path
}
}
class Product: NSObject, Tag {
var name: String?
var price: Double?
var image_path: String?
var title: String? {
return name
}
var img_path: String? {
return image_path
}
}
定义标签列表视图类TagsView
class TagsView: UIView {
//对外提供一系列配置属性,或者定义一个Config结构体
var text_size: CGFloat = 16
var text_color = .white
var bg_color = .white
var tags_margin_h: CGFloat = 16
var tags_margin_v: CGFloat = 16
var tags_size = CGSize(width: 80, height: 40)
var tag_min_width: CGFloat = 80
//.....
/**
* 对外提供刷新方法
* 运用范型,接收任意遵守了Tag协议的元素的数组作为数据源
* 在刷新方法内根据配置属性以及数据源的数据,给视图添加标签
*/
func reloadData<T: Tag>(_ datasource: [T]) {
}
/**
* 该方法根据数据源计算每一个标签的frame
* 用于reloadData方法中每一个标签的布局
*/
private func dispose<T: Tag>(_ array: [T]) -> [String: CGFloat] {
}
}
viewController中的应用
func viewDidLoad() {
super.viewDidLoad()
var config = TagsViewConfig(...)
var tagsView = TagsView(conf: config)
self.view.addSubView(tagsView)
}
func loadData() {
self.tagsView.reloadData(list)
}