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

写在前面(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,有点困!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,294评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,493评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,790评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,595评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,718评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,906评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,053评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,797评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,250评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,570评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,711评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,388评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,018评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,796评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,023评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,461评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,595评论 2 350

推荐阅读更多精彩内容