自从水果发布了5代,苹果为了适配多种屏幕尺寸,搞出了一个所谓的AutoLayout来解决问题,iOS程序员们今后走上了苦逼的适配路。git
“适配”自己其实并非一个头疼的事情,对于4-6寸的手机来讲,只要制定一套规则,就不会有太大的问题。可是令我痛苦的部分在于——iOS的 Constraints 和 VFL。程序员
这里借用iOS开源项目 Masonry 的描述,假如咱们要让一个view在superview里居中,而后每条边留出10像素的空白,代码是这样写的:github
UIEdgeInsets padding = UIEdgeInsetsMake(10, 10, 10, 10); [superview addConstraints:@[ //view1 constraints [NSLayoutConstraint constraintWithItem:view1 attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:superview attribute:NSLayoutAttributeTop multiplier:1.0 constant:padding.top], [NSLayoutConstraint constraintWithItem:view1 attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:superview attribute:NSLayoutAttributeLeft multiplier:1.0 constant:padding.left], [NSLayoutConstraint constraintWithItem:view1 attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:superview attribute:NSLayoutAttributeBottom multiplier:1.0 constant:-padding.bottom], [NSLayoutConstraint constraintWithItem:view1 attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:superview attribute:NSLayoutAttributeRight multiplier:1 constant:-padding.right], ]];
若是你刚刚接触iOS开发,你可能认为这并非什么问题。可是让咱们作个对比,在web开发中,应该怎么写呢?web
#view{margin:10px;}
一行代码搞定问题,CSS是世界上最伟大的排版引擎,没有之一。明明很简单的事情,为何放到iOS上,居然变得这么这么这么复杂了?swift
而后苹果又搞出了VFL,网上对此描述最多的是“象形文字”,虽然它真的真的改善了咱们建立constraints的方式,让这一切变得更快更方便,可是对于下面这段代码,我仍然是不满的。less
constraints += NSLayoutConstraint.constraintsWithVisualFormat("V:[trackBtn]-15-[filterBtn(40)]-15-|", options: NSLayoutFormatOptions.AlignAllRight, metrics: nil, views: views) constraints += NSLayoutConstraint.constraintsWithVisualFormat("[trackBtn]-15-|", options: NSLayoutFormatOptions.AlignmentMask, metrics: nil, views: views) constraints += NSLayoutConstraint.constraintsWithVisualFormat("|-15-[filterBtn]-15-|", options: NSLayoutFormatOptions.AlignmentMask, metrics: nil, views: views)
莫名其妙的options,metrics和views参数的组合,长成狗同样的函数名。并且即便是有了VFL,咱们仍是离不开 constraints ,VFL并无真的知足咱们的全部需求,好比你看看 这个需求。函数
那么,咱们是否是只能一声叹气,说,iOS的世界就这样了呢?动画
NO!!!咱们有Masonry和SnapKit!!!spa
SnapKit是Masonry的Swift版,项目发布至今大约1年的时间,已经在github上有两千多个star,固然了,这其中也少不了"他爹"Masonry给他打的那些广告。code
若是你还记得你在 StoryBoard 里面拉的那些线条,那你也必定记得其中 constriants 的表示方法:
SnapKit所作的就是这样一件事——让你这样写 constraints。
咱们看看文章最顶部的那个需求用 SnapKit 如何实现:
view1.snp_makeConstraints { (make) -> Void in make.top.equalTo(superview).offset(10) make.left.equalTo(superview).offset(10) make.bottom.equalTo(superview).offset(-10) make.right.equalTo(superview).offset(-10) }
对!就是这么简单!还能够更简单!!
view1.snp_makeConstraints { (make) -> Void in make.edges.equalTo(superview).insets(UIEdgeInsetsMake(10, 10, 10, 10)) }
来,请跟我一块儿大叫三声爽!
爽!
爽!
叫完以后咱们继续看还能怎么爽:
// 不仅是相等哦,大于等于也是有的 make.centerX.lessThanOrEqualTo(view2.snp_left) make.left.greaterThanOrEqualTo(label.snp_left) // 不止是边缘哦,宽度高度也是有的 // width >= 200 && width <= 400 make.width.greaterThanOrEqualTo(200) make.width.lessThanOrEqualTo(400) // 其实能够简单点,一行搞定一个size make.size.equalTo(CGSizeMake(50, 100)) // 链式操做,优先级想怎么搞就怎么搞 make.left.greaterThanOrEqualTo(label.snp_left).priorityLow() // 妈妈不再担忧我不会排版了,什么向左5像素向下10像素我一行代码就搞定啦 make.center.equalTo(superview).offset(CGPointMake(-5, 10))
作起动画来也是一把好手!
view1.snp_makeConstraints { (make) -> Void in self.topConstraint = make.top.equalTo(superview).offset(padding.top).constraint make.left.equalTo(superview).offset(padding.left) } // then later you can call self.topConstraint.uninstall() // or if you want to update the constraint self.topConstraint.updateOffset(5) // 也能够用 snp_updateConstraints 实现上述需求
若是你用CocoaPods,那么Podfile你懂的:
pod 'SnapKit', :git => 'https://github.com/SnapKit/SnapKit.git', :branch => 'swift-2.0'
若是你用Carthege……这个我没用过我就不瞎说了……
总之呢,不用CocoaPods的朋友能够去 这里 下载,至于怎么弄进项目我就无论了(好好滴干吗不用CocoaPods..)
我用SnapKit作了下面这个界面:
体验以后发现,其实用SnapKit和原生constraints的代码行数差很少,可是每一行从原来的极为冗长的一坨东西,变成了很容易阅读和维护的短小精干的代码,代码像下面这样优雅,这即是SnapKit最大的做用。
mapView.snp_makeConstraints { (make) -> Void in make.edges.equalTo(view) } locateImage.snp_makeConstraints { (make) -> Void in let topHeight = navigationController!.navigationBar.frame.height + UIApplication.sharedApplication().statusBarFrame.height make.centerX.equalTo(mapView) make.bottom.equalTo(mapView.snp_centerY).offset(topHeight/2) } filterBtn.snp_makeConstraints { (make) -> Void in make.left.equalTo(mapView).offset(15) make.right.equalTo(mapView).offset(-15) make.height.equalTo(40) make.bottom.equalTo(mapView).offset(-15) } trackBtn.snp_makeConstraints { (make) -> Void in make.bottom.equalTo(filterBtn.snp_top).offset(-15) make.right.equalTo(mapView).offset(-15) }