UIButton和UIImageView的圆角用CornerRadius和BezierPath实现对比

本文通过测试不同方法实现UIButton和UIImageView圆角的效果及性能表现,对比layer.cornerRadius与BezierPath两种方式,结果显示layer.cornerRadius方法在显示时间和代码执行时间上更优。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

UIButton和UIImageView的圆角实现方法有好几种,网上查到所有说法都不推荐使用layer.cornerRadius的方法来实现,理由是离屏渲染影响性能。想要测试一下是不是这样,写了一个ViewController里面加载4000个UIButton或UIImageView,一屏幕显示40个控件,分别用纯色和图片填充,大概记录一下从加载到完全显示出来的时间表。(苹果提供的性能检测工具用不了,可能是我Mac太老了)
工具:XCode10.1 Swift5.0 iPhone6x模拟器(手动升级Swift5.0,导致不能真机调试 (ㄒoㄒ) 流泪中…) 秒表(手动记时)

结果如下:

实现方式第一次第二次第三次第四次
显示/执行显示/执行显示/执行显示/执行
UIButton Color CornerRadius2.23/0.292.13/0.251.98/0.252.30/0.25
UIButton Color BezierPath2.55/0.362.30/0.332.23/0.342.21/0.35
UIButton Image CornerRadius3.01/0.283.23/0.272.91/0.272.61/0.29
UIButton Image BezierPath3.35/0.363.10/0.343.06/0.362.91/0.37
UIImageView CornerRadius2.16/0.952.11/0.902.16/0.912.11/0.90
UIImageView BezierPath2.21/1.012.21/0.992.18/0.991.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 CornerRadius1.56/0.491.11/0.491.56/0.471.60/0.48
UIView Color BezierPath1.05/0.581.73/0.591.65/0.561.75/0.56

性能也差不多,如果是一个纯色背景+文字的图片,从上表来看,推荐用UIView+UILable来实现,比UIIMageView快了一倍。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值