質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

Q&A

解決済

1回答

1896閲覧

swiftでカスタムviewを追加したviewをdismissすると例外発生

matsuda2

総合スコア29

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

0グッド

1クリップ

投稿2019/12/04 04:29

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) }

}

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

MasatoUchida

2019/12/04 06:16

読みづらいので質問とは関係ありませんが、markdown記法で修正して頂けると幸いです。
guest

回答1

0

ベストアンサー

addSubviewしていないView(dropView)に対して制約を付けようとして落ちています。
didMoveToSuperview()はremove時にも呼ばれます。

投稿2019/12/05 02:03

fuzzball

総合スコア16731

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

matsuda2

2019/12/06 04:04

ありがとうございます。didMoveToSuperviewを以下のコードに変更して解決しました。 override func didMoveToSuperview() { if let sview = self.superview { sview.addSubview(dropView) sview.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) } }
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問