UIButton和UIImageView的圆角实现方法有好几种,网上查到所有说法都不推荐使用layer.cornerRadius的方法来实现,理由是离屏渲染影响性能。想要测试一下是不是这样,写了一个ViewController里面加载4000个UIButton或UIImageView,一屏幕显示40个控件,分别用纯色和图片填充,大概记录一下从加载到完全显示出来的时间表。(苹果提供的性能检测工具用不了,可能是我Mac太老了)
工具:XCode10.1 Swift5.0 iPhone6x模拟器(手动升级Swift5.0,导致不能真机调试 (ㄒoㄒ) 流泪中…) 秒表(手动记时)
结果如下:
实现方式 | 第一次 | 第二次 | 第三次 | 第四次 |
---|---|---|---|---|
– | 显示/执行 | 显示/执行 | 显示/执行 | 显示/执行 |
UIButton Color CornerRadius | 2.23/0.29 | 2.13/0.25 | 1.98/0.25 | 2.30/0.25 |
UIButton Color BezierPath | 2.55/0.36 | 2.30/0.33 | 2.23/0.34 | 2.21/0.35 |
UIButton Image CornerRadius | 3.01/0.28 | 3.23/0.27 | 2.91/0.27 | 2.61/0.29 |
UIButton Image BezierPath | 3.35/0.36 | 3.10/0.34 | 3.06/0.36 | 2.91/0.37 |
UIImageView CornerRadius | 2.16/0.95 | 2.11/0.90 | 2.16/0.91 | 2.11/0.90 |
UIImageView BezierPath | 2.21/1.01 | 2.21/0.99 | 2.18/0.99 | 1.96/1.06 |
从结果上看,从加载到显示出来的耗时,两种方式基本差不多,相差是毫秒级的。很有趣的是整体上来看,无论是从显示时间,还是代码执行时间来看layer.cornerRadius的耗时明显要少于BezierPath。也许是模拟器的原因,等新Mac机器来了用真机再测试一下看看。
主要代码:入口tableView页面+6个加载测试页面(代码很简单,贴出来方便大家复制测试)
入口页面tableView相关代码
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 6;
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell : UITableViewCell = UITableViewCell.init(style: UITableViewCell.CellStyle.default, reuseIdentifier: "purchaseCell");
cell.layer.borderWidth = 1
cell.layer.borderColor = UIColor.white.cgColor;
cell.layer.cornerRadius = 10
cell.layer.masksToBounds = true
cell.backgroundColor = UIColor.white;
switch indexPath.row{
case 0:
cell.textLabel?.text = "UIButton With Color CornerRadius";
case 1:
cell.textLabel?.text = "UIButton With Color BezierPath";
case 2:
cell.textLabel?.text = "UIImageView CornerRadius";
case 3:
cell.textLabel?.text = "UIImageView BezierPath";
case 4:
cell.textLabel?.text = "UIButton With Image CornerRadius";
case 5:
cell.textLabel?.text = "UIButton With Image BezierPath";
default:
cell.textLabel?.text = "";
}
return cell;
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
switch indexPath.row {
case 0:
let vc : TestCornerRadiusViewController = TestCornerRadiusViewController();
self.navigationController?.pushViewController(vc, animated: true);
case 1:
let vc : TestBezierPathViewController = TestBezierPathViewController();
self.navigationController?.pushViewController(vc, animated: true);
case 2:
let vc : TestImageCornerRadiusViewController = TestImageCornerRadiusViewController();
self.navigationController?.pushViewController(vc, animated: true);
case 3:
let vc : TestImageBezierPathViewController = TestImageBezierPathViewController();
self.navigationController?.pushViewController(vc, animated: true);
case 4:
let vc : TestImgBtnCornerRadiusViewController = TestImgBtnCornerRadiusViewController();
self.navigationController?.pushViewController(vc, animated: true);
case 5:
let vc : TestImgBtnBezierPathViewController = TestImgBtnBezierPathViewController();
self.navigationController?.pushViewController(vc, animated: true);
default:
break;
}
}
UIButton Color CornerRadius
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
initPageTitle(title: "UIButton Color CornerRadius");
self.navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Test", style: UIBarButtonItem.Style.plain, target: self, action: #selector(doTest));
}
@objc func doTest() -> Void {
let dateBegin = Date();
let dateFormatter = DateFormatter();
dateFormatter.dateFormat = "YYYY-MM-dd HH:mm:ss.SSS";
var locationString = dateFormatter.string(from: dateBegin);
print(locationString);
let main_width:CGFloat = self.view.frame.size.width;
var btn_x:CGFloat = 0.0;
var btn_y:CGFloat = navHeight();
let btn_width:CGFloat = main_width/4;
let btn_height:CGFloat = 50.0;
for rowIndex in 1...1000{
btn_x = 0;
btn_y += btn_height;
for colIndex in 0...3{
let btn : UIButton = UIButton(type: UIButton.ButtonType.custom);
btn_x = CGFloat(colIndex) * btn_width;
btn.frame = CGRect(x: btn_x, y: btn_y, width: btn_width, height: btn_height);
btn.backgroundColor = UIColor.brown;
btn.tintColor = UIColor.white;
btn.setTitle(String(rowIndex) + "_" + String(colIndex), for: UIControl.State.normal);
btn.layer.cornerRadius = 10.0;
self.view.addSubview(btn);
}
}
let dateEnd = Date();
locationString = dateFormatter.string(from: dateEnd);
print(locationString);
let timeMinus = dateEnd.timeIntervalSince1970-dateBegin.timeIntervalSince1970;
print(String(timeMinus));
}
UIButton Color BezierPath
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
initPageTitle(title: "UIButton Color BezierPath");
self.navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Test", style: UIBarButtonItem.Style.plain, target: self, action: #selector(doTest));
}
@objc func doTest() -> Void {
let dateBegin = Date();
let dateFormatter = DateFormatter();
dateFormatter.dateFormat = "YYYY-MM-dd HH:mm:ss.SSS";
var locationString = dateFormatter.string(from: dateBegin);
print(locationString);
let main_width:CGFloat = self.view.frame.size.width;
var btn_x:CGFloat = 0.0;
var btn_y:CGFloat = navHeight();
let btn_width:CGFloat = main_width/4;
let btn_height:CGFloat = 50.0;
for rowIndex in 1...1000{
btn_x = 0;
btn_y += btn_height;
for colIndex in 0...3{
let btn : UIButton = UIButton(type: UIButton.ButtonType.custom);
btn_x = CGFloat(colIndex) * btn_width;
btn.frame = CGRect(x: btn_x, y: btn_y, width: btn_width, height: btn_height);
btn.backgroundColor = UIColor.lightGray;
btn.tintColor = UIColor.white;
btn.setTitle(String(rowIndex) + "_" + String(colIndex), for: UIControl.State.normal);
let maskPath : UIBezierPath = UIBezierPath.init(roundedRect:btn.bounds, byRoundingCorners: UIRectCorner.allCorners, cornerRadii: CGSize(width: 10.0,height: 10.0));
let maskShapeLayer : CAShapeLayer = CAShapeLayer();
maskShapeLayer.frame = btn.bounds;
maskShapeLayer.path = maskPath.cgPath;
btn.layer.mask = maskShapeLayer;
self.view.addSubview(btn);
}
}
let dateEnd = Date();
locationString = dateFormatter.string(from: dateEnd);
print(locationString);
let timeMinus = dateEnd.timeIntervalSince1970-dateBegin.timeIntervalSince1970;
print(String(timeMinus));
}
UIButton Image CornerRadius
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
initPageTitle(title: "UIButton Image CornerRadius");
self.navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Test", style: UIBarButtonItem.Style.plain, target: self, action: #selector(doTest));
}
@objc func doTest() -> Void {
let dateBegin = Date();
let dateFormatter = DateFormatter();
dateFormatter.dateFormat = "YYYY-MM-dd HH:mm:ss.SSS";
var locationString = dateFormatter.string(from: dateBegin);
print(locationString);
let main_width:CGFloat = self.view.frame.size.width;
var btn_x:CGFloat = 0.0;
var btn_y:CGFloat = navHeight();
let btn_width:CGFloat = main_width/4;
let btn_height:CGFloat = 50.0;
for rowIndex in 1...1000{
btn_x = 0;
btn_y += btn_height;
for colIndex in 0...3{
let btn : UIButton = UIButton(type: UIButton.ButtonType.custom);
btn_x = CGFloat(colIndex) * btn_width;
btn.frame = CGRect(x: btn_x, y: btn_y, width: btn_width, height: btn_height);
btn.setBackgroundImage(UIImage(named: "BtnJuxing"), for: UIControl.State.normal);
btn.tintColor = UIColor.white;
btn.setTitle(String(rowIndex) + "_" + String(colIndex), for: UIControl.State.normal);
btn.layer.masksToBounds = true;
btn.layer.cornerRadius = 25.0;
self.view.addSubview(btn);
}
}
let dateEnd = Date();
locationString = dateFormatter.string(from: dateEnd);
print(locationString);
let timeMinus = dateEnd.timeIntervalSince1970-dateBegin.timeIntervalSince1970;
print(String(timeMinus));
}
UIButton Image BezierPath
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
initPageTitle(title: "UIButton Image BezierPath");
self.navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Test", style: UIBarButtonItem.Style.plain, target: self, action: #selector(doTest));
}
@objc func doTest() -> Void {
let dateBegin = Date();
let dateFormatter = DateFormatter();
dateFormatter.dateFormat = "YYYY-MM-dd HH:mm:ss.SSS";
var locationString = dateFormatter.string(from: dateBegin);
print(locationString);
let main_width:CGFloat = self.view.frame.size.width;
var btn_x:CGFloat = 0.0;
var btn_y:CGFloat = navHeight();
let btn_width:CGFloat = main_width/4;
let btn_height:CGFloat = 50.0;
for rowIndex in 1...1000{
btn_x = 0;
btn_y += btn_height;
for colIndex in 0...3{
let btn : UIButton = UIButton(type: UIButton.ButtonType.custom);
btn_x = CGFloat(colIndex) * btn_width;
btn.frame = CGRect(x: btn_x, y: btn_y, width: btn_width, height: btn_height);
btn.setBackgroundImage(UIImage(named: "BtnJuxing"), for: UIControl.State.normal);
btn.tintColor = UIColor.white;
btn.setTitle(String(rowIndex) + "_" + String(colIndex), for: UIControl.State.normal);
let maskPath : UIBezierPath = UIBezierPath.init(roundedRect:btn.bounds, byRoundingCorners: UIRectCorner.allCorners, cornerRadii: CGSize(width: 25.0,height: 25.0));
let maskShapeLayer : CAShapeLayer = CAShapeLayer();
maskShapeLayer.frame = btn.bounds;
maskShapeLayer.path = maskPath.cgPath;
btn.layer.mask = maskShapeLayer;
self.view.addSubview(btn);
}
}
let dateEnd = Date();
locationString = dateFormatter.string(from: dateEnd);
print(locationString);
let timeMinus = dateEnd.timeIntervalSince1970-dateBegin.timeIntervalSince1970;
print(String(timeMinus));
}
UIImageView CornerRadius
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
initPageTitle(title: "UIImageView CornerRadius");
self.navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Test", style: UIBarButtonItem.Style.plain, target: self, action: #selector(doTest));
}
@objc func doTest() -> Void {
let dateBegin = Date();
let dateFormatter = DateFormatter();
dateFormatter.dateFormat = "YYYY-MM-dd HH:mm:ss.SSS";
var locationString = dateFormatter.string(from: dateBegin);
print(locationString);
let main_width:CGFloat = self.view.frame.size.width;
var btn_x:CGFloat = 0.0;
var btn_y:CGFloat = navHeight();
let btn_width:CGFloat = main_width/4;
let btn_height:CGFloat = 50.0;
for rowIndex in 1...1000{
btn_x = 0;
btn_y += btn_height;
for colIndex in 0...3{
let imageView : UIImageView = UIImageView(image: UIImage(named: "BtnJuxing"))
btn_x = CGFloat(colIndex) * btn_width;
imageView.frame = CGRect(x: btn_x, y: btn_y, width: btn_width, height: btn_height);
imageView.backgroundColor = UIColor.green;
imageView.tintColor = UIColor.white;
let memoLable : UILabel = UILabel(frame: CGRect(x:0.0,y:0.0,width: btn_width,height:btn_height));
memoLable.textColor = UIColor.white;
memoLable.textAlignment = NSTextAlignment.center;
memoLable.text = String(rowIndex) + "_" + String(colIndex);
imageView.addSubview(memoLable);
imageView.layer.masksToBounds = true;
imageView.layer.cornerRadius = 25.0;
self.view.addSubview(imageView);
}
}
let dateEnd = Date();
locationString = dateFormatter.string(from: dateEnd);
print(locationString);
let timeMinus = dateEnd.timeIntervalSince1970-dateBegin.timeIntervalSince1970;
print(String(timeMinus));
}
UIImageView BezierPath
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
initPageTitle(title: "UIImageView BezierPath");
self.navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Test", style: UIBarButtonItem.Style.plain, target: self, action: #selector(doTest));
}
@objc func doTest() -> Void {
let dateBegin = Date();
let dateFormatter = DateFormatter();
dateFormatter.dateFormat = "YYYY-MM-dd HH:mm:ss.SSS";
var locationString = dateFormatter.string(from: dateBegin);
print(locationString);
let main_width:CGFloat = self.view.frame.size.width;
var btn_x:CGFloat = 0.0;
var btn_y:CGFloat = navHeight();
let btn_width:CGFloat = main_width/4;
let btn_height:CGFloat = 50.0;
for rowIndex in 1...1000{
btn_x = 0;
btn_y += btn_height;
for colIndex in 0...3{
let btn : UIImageView = UIImageView(image: UIImage(named: "BtnJuxing"))
btn_x = CGFloat(colIndex) * btn_width;
btn.frame = CGRect(x: btn_x, y: btn_y, width: btn_width, height: btn_height);
btn.backgroundColor = UIColor.white;
btn.tintColor = UIColor.yellow;
let memoLable : UILabel = UILabel(frame: CGRect(x:0.0,y:0.0,width: btn_width,height:btn_height));
memoLable.textColor = UIColor.white;
memoLable.text = String(rowIndex) + "_" + String(colIndex);
memoLable.textAlignment = NSTextAlignment.center;
btn.addSubview(memoLable);
let maskPath : UIBezierPath = UIBezierPath.init(roundedRect:btn.bounds, byRoundingCorners: UIRectCorner.allCorners, cornerRadii: CGSize(width: 25.0,height: 25.0));
let maskShapeLayer : CAShapeLayer = CAShapeLayer();
maskShapeLayer.frame = btn.bounds;
maskShapeLayer.path = maskPath.cgPath;
btn.layer.mask = maskShapeLayer;
self.view.addSubview(btn);
}
}
let dateEnd = Date();
locationString = dateFormatter.string(from: dateEnd);
print(locationString);
let timeMinus = dateEnd.timeIntervalSince1970-dateBegin.timeIntervalSince1970;
print(String(timeMinus));
}
顺便试了一下UIView纯色填充,结果如下:
实现方式 | 第一次 | 第二次 | 第三次 | 第四次 |
---|---|---|---|---|
– | 显示/执行 | 显示/执行 | 显示/执行 | 显示/执行 |
UIView Color CornerRadius | 1.56/0.49 | 1.11/0.49 | 1.56/0.47 | 1.60/0.48 |
UIView Color BezierPath | 1.05/0.58 | 1.73/0.59 | 1.65/0.56 | 1.75/0.56 |
性能也差不多,如果是一个纯色背景+文字的图片,从上表来看,推荐用UIView+UILable来实现,比UIIMageView快了一倍。