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)
}