Swift編程(六):Snapkit的啟示錄

寫在前面(Github地址)

個人項目

個人站點:LN電影網
個人博客:L&N博客

歡迎大家關注我的個人博客:<a >博客地址</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閱讀 228,505評論 6 533
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,556評論 3 418
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,463評論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,009評論 1 312
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,778評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,218評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,281評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,436評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,969評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,795評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,993評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,537評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,229評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,659評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,917評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,687評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,990評論 2 374

推薦閱讀更多精彩內容