前提・実現したいこと
初めて投稿いたします、いざ氏と申します。
当方autoLayoutがよく理解できておらず、皆様のお力をお借りしたいと思い投稿いたしました。
現在テスト的に以下の動作をするアプリを作っています。
<テスト環境>
iOS12.1.4
xcode 10.1
swift 4.2
<動作内容>
1:2つのビューがある(添付コードでは緑、赤)
2:タップすると画面一杯のサイズに拡大される
3:閉じるを押すと、元のサイズに戻る
4:ビュー拡大時にスワイプすると、拡大ビューは横移動(この時もう一方を移動前に拡大)、
下からもう一方が出てくるようにしています。
発生している問題・エラーメッセージ
4の閉じるを押しても画面が縮小されず、以下のエラーが表示されます。
拡大中の制約が重複していることが原因でエラーが表示されていると思われます。
エラーメッセージ
2019-02-25 11:44:16.082031+0900 PLTestAutoLayout_190222[1100:121133] [LayoutConstraints] Unable to simultaneously satisfy constraints.
Probably at least one of the constraints in the following list is one you don't want.
Try this:
(1) look at each constraint and try to figure out which you don't expect;
(2) find the code that added the unwanted constraint or constraints and fix it.
(
"<NSLayoutConstraint:0x28370e490 V:|-(0)-[PLTestAutoLayout_190222.CustomView:0x10181d3d0] (active, names: '|':UIView:0x101821d00 )>",
"<NSLayoutConstraint:0x283736800 V:|-(200)-[PLTestAutoLayout_190222.CustomView:0x10181d3d0] (active, names: '|':UIView:0x101821d00 )>"
)
該当のソースコード
質問の文字数が10000文字までであったため、CustomViewクラスの実装は省略致します。
import UIKit
class ViewController: UIViewController, CustomViewDelegate {
// 赤ビュー lazy var red: CustomView = CustomView.init(frame: CGRect.zero) // 緑ビュー var green: CustomView = CustomView.init(frame: CGRect.zero) // 保持用 var saveCon : [NSLayoutConstraint] = [] var conGreen : [NSLayoutConstraint] = [] // 緑ビュー制約 var conRed : [NSLayoutConstraint] = [] // 赤ビュー制約 // 拡大 func scaleUp(upView: CustomView) { // 最前面に移動 self.view.bringSubviewToFront(upView) // 赤ビューの制約無効 if upView == red{ NSLayoutConstraint.deactivate(conRed) } // 緑ビューの制約無効 else{ NSLayoutConstraint.deactivate(conGreen) } // 新規制約生成(画面いっぱいに広げる)、有効にする let constA = upView.topAnchor.constraint(equalTo: view.topAnchor) let constB = upView.bottomAnchor.constraint(equalTo: view.bottomAnchor) let constC = upView.leadingAnchor.constraint(equalTo: view.leadingAnchor) let constD = upView.trailingAnchor.constraint(equalTo: view.trailingAnchor) // 作成した制約保持(縮小時に使用するため) saveCon = [constA, constB, constC, constD] NSLayoutConstraint.activate(saveCon) UIView.animate(withDuration: 0.3, animations: { self.view.layoutIfNeeded() }, completion: { finished in }) } // 縮小 func scaleDown(downView: CustomView) { // 保持していた制約を使用して無効にする NSLayoutConstraint.deactivate(saveCon) // 赤ビューの元々の制約有効 if downView == red{ NSLayoutConstraint.activate(conRed) } // 緑ビューの元々の制約有効 else{ NSLayoutConstraint.activate(conGreen) } UIView.animate(withDuration: 0.3, animations: { self.view.layoutIfNeeded() }, completion: { finished in }) } func swipeDirection(sender: UISwipeGestureRecognizer){ let notSwipeView = sender.view != red ? red : green // スワイプされていないビュー:1つ後ろにinsertする //self.view.insertSubview(notSwipeView, at: 0) // スワイプされていないビュー:現在の制約無効 if notSwipeView == red{ NSLayoutConstraint.deactivate(conRed) } else{ NSLayoutConstraint.deactivate(conGreen) } // スワイプされていないビュー:制約有効(拡大) let conNotSwipe1 = notSwipeView.topAnchor.constraint(equalTo: view.topAnchor) let conNotSwipe2 = notSwipeView.bottomAnchor.constraint(equalTo: view.bottomAnchor) let conNotSwipe3 = notSwipeView.leadingAnchor.constraint(equalTo: view.leadingAnchor) let conNotSwipe4 = notSwipeView.trailingAnchor.constraint(equalTo: view.trailingAnchor) NSLayoutConstraint.activate([conNotSwipe1, conNotSwipe2, conNotSwipe3, conNotSwipe4]) DispatchQueue.main.asyncAfter(deadline: .now() + 0.01) { // スワイプビュー:制約無効(拡大) NSLayoutConstraint.deactivate(self.saveCon) // スワイプされていないビュー:制約保持(このビューを縮小するときに使用する) self.saveCon = [conNotSwipe1, conNotSwipe2, conNotSwipe3, conNotSwipe4] // 移動処理 var currentConst : [NSLayoutConstraint]? // 左にスワイプ if sender.direction == UISwipeGestureRecognizer.Direction.left{ let conMove1 = sender.view!.topAnchor.constraint(equalTo: self.view.topAnchor) let conMove2 = sender.view!.bottomAnchor.constraint(equalTo: self.view.bottomAnchor) let conMove3 = sender.view!.widthAnchor.constraint(equalToConstant: 768) let conMove4 = sender.view!.trailingAnchor.constraint(equalTo: self.view.leadingAnchor) currentConst = [conMove1, conMove2, conMove3, conMove4] } // 右にスワイプ else if sender.direction == UISwipeGestureRecognizer.Direction.right{ let conMove1 = sender.view!.topAnchor.constraint(equalTo: self.view.topAnchor) let conMove2 = sender.view!.bottomAnchor.constraint(equalTo: self.view.bottomAnchor) let conMove3 = sender.view!.widthAnchor.constraint(equalToConstant: 768) let conMove4 = sender.view!.leadingAnchor.constraint(equalTo: self.view.trailingAnchor) currentConst = [conMove1, conMove2, conMove3, conMove4] } // スワイプビュー:制約有効(移動) NSLayoutConstraint.activate(currentConst!) UIView.animate(withDuration: 0.3, animations: { self.view.layoutIfNeeded() }, completion: { finished in // スワイプビュー:制約無効 NSLayoutConstraint.deactivate(currentConst!) // スワイプビュー:元々の制約有効(縮小) if sender.view! == self.red{ NSLayoutConstraint.activate(self.conRed) } else{ NSLayoutConstraint.activate(self.conGreen) } // スワイプビュー:後ろに移動する self.view.insertSubview(sender.view!, at: 0) }) } } override func viewDidLoad() { super.viewDidLoad() // 赤ビュー red.backgroundColor = UIColor.red red.myDelegate = self view .addSubview(red) red.translatesAutoresizingMaskIntoConstraints = false let constRedA = red.topAnchor.constraint(equalTo: view.topAnchor, constant: 200) let constRedB = red.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 100) let constRedC = red.widthAnchor.constraint(equalToConstant: 200) let constRedD = red.heightAnchor.constraint(equalToConstant: 200) conRed = [constRedA, constRedB, constRedC, constRedD] // 赤ビューの初期制約セット NSLayoutConstraint.activate(conRed) // 緑ビュー green.backgroundColor = UIColor.green green.myDelegate = self view .addSubview(green) green.translatesAutoresizingMaskIntoConstraints = false let constGreenA = green.topAnchor.constraint(equalTo: view.topAnchor, constant: 200) let constGreenB = green.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -100) let constGreenC = green.widthAnchor.constraint(equalToConstant: 200) let constGreenD = green.heightAnchor.constraint(equalToConstant: 200) conGreen = [constGreenA, constGreenB, constGreenC, constGreenD] // 緑ビューの初期制約セット NSLayoutConstraint.activate(conGreen) } override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() }
}
補足情報(FW/ツールのバージョンなど)
iOS12.1.4
xcode 10.1
swift 4.2

回答1件
あなたの回答
tips
プレビュー