iOS中容易用错的常用知识点
坐标系转换
ios中的坐标系有三种
视图坐标系:原点(0,0)视图的左上角
窗口坐标系:原点(0,0)窗口的左上角
世界坐标系:原点(0,0)游戏中世界的原点
平时开发中经常会遇到转UIWindow坐标问题,如:已知一个UI控件的坐标,把它转换到UIWindow时,它对应的UIWindow坐标是什么?
苹果提供了一套相关的转换方法,但是它缺少了坐标在转换时会涉及到三个UIView, 方法中没有对这3个UIView关系的描述,这在使用坐标转换时就很容易搞迷糊了。
1 2 3 4 5 6 7 8 9 | open func point ( inside point : CGPoint , with event : UIEvent ?) - > Bool open func convert ( _ point : CGPoint , to view : UIView ?) - > CGPoint open func convert ( _ point : CGPoint , from view : UIView ?) - > CGPoint open func convert ( _ rect : CGRect , to view : UIView ?) - > CGRect open func convert ( _ rect : CGRect , from view : UIView ?) - > CGRect |
举例如下:
1 2 3 4 5 6 7 | override func viewDidLoad () { super . viewDidLoad () view . addSubview ( myButton ) let center2 = view . convert ( myButton . center , to : UIApplication . shared . keyWindow ) } |
下面这件代码的意思是将self.view下面的子视图self.myButton的中点从它的视图坐标系中转换到keyWindow的窗口坐标系中时,得到的坐标是什么。
这句代码种涉及到的三个UIView: self.view, self.myButton, keyWindow。其中self.myButton是self.view的子视图。这层关系需要清楚,就避免迷糊了。
1 | view . convert ( myButton . center , to : UIApplication . shared . keyWindow ) |
自定义UIButton中Image和title的位置关系
UIButton中Image和title的位置坐标是可以自定义调整的,弄懂了下面这些就不用经常在UIView里套Image和Label来自定义视图了。
前置条件
手写UIButton时,ButtonType选择custom,style设置为Default(这个没有找到设置的地方,在xib上有这项,实际上手动创建的代码style默认就是Default)
使用xib创建的UIButton时,把它的plain改成Default。ButtonType设置成custom。
就是截图中的上面2项:

已知概念
1.UIButton中的image和image现在默认是上下,左右居中,并且image和title在水平方向是挨着的。
1 2 3 | btn . contentEdgeInsets = . zero btn . imageEdgeInsets = UIEdgeInsets ( top : 2 , left : 2 , bottom : 2 , right : 25 ) btn . titleEdgeInsets = UIEdgeInsets ( top : 2 , left : 12 , bottom : 2 , right : 2 ) |
2.上面btn相关的EdgeInset值的设置的效果 是和css中的padding内边距效果一致的。即:值>0内容向内缩,值<0内容往外扩展。
3.image和title具有中间挨着的特性,默认情况下,无论image左移多少,title都会跟随左移多少,以满足image和title中间挨着的特性。
4.对于设置的EdgeInset中的偏移量是相对于image和title在没有设置任何偏移量时的默认状态的偏移。
了解了上面这些概念就可以愉快的自定义UIButton中image和lable的位置了。
1 2 3 4 5 6 7 8 9 10 11 12 | let btn = UIButton ( type : . custom ) btn . frame = CGRect ( x : 100 , y : 80 , width : 40 , height : 20 ) btn . setTitleColor (. white , for : . normal ) btn . setTitle ( "jack" , for : . normal ) btn . titleLabel ?. font = UIFont . systemFont ( ofSize : 10 ) btn . setImage ( UIImage . init ( named : "loveHeat" ), for : . normal ) btn . backgroundColor = UIColor . black . withAlphaComponent ( 0.6 ) btn . layer . cornerRadius = 4 ; btn . layer . masksToBounds = true ; btn . imageEdgeInsets = UIEdgeInsets ( top : 3 , left : 2 , bottom : 1 , right : 25 ) btn . titleEdgeInsets = UIEdgeInsets ( top : 0 , left : 1 , bottom : 0 , right : 0 ) btn . isUserInteractionEnabled = false |
图层遮罩mask
在APP启动引导页或者APP中的气泡弹窗时,经常会用到图层的mask遮罩来自定义一些气泡形状。当向view.layer的mask属性添加一个图层属性时,有时候会搞混乱,这两个图层都有内容,它们作用在一起后,最终的显示效果是哪个展示,哪个不展示呢
1 | view . layer . mask = maskLayer |
简单的理解为:将view.layer中的页面内容按照maskLayer的路径进行裁剪。得出一个有一定路径边界的view视图。
举例如下:
1 2 3 4 5 6 7 8 | let view = UIView ( frame : CGRect ( x : 0 , y : 0 , width : 200 , height : 200 )) view . backgroundColor = . red let maskLayer = CAShapeLayer () let path = UIBezierPath ( ovalIn : view . bounds ) maskLayer . path = path . cgPath view . layer . mask = maskLayer |
这里我们首先创建了一个红色的 UIView,然后创建了一个圆形的 CAShapeLayer,将其 path 属性设置为一个内切于 view 边界的圆形 UIBezierPath,最后将 view 的 mask 属性设置为这个 CAShapeLayer,这样就实现了将视图裁剪成圆形的效果。
获取keyWindow
从iOS 13开始,应用程序可能同时包含多个场景(多个窗口),所以要获取keyWindow的话,已经不能直接读取UIApplication中的kewWindow这种方式了。
而是需要通过connectedScenes属性获取所有连接的场景(Scene),然后选择第一个场景,并将其转换为UIWindowScene类型。
然后从该场景中选择第一个UIWindow对象,判断该对象被是否被标记为isKeyWindow,如果返回true,则表示当前window为keyWindow。
代码如下:
1 2 3 4 | if let windowScene = UIApplication . shared . connectedScenes . first as ? UIWindowScene , let window = windowScene . windows . first ( where : { $ 0 . isKeyWindow }) { // 在这里使用当前正在使用的window对象 } |
· 分享4款.NET开源、免费、实用的商城系统
· Obsidian + DeepSeek:免费 AI 助力你的知识管理,让你的笔记飞起来!
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了