最近在用Swift下的SnapKit写一个登录注册界面,写完调试时出现了一个奇葩的问题,具体是这样:
登录的placeholder明显在后面,而密码的则无问题。我仔细对比了两个创建输入框的代码:
lazy var usernameLabel :ROBaseInputView = {
var usernameLabel = ROBaseInputView.init(title: "用户名", placeholder: "请输入用户名")
usernameLabel.addRule(rule: { (object) -> (Bool, String, AnyObject) in
guard let text = (object as! ROBaseInputView).textfield.text else{ return (false, "请输入用户名", object) }
if text.characters.count < 3 {
return (false, "用户名必须大于3个字母或数字", object)
}
let rx = "[A-Z0-9a-z]{4,10}"
return ((text =~ rx), "用户名必须为数字或字母", object)
})
return usernameLabel
}()
lazy var passwordLabel :ROBaseInputView = {
var passwordLabel = ROBaseInputView.init(title: "密码", placeholder: "请输入密码")
passwordLabel.textfield.isSecureTextEntry = true
passwordLabel.addRule(rule: { (object) -> (Bool, String, AnyObject) in
guard let text = (object as! ROBaseInputView).textfield.text else{ return (false, "请输入密码", object) }
if text.characters.count < 6 {
return (false, "密码必须大于6个字母或数字", object)
}
let rx = "[A-Z0-9a-z]{6,10}"
return ((text =~ rx), "密码必须为数字或字母", object)
})
return passwordLabel
}()
这明明是一毛一样好不好,完全让我彻底懵了逼,我将无关的代码删除,只是保持这两个InputView的存在,发现问题依旧,我只能将passwordLabel的布局也依赖于icon图片(usernameLabel的布局是依赖于icon图片,usernameLabel和passwordLabel仅仅在此处不同),这时就出现了这个问题了,我发现,只要在相对布局中引用ImageVIew,那就有问题,对Self.view相对布局则没有问题!
我天真的以为,这是Snapkit的bug,故更新SnapKit.
问题依旧!怎么办,我也很绝望啊。重新review代码,这是布局图:
这是ROBaseInputView的代码内部空间布局的关键一段。
self.addSubview(textfield)
self.addSubview(title)
title.snp.makeConstraints { (make) in
make.left.centerY.equalTo(self)
}
textfield.snp.makeConstraints { (make) in
make.left.equalTo(title.snp.right).offset(15)
make.right.bottom.equalTo(self)
make.top.equalTo(self).offset(5)
}
我的想法是,title可以根据前面的名字长短自动伸缩,而textfield只要接在title的后面并且衍生到最后面就可以了。看似这个想法很好,但是,title和textfield的布局完全没有指定width,这就造成了之前的问题,Snapkit可以随机(或者是依据参考的对象来确定)指定两个控件的分界线!
这居然是个随机bug,但是看起来就不是那么一回事啊。。。
解决办法想必大家都应该知道了,就是利用布局的优先级。将它在创建的时候就确定一个低优先级的布局,指定宽度为1,这样子textfield就向前贪婪布局,而由于之后再指定字体的宽度,这又是一个高优先级的操作,所以就只会把textfield向后推动可容纳字体的宽度,这样就可以解决了。实际上就是一行代码:
title.snp.makeConstraints { (make) in
make.left.centerY.equalTo(self)
make.width.equalTo(1).priority(100)
}
看来我写代码还太心浮气躁了。