Swift學習->自己動手寫自動布局框架

前言

最近公司項目不忙, 在學swift, 雖然之前也了解過, 但是沒怎么寫, 所以基本上都忘光了, 作為一個程序員, 怎么能夠不追求新的藝術呢, 對, swift就是一門藝術, 一個禮拜左右的時間, 邊看邊練, 寫了三個文件

  • 網絡請求(對URLSession的封裝)
  • 圖片加載器(簡仿寫的SDWebImage)
  • 自動布局(類似Massory的調用方法 基于->NSLayoutConst.....)

下面針對自動布局的簡單概述一下
功能沒有那么SnapKit那么強大, 對我而言, 夠用足矣
調用的方法如下

imageView.makeConstraint { (maker) in
      maker.center.equalTo(self.view.cm_center)
      maker.width.height.equalTo(self.view).multiplier(0.5)
}

button.makeConstraint { (maker) in
      maker.centerX.equalTo(self.view)
      maker.top.equalTo(imageView.cm_bottom).constant(30)
      maker.height.equal(40)
      maker.width.equalTo(imageView)
}

上面代碼的效果如下

跟我想的結果一樣.png

差不多, 挺好的 , 嗯 , 很棒
當然了. 更新約束也有的, 就不演示了只不過是make換成了update 比較習慣了Massory的 所以就采用了相同的辦法

實現的Api基于分類(extension) 對UIView的extension

func makeConstraint(constraint: (FMConstraintMaker) -> ()) -> Void {
    self.isUpdateConstraint = false //是否是更新布局的標識
    constraint(FMConstraintMaker(currentView: self))
}
image.png
  • FMConstraintMaker(生成FMCMAttributes一個)
  • FMCMAttributes(保存要約束的屬性FMCMAttribute)
  • FMCMACalculate(根據屬性, 加上判斷得出NSLayoutConstraint)
  • FMCMATarget(相對誰的約束包含屬性)
  • FMCMAttribute(枚舉類型 所有的屬性類型)
  • FMCMRelation(枚舉類型 約束的關系類型)
  • FMCMVRelation(枚舉類型 當前控件與目標的控件的關系)

舉個例子

  button.makeConstraint { (maker) in
      maker.left.right.top.bottom.equalTo(self.view) // 四邊約束緊靠view的四邊
  }

// maker.left之后
// 其他的屬性都是一樣的  根據不同的屬性名傳入相應的約束類型, 返回一個FMCMAttributes
lazy var left: FMCMAttributes = {
     return FMCMAttributes(attribute: .left, current: self.currentMakerView)
 }()
// maker.left.right之后   .top.bottom  也是一樣的道理
/* 這里調用的就是FMCMAttributes的對象了  僅僅是將對應的
   屬性名標記加入到數組里  留著給后面去生成對應的布局 */
  lazy var right: FMCMAttributes = {
      self.attributes.append(.right)
      return self
  }()

再然后就到了equalTo這個方法 這個根據傳進來的參數做判斷生成FMCMACalculate

  @discardableResult    //這個標識是忽略這個方法的返回值沒有調用的警告
  func equalTo(_ target: Any) -> FMCMACalculate {
      return self.toCalculate(target: target, relation: .Equal)
  }

  private func toCalculate(target: Any, relation: FMCMRelation) -> FMCMACalculate {
      if let targetView = target as? UIView {
            return FMCMACalculate(current: self, targetView: targetView, relation: relation)
      }
      if let targetAttr = target as? FMCMATarget {
            return FMCMACalculate(current: self, target: targetAttr, relation: relation)
      }
      return FMCMACalculate(current: self, relation: relation)
  }

根據上傳的傳入的參數判斷

//    FMCMACalculate
 init(current: FMCMAttributes, targetView: UIView?, relation: FMCMRelation) {
      self.current = current    // FMCMAttributes實例對象
      self.targetView = targetView  // 目標的控件
      self.hasAttribute = false // 是否是帶有屬性的  如:self.view.cm_left
      self.target = nil  // 帶有屬性的目標
      self.relation = relation  // 約束的關系  相等大于小于
}

