swiftにカスタムview(stateBtn)をaddsubviewして親viewをdismissするとappdelegateでsigabortが発生します。
UserApp[2337:59789] *** Terminating app due to uncaught exception 'NSGenericException', reason: 'Unable to activate constraint with anchors <NSLayoutYAxisAnchor:0x600003e25640 "UserApp.dropDownView:0x7fd7a81dde80.top"> and <NSLayoutYAxisAnchor:0x600003e24340 "UserApp.dropDownBtn:0x7fd7a81dd3a0'神奈川県'.bottom"> because they have no common ancestor. Does the constraint or its anchors reference items in different view hierarchies? That's illegal.'
*** First throw call stack:
省略
libc++abi.dylib: terminating with uncaught exception of type NSException
が発生します。
stateBtnをaddsubviewせずにdismissすると正常に親viewが閉じられます。
この事象を解決する方法はないでしょうか?
開発環境はxcode10.2.1,swift 5.0.1です。
ソースは以下のとおりです。
//// UserEditViewController.swift //////////////////////////////
class UserEditViewController: UIViewController {
var stateBtn: dropDownBtn? = nil
override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view. stateBtn = dropDownBtn() stateBtn = dropDownBtn.init(frame: CGRect(x: 0, y: 0, width: 0, height: 0)) if let stbtn = self.stateBtn {
stbtn.translatesAutoresizingMaskIntoConstraints = false
self.view.addSubview(stbtn) stbtn.leftAnchor.constraint(equalTo: self.view.leftAnchor, constant: CGFloat(66)).isActive = true stbtn.topAnchor.constraint(equalTo: self.view.topAnchor, constant: CGFloat(373)).isActive = true stbtn.widthAnchor.constraint(equalToConstant: 300).isActive = true stbtn.heightAnchor.constraint(equalToConstant: 30).isActive = true } } @IBAction func backTapped(_ sender: Any) { self.dismiss(animated: true, completion: nil) }
//// DropDownList.swift ////////////////////////////////////////////
import UIKit
protocol dropDownProtocol {
func dropDownPressed(string : String)
}
class dropDownBtn: UIButton, dropDownProtocol {
func dropDownPressed(string: String) { self.setTitle(string, for: .normal) self.dismissDropDown() } var dropView = dropDownView() var height = NSLayoutConstraint() override init(frame: CGRect) { super.init(frame: frame) self.backgroundColor = UIColor.darkGray dropView = dropDownView.init(frame: CGRect.init(x: 0, y: 0, width: 0, height: 0)) dropView.delegate = self dropView.translatesAutoresizingMaskIntoConstraints = false } override func didMoveToSuperview() { self.superview?.addSubview(dropView) self.superview?.bringSubviewToFront(dropView) dropView.topAnchor.constraint(equalTo: self.bottomAnchor).isActive = true dropView.centerXAnchor.constraint(equalTo: self.centerXAnchor).isActive = true dropView.widthAnchor.constraint(equalTo: self.widthAnchor).isActive = true height = dropView.heightAnchor.constraint(equalToConstant: 0) } var isOpen = false override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { if isOpen == false { isOpen = true NSLayoutConstraint.deactivate([self.height]) if self.dropView.tableView.contentSize.height > 150 { self.height.constant = 150 } else { self.height.constant = self.dropView.tableView.contentSize.height } NSLayoutConstraint.activate([self.height]) UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 0.5, initialSpringVelocity: 0.5, options: .curveEaseInOut, animations: { self.dropView.layoutIfNeeded() self.dropView.center.y += self.dropView.frame.height / 2 }, completion: nil) } else { isOpen = false NSLayoutConstraint.deactivate([self.height]) self.height.constant = 0 NSLayoutConstraint.activate([self.height]) UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 0.5, initialSpringVelocity: 0.5, options: .curveEaseInOut, animations: { self.dropView.center.y -= self.dropView.frame.height / 2 self.dropView.layoutIfNeeded() }, completion: nil) } } func dismissDropDown() { isOpen = false NSLayoutConstraint.deactivate([self.height]) self.height.constant = 0 NSLayoutConstraint.activate([self.height]) UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 0.5, initialSpringVelocity: 0.5, options: .curveEaseInOut, animations: { self.dropView.center.y -= self.dropView.frame.height / 2 self.dropView.layoutIfNeeded() }, completion: nil) } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") }
}
class dropDownView: UIView, UITableViewDelegate, UITableViewDataSource {
var dropDownOptions = [String]() var tableView = UITableView() var delegate : dropDownProtocol! override init(frame: CGRect) { super.init(frame: frame) tableView.backgroundColor = UIColor.darkGray self.backgroundColor = UIColor.darkGray tableView.delegate = self tableView.dataSource = self tableView.translatesAutoresizingMaskIntoConstraints = false self.addSubview(tableView) tableView.leftAnchor.constraint(equalTo: self.leftAnchor).isActive = true tableView.rightAnchor.constraint(equalTo: self.rightAnchor).isActive = true tableView.topAnchor.constraint(equalTo: self.topAnchor).isActive = true tableView.bottomAnchor.constraint(equalTo: self.bottomAnchor).isActive = true } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } func numberOfSections(in tableView: UITableView) -> Int { return 1 } func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return dropDownOptions.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = UITableViewCell() cell.textLabel?.text = dropDownOptions[indexPath.row] cell.backgroundColor = UIColor.lightGray return cell } func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { self.delegate.dropDownPressed(string: dropDownOptions[indexPath.row]) self.tableView.deselectRow(at: indexPath, animated: true) }
}
回答1件
あなたの回答
tips
プレビュー