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对象即将销毁的时候 如果没有去布局的 就去执行布局

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

差不多就是这些了 想通了 实现起来还是挺简单的
更多请看源文件
demo地址

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

推荐阅读更多精彩内容