美文网首页ios进阶iOS开发SwiftiOS小超人
Swift编程(六):Snapkit的启示录

Swift编程(六):Snapkit的启示录

作者: zZ爱吃菜 | 来源:发表于2015-11-22 01:26 被阅读19595次

    写在前面(Github地址)

    个人项目

    个人站点:LN电影网
    个人博客:L&N博客

    欢迎大家关注我的个人博客:<a href="http://blog.noasis.cn" >博客地址</a>,这里主要是我在个人开发时候遇到的坑和挖完的坑,包括 PHP CentOS 以及 Swift 等相关只是

    主要记录了,我在学习Snapkit中的一些整理记录

    学习目标

    • 好好学习如何用代码来做自动布局
    • 使用SnapKit做了一个修改密码的表单
    效果图

    1. Snapkit的安装

    • Cocoapods安装

    在项目的Podfile下添加如下信息
    在终端中执行:<code>pod install</code>(注意路径是当前项目中Podfile锁在路径)

    source 'https://github.com/CocoaPods/Specs.git'
    platform :ios, '8.0'
    use_frameworks!pod 'SnapKit', '~> 0.15.0'
    
    • Carthage安装

    Carthage是一种分散式依赖管理库用来自动为你的Cocoa应用添加第三方框架

    1) 通过下面命令行执行安装Carthage

    brew update
    brew install carthage
    

    2) 通过下面命令行继承SnapKit到你的项目中的Cartfile

    github "SnapKit/SnapKit" >= 0.15.0
    

    3.)通过直接讲SnapKit的源代码拖放到自己的项目目录当中

    这也是我比较喜欢的一种方式,这样可以比较自由的讲代码拖放到自己执行的目录下

    2. SnapKit的兼容操作

    如果希望SnapKit支持IOS7版本,需要在自己的项目的 Build Setting 中搜索的 OTHER_SWIFT_FLAGS,在其下面添加 -DSNAPKIT_DEPLOYMENT_LEGACY,如下图所示:(否则会报错!)

    示意图

    3. Snapkit官方文档翻译

    通用模式:

    let box = UIView()
    superview.addSubview(box)
    box.snp_makeConstraints { (make) -> Void in
      //解释:box对象相对于父视图上边距为20像素
      make.top.equalTo(superview).offset(20) 
      make.left.equalTo(superview).offset(20) 
      make.bottom.equalTo(superview).offset(-20) 
      make.right.equalTo(superview).offset(-20)
    }
    

    注意:在SnapKit当中 X轴向右方向;Y轴向下方向 为正

    缩写形式

    let box = UIView()
    superview.addSubview(box)
    box.snp_makeConstraints { (make) -> Void in 
        //注释:box距离父视图上下左右边距都是20像素
        make.edges.equalTo(superview).inset(UIEdgeInsetsMake(20, 20, 20, 20))
    }
    

    SnapKit还可以通过下面几个步骤来实现缩短代码和提高代码可读性

    • 确定最佳的普通视图安装限制。
    • 保持轨道的约束安装所以他们可以很容易地被删除后。
    • 在所有适当的视图上确保 <code>setTranslatesAutoresizingMaskIntoConstraints(false)</code>属性被设置

    SnapKit中并不局限于 等于(equalTo)

    • .equalTo:等于
    • .lessThanOrEqualTo 小于等于
    • .greaterThanOrEqualTo 大于等于
    1.视图属性
    //当前视图对象的中心x坐标小于等于view视图的左边的x左边
    make.centerX.lessThanOrEqualTo(view.snp_left)
    

    视图属性:

    上 :上边对应的Y轴 (top)
    下: 下边对应的Y轴 (bottom)
    左: 左边对应的Y轴 (left)
    右: 右边对应的X轴 (right)

    视图属性(ViewAttribute) 布局属性 (NSLayoutAttribute)
    view.snp_left NSLayoutAttribute.Left
    view.snp_right NSLayoutAttribute.Right
    view.snp_top NSLayoutAttribute.Top
    view.snp_bottom NSLayoutAttribute.Bottom
    view.snp_leading NSLayoutAttribute.Leading
    view.snp_trailing NSLayoutAttribute.Trailing
    view.snp_width NSLayoutAttribute.Width
    view.snp_height NSLayoutAttribute.Height
    view.snp_centerX NSLayoutAttribute.CenterX
    view.snp_centerY NSLayoutAttribute.CenterY
    view.snp_baseline NSLayoutAttribute.Baseline
    2.视图关系(UIView/NSView)

    如果你想 视图 view.left 大于等于 label.left ,执行下面代码:

    //下面这两者的约束是完全一样的
    make.left.greaterThanOrEqualTo(label)
    make.left.greaterThanOrEqualTo(label.snp_left)
    
    3.严格检测(Strick Checks)

    自动布局允许将宽度和高度属性设置为常量值。如果你想对视图设置一个最小和最大宽度,你必须先给他一个初始的平等块:

    //设置宽度>= 200 && <= 400
    

    你也可以用其他的约束和结构来建立你的约束,像这样:

    make.top.equalTo(42)
    make.height.equalTo(20)
    make.size.equalTo(CGSizeMake(50,100))
    make.edges.equalTo(UIEdgeInsetsMake(10,0,10,0))
    make.left.equalTo(view).offset(UIEdgeInsetsMake(10,0,10,0)) 
    
    4.学习优先级
    • .priority: 允许您指定一个确切的优先级
    • .priorityHigh: 高优先级 等价于 UILayoutPriority.DefaultHigh
    • .priorityMedium:中优先级
    • .priorityLow:低优先级 UILayoutPriority.DefaultLow

    优先级可以放在约束链的结束处,例如

    //当前视图的左边>=label的底部 低优先级
    make.left.greaterThanOrEqualTo(label.snp_left).priorityLow()
    //当前视图与label的顶部齐平,优先级:600
    make.top.equalTo(label.snp_top).priority(600)
    
    5.组成,组成,组成

    SnapKit 也可以提供一些便利的方法来同时创建多约束

    1. edges(边缘)
    //让当前视图 的 上下左右(top,left,bottom,right) 等于 view2
    make.edges.equalTo(view2)
    // make top = superview.top + 5; left = superview.left +10
    // bottom = superview.bottom -15; right = superview.right - 20
    make.edges.equalTo(superView).inset(UIEdgeInsetsMake(5,10,15,20))
    

    2.size(尺寸)

    //当前视图宽高 >= titleLabel
    make.size.greaterThanOrEqualTo(titleLabel)
    //make width = superview.width + 100; height = superview.height -50
    //即 当前视图宽 = 父视图 + 100,高 = 父视图.高 - 50
    make.size.equalTo(superview).offset(CGSizeMake(100, -50))
    ```<
    
    >3.center(中心)
    
    ```swift
    //当前视图与 button1中心相同 (centerX 和 centerY)
    make.center.equalTo(button1)
    //make centerX = superview.centerX - 5; centerY = superview.centerY +10
    make.center.equalTo(superview).offset(CGPointMake(-5,10))
    

    您可以串连视图属性增加可读性

    //所有边缘除了top都等于父视图, top为20
    make.left.right.bottom.equalTo(superview)
    make.top.equalTo(20)
    
    6.Hold on for dear life

    有时候你需要修改已经存在的约束为了移动或者移除、代替约束。在SnapKit 有一些不同的方法更新约束

    1.引用(References)
    你可以通过将约束的结果赋值给一个局部变量或一个类属性来保持一个特定的约束的引用。您还可以将多个约束引用存储在数组中。

    var topConstraint: Constraint? = nil
    
    //当制作约束时
    view1.snp_makeConstraints{ (make) -> Void in
            self.topConstrain = make.top.equalTo(superview).offset(padding.top).constraint
            make.left.equalTo(superview).offset(padding.left)
    
    // 然后接下来你可以这样
    self.topConstraint.uninstall()
    
    //或者如果你想要更新约束
    self.topConstraint.updateOffset(5)
    

    2.snp_updateConstraints(更新约束)
    如果你仅仅想更新一个常数给一个约束,你可以使用方法<code>snp_updateConstraints</code>来代替<code>snp_makeConstraints</code>

    //这是一个苹果官方推荐的添加和更新约束的地方
    //这个方法在响应<code>setNeedsUpdateConstraints</code>多次调用
    //这个方法可以倍UIKit调用
    override func updateConstraints() {
            self.growingButton.snp_updateConstraints{ (make) -> Void in
                    make.center.equalTo(self);
                    make.width.equalTo(self.buttonSize.width).priorityLow()
                    make.height.equalTo(self.buttonSize.height).priorityLow()
                    make.width.lessThanOrEqualTo(self)
                    make.height.lessThanOrEqualTo(self)
            }
            
            //父类可以调用
            super.updateConstraints()
    }
    

    3.snp_remakeConstraints(重做约束)

    <code>snp_remakeConstraints</code>与<code>snp_makeConstraints</code>类似,但是首先会先清除掉所有被SnapKit设置的约束

    func changeButtonPosition() {
            self.button.snp_remakeConstraints{ (make) -> Void in
                    make.size.equalTo(self.buttonSize)
                    if topLeft {
                            make.top.left.equalTo(10)
                    } else {
                            make.bottom.equalTo(self.view).offset(-10)
                            make.right.equalTo(self.view).offset(-10)
                    }
            }
    }
    

    4.Demo的具体代码(我的Github)

    创建属性

        var oldPassword: UITextField!
        var newPassword: UITextField!
        var confirmPassword: UITextField!
        var formView: UIView!
        var confirmButton:UIButton!
        
        var topConstraint: Constraint?
    

    UI初始化

        func initUI(){
            self.title = "修改密码"
            self.view.backgroundColor = UIColor.redColor()
            //登录框背景
            self.formView = UIView()
            self.formView.layer.borderWidth = 0.5
            self.formView.layer.borderColor = UIColor.lightGrayColor().CGColor
            self.formView.backgroundColor = UIColor.whiteColor()
            self.formView.layer.cornerRadius = 5
            self.view.addSubview(self.formView)
            //最常规的设置模式
            self.formView.snp_makeConstraints { (make) -> Void in
                make.left.equalTo(15)
                make.right.equalTo(-15)
                //存储top属性
                self.topConstraint = make.top.equalTo(200).constraint
                make.height.equalTo(220)
                
            }
            
            //密码图
            let imgLock1 =  UIImageView(frame:CGRectMake(11, 11, 22, 22))
            imgLock1.image = UIImage(named:"iconfont-password")
            
            //密码图
            let imgLock2 =  UIImageView(frame:CGRectMake(11, 11, 22, 22))
            imgLock2.image = UIImage(named:"iconfont-password")
            
            //密码图
            let imgLock3 =  UIImageView(frame:CGRectMake(11, 11, 22, 22))
            imgLock3.image = UIImage(named:"iconfont-password")
            
            //旧密码输入框
            self.oldPassword = UITextField()
            self.oldPassword.delegate = self
            self.oldPassword.tag = 100
            self.oldPassword.placeholder = "请输入旧密码"
            self.oldPassword.layer.cornerRadius = 5
            self.oldPassword.layer.borderColor = UIColor.lightGrayColor().CGColor
            self.oldPassword.layer.borderWidth = 0.5
            self.oldPassword.leftView = UIView(frame:CGRectMake(0, 0, 44, 44))
            self.oldPassword.leftViewMode = UITextFieldViewMode.Always
            self.oldPassword.returnKeyType = UIReturnKeyType.Next
            
            //密码输入框左侧图标
            self.oldPassword.leftView!.addSubview(imgLock1)
            self.formView.addSubview(self.oldPassword)
            
            //布局
            self.oldPassword.snp_makeConstraints { (make) -> Void in
                make.left.equalTo(30)
                make.top.equalTo(20)
                make.right.equalTo(-30)
                make.height.equalTo(44)
            }
            
            //新密码输入框
            self.newPassword = UITextField()
            self.newPassword.delegate = self
            self.newPassword.tag = 101
            self.newPassword.placeholder = "请输入新密码"
            self.newPassword.layer.cornerRadius = 5
            self.newPassword.layer.borderColor = UIColor.lightGrayColor().CGColor
            self.newPassword.layer.borderWidth = 0.5
            self.newPassword.leftView = UIView(frame:CGRectMake(0, 0, 44, 44))
            self.newPassword.leftViewMode = UITextFieldViewMode.Always
            self.newPassword.returnKeyType = UIReturnKeyType.Next
            
            //密码输入框左侧图标
            self.newPassword.leftView!.addSubview(imgLock2)
            self.formView.addSubview(self.newPassword)
            
            //布局
            self.newPassword.snp_makeConstraints { (make) -> Void in
                make.left.equalTo(30)
                make.top.equalTo(self.oldPassword.snp_bottom).offset(20)
                make.right.equalTo(-30)
                make.height.equalTo(44)
            }
            
            //确认新密码输入框
            self.confirmPassword = UITextField()
            self.confirmPassword.delegate = self
            self.confirmPassword.tag = 102
            self.confirmPassword.placeholder = "请重复新密码"
            self.confirmPassword.layer.cornerRadius = 5
            self.confirmPassword.layer.borderColor = UIColor.lightGrayColor().CGColor
            self.confirmPassword.layer.borderWidth = 0.5
            self.confirmPassword.leftView = UIView(frame:CGRectMake(0, 0, 44, 44))
            self.confirmPassword.leftViewMode = UITextFieldViewMode.Always
            self.confirmPassword.returnKeyType = UIReturnKeyType.Done
            
            //密码输入框左侧图标
            self.confirmPassword.leftView!.addSubview(imgLock3)
            self.formView.addSubview(self.confirmPassword)
            
            //布局
            self.confirmPassword.snp_makeConstraints { (make) -> Void in
                make.left.equalTo(30)
                make.top.equalTo(self.newPassword.snp_bottom).offset(20)
                make.right.equalTo(-30)
                make.height.equalTo(44)
            }
            
            self.confirmButton = UIButton()
            self.confirmButton.setTitle("确认修改", forState: UIControlState.Normal)
            self.confirmButton.setTitleColor(UIColor.whiteColor(), forState: UIControlState.Normal)
            self.confirmButton.layer.cornerRadius = 5
            self.confirmButton.backgroundColor = UIColor(colorLiteralRed: 0.99, green: 0.82, blue: 0.04, alpha: 1)
            self.view.addSubview(self.confirmButton)
            self.confirmButton.snp_makeConstraints { (make) -> Void in
                make.left.equalTo(15)
                make.top.equalTo(self.formView.snp_bottom).offset(20)
                make.right.equalTo(-15)
                make.height.equalTo(44)
            }
        }
    

    UITextField的代理

     extension SnapkitViewController: UITextFieldDelegate {
        
        //输入框获取焦点开始编辑
        func textFieldDidBeginEditing(textField:UITextField)
        {
            let tag = textField.tag
            switch tag {
            case 100:
                UIView.animateWithDuration(0.5, animations: { () -> Void in
                    self.topConstraint?.updateOffset(150)
                    self.view.layoutIfNeeded()
                })
            case 101:
                UIView.animateWithDuration(0.5, animations: { () -> Void in
                    self.topConstraint?.updateOffset(100)
                    self.view.layoutIfNeeded()
                })
            case 102:
                UIView.animateWithDuration(0.5, animations: { () -> Void in
                    self.topConstraint?.updateOffset(70)
                    self.view.layoutIfNeeded()
                })
            default:
                print("error")
            }
        }
        
        //输入框返回时操作
        func textFieldShouldReturn(textField:UITextField) -> Bool
        {
            let tag = textField.tag
            switch tag {
            case 100:
                self.newPassword.becomeFirstResponder()
            case 101:
                //下一个
                self.confirmPassword.becomeFirstResponder()
            case 102:
                //收起键盘
                textField.resignFirstResponder()
                UIView.animateWithDuration(0.5, animations: { () -> Void in
                    self.topConstraint?.updateOffset(200)
                    self.view.layoutIfNeeded()
                })
            default:
                print(textField.text)
            }
            return true
        }
    }
    

    5.总结一下 UITextField

    样式

     UITextBorderStyle.None:无边框
     UITextBorderStyle.Line:直线边框
     UITextBorderStyle.RoundedRect:圆角矩形边框
     UITextBorderStyle.Bezel:边线+阴影
    

    输入提示

    textField.placeholder="请输入用户名"
    

    内容设置

    //当文字超出文本框宽度时,自动调整文字大小
    textField.adjustsFontSizeToFitWidth = true
    //最小可缩小的字号
    textField.minimumFontSize = 14  
    

    对齐方式

     //水平右对齐
    textField.textAlignment = .Right
    
     //水平居中对齐
    textField.textAlignment = .Center
    
     //水平左对齐
    textField.textAlignment = .Left
    
     //垂直向上对齐
    textField.contentVerticalAlignment = .Top
     
      //垂直居中对齐
    textField.contentVerticalAlignment = .Center
    
      //垂直向下对齐
    textField.contentVerticalAlignment = .Bottom
    

    设置清除按钮

      //编辑时出现清除按钮
    textField.clearButtonMode = UITextFieldViewMode.WhileEditing
    
      //编辑时不出现,编辑后才出现清除按钮
    textField.clearButtonMode = UITextFieldViewMode.UnlessEditing
    
      //一直显示清除按钮
    textField.clearButtonMode = UITextFieldViewMode.Always
    
    

    设置键盘的类型

    Default:系统默认的虚拟键盘
    ASCII Capable:显示英文字母的虚拟键盘
    Numbers and Punctuation:显示数字和标点的虚拟键盘
    URL:显示便于输入数字的虚拟键盘
    Number Pad:显示便于输入数字的虚拟键盘
    Phone Pad:显示便于拨号呼叫的虚拟键盘
    Name Phone Pad:显示便于聊天拨号的虚拟键盘
    Email Address:显示便于输入Email的虚拟键盘
    Decimal Pad:显示用于输入数字和小数点的虚拟键盘
    Twitter:显示方便些Twitter的虚拟键盘
    Web Search:显示便于在网页上书写的虚拟键盘
    //例子
    textField.keyboardType = UIKeyboardType.NumberPad
    

    焦点

    //获取焦点
    textField.becomeFirstResponder()
    //移除焦点
    textField.resignfirstresponder()
    

    设置返回return样式跟功能

     //表示完成输入
    textField.returnKeyType = UIReturnKeyType.Done
    
     //表示完成输入,同时会跳到另一页
    textField.returnKeyType = UIReturnKeyType.Go
    
     //表示搜索
    textField.returnKeyType = UIReturnKeyType.Search
    
     //表示注册用户或添加数据
    textField.returnKeyType = UIReturnKeyType.Join
    
     //表示继续下一步
    textField.returnKeyType = UIReturnKeyType.Next
    
     //表示发送
    textField.returnKeyType = UIReturnKeyType.Send
    
    

    代理

    //开始编辑时的操作
    func textFieldDidBeginEditing()
    //点击返回按钮时的操作
    func textFieldShouldReturn()
    

    今天的内容就这样吧,2015-11-22 01:25:29,有点困!

    相关文章

      网友评论

      • 舒马赫:用纯代码写界面是不是有点太慢了,随便一个界面都要一大坨代码,每改点东西还要重新运行,另外由于autolayout先天原因布局速度是比较慢的,会影响帧率。推荐使用xml的布局库FlexLib,采用前端布局标准flexbox(不使用autolayout),支持热刷新,自动计算高度等。可以到这里了解详细信息:

        https://github.com/zhenglibao/FlexLib
      • taocejun:用了这个框架布局后在Instruments-->leaks中发现好多内存泄漏,怎么破?
      • 幸福的鱼:怎么设置两个同级控件的约束呢,试了好久都不对
      • 皓皓大帝:楼主,为什么用pod安装完SnapKit后,在OC和Swift中都无法使用?找不到方法!
        郭鵬飛on:@风吹柳絮如花落 我编译没问题。可是box 点不出来 snp. 你解决了么?
        冯思畅:@皓皓大帝 安装完框架之后Command+B一下
        风吹柳絮如花落:@皓皓大帝 同问楼主这个问题,安装成功了,但是view “丶” 不出来snp
      • a0c0cdcc96c9:能不能把deom的代码地址发一下,谢谢了
      • 814caae8520c:按照楼主的安装方式 没有安装成功
        zZ爱吃菜:@光棱 你是使用手动还是 pod 方式?
        814caae8520c:是我pod repo的问题 http://blog.cocoachina.com/article/29127#0-tsina-1-76364-397232819ff9a47a7b7e80a40613cfe1
        用上边的链接, 解决了pod search搜不到snapkit的问题。
        814caae8520c:我用的是cocoapods安装方法 提示是找不到 'SnapKit', '~> 0.15.0'
        去掉, '~> 0.15.0' 的版本说明、 翻墙、等方法都是找不到
        pod search snapkit 也是搜不到正确的信息
      • 劉戦軍:很棒, 谢了
      • Azen:哇很棒!!
      • chenyu1520:没有放到 Github 上吗?
      • 517c8c0b74c8:你Github地址在哪里?
      • 戏精鸭鸭:还是没搞明白优先级和大于等于这些有什么实际作用,望解答。谢谢!
      • 一粒吗:感谢楼主
      • 3d021e52b4ba:如何要自适应各个屏幕的话,还是得要用“百分比”的方法来布局的把
        zZ爱吃菜:@普叶 此库,也是相对布局,设置好相对布局属性,不需要在意屏幕尺寸,代码版的autolayout
      • b5f05d9357e2:
        topSeparatorView.snp_makeConstraints { (make) -> Void in
        make.left.top.right.equalTo(0)
        make.height.equalTo(50)
        }
        topSeparatorView.backgroundColor = UIColor.greenColor()

        我这样uiview不显示是什么原因?
        b5f05d9357e2:@zZ爱吃菜 可是我怎么都显示不了,能看看我哪里写错了吗? 70行。 https://github.com/iScript/swift-project/blob/master/ySeed/StatusTopView.swift
        zZ爱吃菜:@袁克强 我测试了,没有问题,确定一下你的父容器是否显示,Snapkit位置 是相对 父容器 superview
      • zZ爱吃菜:整理很大程度就是为了给自己制作一个参考,喜欢我的就顺便看看,不求啥知名度 :grin:
      • Joy___:整理的真心棒,但是怎么提高自己的访问量,感觉检索的时候简书的曝光率不算太高
      • smalldu:感谢楼主费心整理
        zZ爱吃菜:@大石头布 :blush:

      本文标题:Swift编程(六):Snapkit的启示录

      本文链接:https://www.haomeiwen.com/subject/lxylhttx.html