有 我试图将视图代码与UIViewController分开,显示部分很好,但对用户交互没有任何反应。
例如, 我有我的LoginViewController
class LoginViewController: UIViewController,UITextFieldDelegate {
let loginView = LoginView(frame: .zero)
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(loginView)
loginView.centerInSuperview()//extension to center layouts
loginView.loginButton.addTarget(self, action: #selector(loginPressed(sender:)), for: .touchUpInside)
}
@objc func loginPressed(sender:UIButton){
print("login")
}
}
LoginView类
class LoginView: UIView {
fileprivate let containerWidth:CGFloat = 250
fileprivate let contentWidth:CGFloat = 240
let containerView:UIView={
let v = UIView()
v.backgroundColor = .white
v.layer.cornerRadius = 8
return v
}()
let passkeyInput:UITextField = {
let tf = UITextField(frame: .zero)
tf.placeholder = "PASSKEY"
tf.textAlignment = .center
tf.anchor( size: CGSize(width: 240, height: 0))
tf.isSecureTextEntry = true
return tf
}()
let loginButton:UIButton={
let button = UIButton()
button.backgroundColor = .red
button.setTitle("LOGIN", for: .normal)
button.anchor( size: CGSize(width: 240, height: 0))
button.layer.cornerRadius = 8
return button
}()
func setupView() {
let stackView = UIStackView(arrangedSubviews: [passkeyInput,loginButton])
stackView.alignment = .center
stackView.distribution = .equalSpacing
stackView.axis = .vertical
stackView.spacing = 20
stackView.isLayoutMarginsRelativeArrangement = true
stackView.layoutMargins = UIEdgeInsets(top: 10, left: 5, bottom: 10, right: 5)
addSubview(containerView)
containerView.addSubview(stackView)
containerView.anchor(size: CGSize(width: containerWidth, height: 0))//extension to layout
stackView.fillSuperview()//extension to layout
containerView.centerInSuperview()//extension to layout
}
override init(frame: CGRect) {
super.init(frame: frame)
setupView()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setupView()
}
}
我原本希望在单击loginButton时看到“登录”,但是由于某种原因,这没有发生。
我尝试了一些不同的事情:
因此,如果我将所有视图代码(LoginView中的代码)放在UIViewController旁边,则可以毫无问题地看到预期的结果,但是这没有意义-尝试将视图和viewcontroller分开
如果我在ViewController中更改代码, 从添加为子视图中
view.addSubview(loginView)
替换现有的默认视图,
view = loginView
它适用于这种情况,但我并不总是希望替换视图,有时(大多数时候)需要添加子视图
我试图在这里搜索类似的问题,但没有成功, 请帮助指出我做错了什么地方。
谢谢。
更新: 这是我使用的布局扩展名,仍然没有弄清楚是什么原因引起的。
struct AnchoredConstraints {
var top, leading, bottom, trailing, width, height: NSLayoutConstraint?
}
extension UIView {
@discardableResult
func anchor(top: NSLayoutYAxisAnchor? = nil, leading: NSLayoutXAxisAnchor? = nil, bottom: NSLayoutYAxisAnchor? = nil, trailing: NSLayoutXAxisAnchor? = nil, padding: UIEdgeInsets = .zero, size: CGSize = .zero) -> AnchoredConstraints {
translatesAutoresizingMaskIntoConstraints = false
var anchoredConstraints = AnchoredConstraints()
if let top = top {
anchoredConstraints.top = topAnchor.constraint(equalTo: top, constant: padding.top)
}
if let leading = leading {
anchoredConstraints.leading = leadingAnchor.constraint(equalTo: leading, constant: padding.left)
}
if let bottom = bottom {
anchoredConstraints.bottom = bottomAnchor.constraint(equalTo: bottom, constant: -padding.bottom)
}
if let trailing = trailing {
anchoredConstraints.trailing = trailingAnchor.constraint(equalTo: trailing, constant: -padding.right)
}
if size.width != 0 {
anchoredConstraints.width = widthAnchor.constraint(equalToConstant: size.width)
}
if size.height != 0 {
anchoredConstraints.height = heightAnchor.constraint(equalToConstant: size.height)
}
[anchoredConstraints.top, anchoredConstraints.leading, anchoredConstraints.bottom, anchoredConstraints.trailing, anchoredConstraints.width, anchoredConstraints.height].forEach{ $0?.isActive = true }
return anchoredConstraints
}
func fillSuperview(padding: UIEdgeInsets = .zero) {
translatesAutoresizingMaskIntoConstraints = false
if let superviewTopAnchor = superview?.topAnchor {
topAnchor.constraint(equalTo: superviewTopAnchor, constant: padding.top).isActive = true
}
if let superviewBottomAnchor = superview?.bottomAnchor {
bottomAnchor.constraint(equalTo: superviewBottomAnchor, constant: -padding.bottom).isActive = true
}
if let superviewLeadingAnchor = superview?.leadingAnchor {
leadingAnchor.constraint(equalTo: superviewLeadingAnchor, constant: padding.left).isActive = true
}
if let superviewTrailingAnchor = superview?.trailingAnchor {
trailingAnchor.constraint(equalTo: superviewTrailingAnchor, constant: -padding.right).isActive = true
}
}
func centerInSuperview(size: CGSize = .zero) {
translatesAutoresizingMaskIntoConstraints = false
if let superviewCenterXAnchor = superview?.centerXAnchor {
centerXAnchor.constraint(equalTo: superviewCenterXAnchor).isActive = true
}
if let superviewCenterYAnchor = superview?.centerYAnchor {
centerYAnchor.constraint(equalTo: superviewCenterYAnchor).isActive = true
}
if size.width != 0 {
widthAnchor.constraint(equalToConstant: size.width).isActive = true
}
if size.height != 0 {
heightAnchor.constraint(equalToConstant: size.height).isActive = true
}
}
}
答案 0 :(得分:0)
由于未设置loginView
的框架,因此按钮不会触发触摸事件。您只能使用loginView.centerInSuperview()
来定义其位置。
在LoginViewController
的{{1}}方法中,添加以下代码,它应该可以工作:
viewDidLoad()
(或其他框架定义)
使用loginView.fillSuperview()
时,view = loginView
设置在其他位置,这就是它起作用的原因。