根據上面的代碼 到這里已經結束了
但是這并沒有去添加布局的代碼
添加布局的代碼在

var constant: (Float) -> Void {
    return {  (value) in
        self.hasConstant = true
        for attr in self.current.attributes {
            self.setAttribute(attribute: attr, constant: value)
        }
     }
 }

func setAttribute(attribute: FMCMAttribute, constant: Float) -> Void {
     let cons: NSLayoutConstraint = self.layoutConstraint(attribute: attribute, constant: constant) // 根據屬性與constant生成一個NSLayoutConstraint作為
    var change: UIView?
    switch self.viewrelation() { // 獲取當前的控件與目標的控件的關系
    case .FatherAndSon:
    change = self.current.current
    break
    case .SonAndFather:
    change = self.current.current.superview!
    break
    case .Equative:
    change = self.current.current.superview!
    break
    case .BeMySelf:
    change = self.current.current
    break
    default:
    change = nil
    break
    }
        
    if change != nil {
         if self.current.current.isUpdateConstraint { // 更新約束
              let consItems = change!.constraints
              if consItems.count == 0 {
                 return
              }
            
              var changeCon: NSLayoutConstraint?
              for con in consItems {
                   if con.firstItem as! NSObject == self.current.current && con.firstAttribute == attribute.ConstraintAttr() {
                        changeCon = con
                        break
                    } else {
                        continue
                    }
               }
                
               if changeCon != nil {// 如果找到舊的約束 就可以移除這個舊的約束  更新成當前最新的
                    change!.removeConstraint(changeCon!)
                    change!.addConstraint(cons)
                }
                
            } else { // 添加約束
                change!.addConstraint(cons)
            }
        }
    }

到這里已經差不多了 至于為什么沒有調用這個方法就去更新是因為在析構方法里加了一層判斷 當這個FMCMACalculate對象即將銷毀的時候 如果沒有去布局的 就去執(zhí)行布局

deinit {
    if !self.hasConstant {
         self.constant(0)
    }
}

差不多就是這些了 想通了 實現起來還是挺簡單的
更多請看源文件
demo地址

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末逼蒙,一起剝皮案震驚了整個濱河市从绘,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖僵井,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件陕截,死亡現場離奇詭異,居然都是意外死亡批什,警方通過查閱死者的電腦和手機农曲,發(fā)現死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來渊季,“玉大人朋蔫,你說我怎么就攤上這事∪春海” “怎么了?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵荷并,是天一觀的道長合砂。 經常有香客問我,道長源织,這世上最難降的妖魔是什么翩伪? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮谈息,結果婚禮上缘屹,老公的妹妹穿的比我還像新娘。我一直安慰自己侠仇,他們只是感情好轻姿,可當我...
    茶點故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著逻炊,像睡著了一般互亮。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上余素,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天豹休,我揣著相機與錄音,去河邊找鬼桨吊。 笑死威根,一個胖子當著我的面吹牛,可吹牛的內容都是我干的视乐。 我是一名探鬼主播洛搀,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼炊林!你這毒婦竟也來了姥卢?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎独榴,沒想到半個月后僧叉,有當地人在樹林里發(fā)現了一具尸體,經...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡棺榔,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年瓶堕,在試婚紗的時候發(fā)現自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片症歇。...
    茶點故事閱讀 38,161評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡郎笆,死狀恐怖,靈堂內的尸體忽然破棺而出忘晤,到底是詐尸還是另有隱情宛蚓,我是刑警寧澤,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布设塔,位于F島的核電站凄吏,受9級特大地震影響,放射性物質發(fā)生泄漏闰蛔。R本人自食惡果不足惜痕钢,卻給世界環(huán)境...
    茶點故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望序六。 院中可真熱鬧任连,春花似錦、人聲如沸例诀。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽余佃。三九已至暮刃,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間爆土,已是汗流浹背椭懊。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留步势,地道東北人氧猬。 一個月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像坏瘩,于是被迫代替她去往敵國和親盅抚。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,916評論 2 344

推薦閱讀更多精彩內容