LoginSignup
KAinone
@KAinone

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

UIButton をタップして遷移したいが落ちる

Q&AClosed

解決したいこと

1. HomeHeaderViewCellに設置したaccountButtonをタップしてMyAccountViewCotrollerへ遷移させたいのですが、アプリが落ちてしまいます。遷移の処理はHomeViewControllerにデリゲートしています。理由がわからないので教えてほしいです。アプリが落ちた時のデバッグを貼っておきます。コードは長すぎて見辛くなるので、Gitからご覧いただけると幸いです。

<デバッグ>

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'NSLayoutConstraint for <UIImageView: 0x1088595a0; frame = (0 0; 0 0); userInteractionEnabled = NO; image = <(null):0x0 (null) anonymous; (0 0)@0>; layer = <CALayer: 0x6000002d7c20>>: A constraint cannot be made between a leading/trailing attribute and a right/left attribute. Use leading/trailing for both or neither.'
*** First throw call stack:
(
	0   CoreFoundation                      0x000000018048d8a8 __exceptionPreprocess + 172
	1   libobjc.A.dylib                     0x000000018008409c objc_exception_throw + 56
	2   CoreAutoLayout                      0x00000001ca3c4c44 ResolveConstraintArguments + 940
	3   CoreAutoLayout                      0x00000001ca3c4cdc +[NSLayoutConstraint constraintWithItem:attribute:relatedBy:toItem:attribute:multiplier:constant:] + 88
	4   SnapKit                             0x0000000106e5ef44 $sSo18NSLayoutConstraintC4item9attribute9relatedBy6toItemAD10multiplier8constantAByp_So0A9AttributeVSo0A8RelationVypSgAJ12CoreGraphics7CGFloatVAPtcfCTO + 368
	5   SnapKit                             0x0000000106e5eb5c $s7SnapKit10ConstraintC4from2to8relation14sourceLocation5label10multiplier8constant8priorityAcA0C4ItemC_AmA0C8RelationOSS_SutSSSgAA0C16MultiplierTarget_pAA0c8ConstantP0_pAA0c8PriorityP0_ptcfc + 4	6   SnapKit                             0x0000000106e5da60 $s7SnapKit10ConstraintC4from2to8relation14sourceLocation5label10multiplier8constant8priorityAcA0C4ItemC_AmA0C8RelationOSS_SutSSSgAA0C16MultiplierTarget_pAA0c8ConstantP0_pAA0c8PriorityP0_ptcfC + 1	7   SnapKit                             0x0000000106e6fd9c $s7SnapKit21ConstraintDescriptionC10constraintAA0C0CSgvgAGyXEfU_ + 592
	8   SnapKit                             0x0000000106e6faa4 $s7SnapKit21ConstraintDescriptionC10constraintAA0C0CSgvg + 148
	9   SnapKit                             0x0000000106e749f0 $s7SnapKit15ConstraintMakerC18prepareConstraints4item7closureSayAA0C0CGAA06LayoutC4Item_p_yACXEtFZ + 388
	10  SnapKit                             0x0000000106e74bf8 $s7SnapKit15ConstraintMakerC15makeConstraints4item7closureyAA06LayoutC4Item_p_yACXEtFZ + 104
	11  SnapKit                             0x0000000106e7bb88 $s7SnapKit17ConstraintViewDSLV15makeConstraintsyyyAA0C5MakerCXEF + 96
	12  Ainone                              0x00000001040e591c $s6Ainone17MyAccountViewCellC13setupSubViewsyyF + 2524
	13  Ainone                              0x00000001040e1f90 $s6Ainone17MyAccountViewCellC5style15reuseIdentifierACSo07UITabledE5StyleV_SSSgtcfc + 1700
	14  Ainone                              0x00000001040e21e4 $s6Ainone17MyAccountViewCellC5style15reuseIdentifierACSo07UITabledE5StyleV_SSSgtcfcTo + 160
	15  UIKitCore                           0x00000001854d0028 -[UITableView _dequeueReusableViewOfType:withIdentifier:] + 416
	16  UIKitCore                           0x00000001854d0268 -[UITableView dequeueReusableCellWithIdentifier:] + 152
	17  Ainone                              0x000000010413c940 $s6Ainone23MyAccountViewControllerC05tableD0_12cellForRowAtSo07UITableD4CellCSo0kD0C_10Foundation9IndexPathVtF + 172
	18  Ainone                              0x000000010413cb24 $s6Ainone23MyAccountViewControllerC05tableD0_12cellForRowAtSo07UITableD4CellCSo0kD0C_10Foundation9IndexPathVtFTo + 136
	19  UIKitCore                           0x00000001854e4fc4 -[UITableView _createPreparedCellForGlobalRow:withIndexPath:willDisplay:] + 1376
	20  UIKitCore                           0x00000001854b8134 -[UITableView _updateVisibleCellsForRanges:createIfNecessary:] + 560
	21  UIKitCore                           0x00000001854b874c -[UITableView _updateVisibleCellsNow:] + 1112
	22  UIKitCore                           0x00000001854d253c -[UITableView layoutSubviews] + 144
	23  UIKitCore                           0x00000001857cdb1c -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 1492
	24  QuartzCore                          0x0000000189f6fdd4 _ZN2CA5Layer16layout_if_neededEPNS_11TransactionE + 440
	25  QuartzCore                          0x0000000189f7ab30 _ZN2CA5Layer28layout_and_display_if_neededEPNS_11TransactionE + 124
	26  QuartzCore                          0x0000000189e963bc _ZN2CA7Context18commit_transactionEPNS_11TransactionEdPd + 460
	27  QuartzCore                          0x0000000189ec5bf0 _ZN2CA11Transaction6commitEv + 652
	28  UIKitCore                           0x00000001852e2ec4 _afterCACommitHandler + 80
	29  CoreFoundation                      0x00000001803ed648 __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 32
	30  CoreFoundation                      0x00000001803e804c __CFRunLoopDoObservers + 528
	31  CoreFoundation                      0x00000001803e8504 __CFRunLoopRun + 968
	32  CoreFoundation                      0x00000001803e7d28 CFRunLoopRunSpecific + 572
	33  GraphicsServices                    0x000000018e7cdbc0 GSEventRunModal + 160
	34  UIKitCore                           0x00000001852bafdc -[UIApplication _run] + 868
	35  UIKitCore                           0x00000001852bec54 UIApplicationMain + 124
	36  UIKitCore                           0x0000000184780ab8 __swift_destroy_boxed_opaque_existential_1Tm + 12244
	37  Ainone                              0x000000010410da64 $sSo21UIApplicationDelegateP5UIKitE4mainyyFZ + 120
	38  Ainone                              0x000000010410d9dc $s6Ainone11AppDelegateC5$mainyyFZ + 44
	39  Ainone                              0x000000010410dae0 main + 28
	40  dyld                                0x00000001063e9558 start_sim + 20
	41  ???                                 0x0000000105dd20e0 0x0 + 4393345248
	42  ???                                 0xd36b000000000000 0x0 + 15234270164510834688
)
libc++abi: terminating due to uncaught exception of type NSException

2. accountButtonのレイアウトをlayoutSubviews()内に書いたのですが、角丸と画像の設定だけ反映されません。このメソッドを使うのが良くない気はしたのですが、headerLabelのレイアウトやaccountButtonの backgroundColor は反映されているので理由がわかりません。分かる方がいらっしゃいましたらご教授ください。

override func layoutSubviews() {
    
    self.backgroundColor = .clear
    
    headerLabel.text = "Home"
    headerLabel.font = UIFont.boldSystemFont(ofSize: 40)
    headerLabel.backgroundColor = .clear
    headerLabel.textAlignment = .left
    
    accountButton.layer.cornerRadius = accountButton.frame.height / 2 //これ
    accountButton.layer.masksToBounds = true
    accountButton.backgroundColor = .cyan
    accountButton.imageView?.contentMode = .scaleAspectFit
    accountButton.imageView?.image = UIImage(systemName: "person.fill") //これ
}
0

2Answer

これ
accountButton.layer.cornerRadius = accountButton.frame.height / 2 //これ

accountButton.layer.cornerRadius = accountButton.frame.size.height / 2 //これ
と思います。

これ
accountButton.imageView?.image = UIImage(systemName: "person.fill") //これ

accountButton.setImage(UIImage(named: "person.fill"), for: .normal)
と思います。

0

Comments

  1. @KAinone

    Questioner

    画像の設定は教えていただいた通り記述することで解決しました。

    角丸は念の為、accountButton.frame.size.height / 2 に修正しておきました。
    解決方法は @nak435 様からコメントいただきました。

    ご回答いただきありがとうございました!

1.落ちる原因

MyAccountViewCell.swiftsetupSubViews() にある、$0.trailing.equalTo(XXX.snp.left)の影響で、ことごとく落ちます。使い方を確認されたし。

MyAccountViewCell.swiftlayoutSubviews()で行っている初期化処理は、initに移動する。
layoutSubviews()は、setupSubViews()より後に呼ばれます。
他のViewControllerも同様。


2.accountButtonの外見の件

  • 角丸

この時点でaccountButton.frame.height0のため
(もちろんaccountButton.frame.size.height0
contentView.frame.heightを使えばよいのでは。

- accountButton.layer.cornerRadius = accountButton.frame.height / 2
+ accountButton.layer.cornerRadius = contentView.frame.height / 2
  • 画像

設定誤り

- accountButton.imageView?.image = UIImage(systemName: "person.fill")
+ accountButton.setImage(UIImage(systemName: "person.fill")!, for: .normal)
0

Comments

  1. @KAinone

    Questioner

    1.
    SnapKitに関してはこちらを参考にしました。
    centerX を基準に設置していたパーツの left に、後からレイアウトするパーツの trailing を合わせたくて、$0.trailing.equalTo(XXX.snp.left)と書きましたが、誤りとしては、left/leading, right/trailing を区別していなかったからでしょうか?
    もしくは、左上から順番にレイアウトしていないからでしょうか?

    対策として、$0.left.equalTo(XXX.snp.right)のように書けるよう、全ファイルのレイアウトを修正しましたが、やはり落ちてしまいます。

    MyAccountViewCell.swiftのlayoutSubviews()で行っている初期化処理

    ここに落ちる原因があったということをおっしゃってますか?


    2.
    画像に関しては完全にドジってました、、、

    角丸に関しては、教えていただいた通り記述したら出来ました。ありがとうございます!

    ただ、レイアウトを記述しているsetupSubViews()より後に呼ばれるlayoutSubviews()で frame の値が0なのは何故ですか?
    あと、今回は accountButton.frame.heightcontentView.frame.heightが同じなので上手くいきましたが、通常、cell でパーツを角丸にする(frameの値を取得したい)場合はどこで記述するのが良いですか?

  2. MyAccountViewCell.swiftのlayoutSubviews()で行っている初期化処理

    ここに落ちる原因があったということをおっしゃってますか?

    通常は、①インスタンスを生成、②各プロパティを設定、③親viewに追加、します(①②③は一連の処理)。
    インスタンスだけ生成し、何もプロパティを設定する前に、レイアウトの制約を付ける順番は、普通ではあり得ないので、もしかすると、落ちる原因になっていないとも言い切れません。


    ただ、レイアウトを記述しているsetupSubViews()より後に呼ばれるlayoutSubviews()で frame の値が0なのは何故ですか?

    accountButtonの初期化でframeを設定していないからだと思います。


    通常、cell でパーツを角丸にする(frameの値を取得したい)場合はどこで記述するのが良いですか?

    cellViewの場合は、親viewに当たるcontentViewのサイズが決まった後に呼び出されるはずなので、常にcontentViewを参照して問題ないはずです。


    snapKitの使い方は、調べてみないと分かりません。

  3. つい先ほどGitHubから取り込んだPJをビルドしてシミュレータで実行してみましたが、accountButtonボタンをクリックすると、下記スクショの場所で落ちました。
    理由はuidのnil参照です。 MyAccountViewController.swift#160

    scr1.png

    再度、シミュレータを起動すると、今度はサインアップ画面に遷移しましたが、下記スクショで示すエラーとなり、先に進めませんでした。

    scr2.png



    よって、↓この現象を確認することができませんでした。

    対策として、$0.left.equalTo(XXX.snp.right)のように書けるよう、全ファイルのレイアウトを修正しましたが、やはり落ちてしまいます。

  4. @KAinone

    Questioner

    ご指摘いただいた通りの順番でレイアウトしてみたのですが、レイヤーだけはやはりlayoutSubviews()に書く必要があるようです。(参照)

    角丸についてですが、他のCellではできていることを思い出し精査したところ、super.layoutSubviews()を書き忘れていただけという初歩的なミスでした、、、
    よって、snapKitで制約を付けてもframeの値を取得できるようです。


    取り込み・実行ありがとうございます。

    デバッグにcurrentUser != nilとあるようにログインした状態ではあると思うのですが、なぜuidがnilになってしまったかわかりますか?
    imageRef自体nilなのが原因であれば、エラーを起こさせない処理を教えていただきたいです。imageRefがオプショナル型ではないのでguard letif letは使えませんでした。

    サインアップができない理由は、同じメールアドレスがFirebaseのAuthenticationに存在しているからだと思います。時間が経たないと何故かログインしてしまう現象が起きる可能性はありますが、過去に作成した情報は消しておきますので次回立ち上げていただける際は、サインアップからお願いします。

    再度シミュレータを起動したときはWelcomeViewControllerを経由せず、直接サインアップ画面に遷移しましたか? WelcomeViewControllerが表示されたのであれば、おそらく何かのエラーで自動的にログアウトされただけなのでサインインなら進めたかもしれません。

    現状、uidは全てguard let uid = Auth.auth().currentUser?.uid else {return}に修正して対応しています。
    その状態でシミュレータを起動するとまた別のエラーが出ました。
    スクショとデバッグを貼っておくのでもし原因が分かりましたら教えていただけると幸いです。

    <スクショ>
    Screenshot 2023-11-26 at 2.23.32.png

    <デバッグ>

    *** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayM objectAtIndexedSubscript:]: index 0 beyond bounds for empty array'
    *** First throw call stack:
    (
    	0   CoreFoundation                      0x000000018048d8a8 __exceptionPreprocess + 172
    	1   libobjc.A.dylib                     0x000000018008409c objc_exception_throw + 56
    	2   CoreFoundation                      0x00000001803747d4 -[__NSArrayM removeAllObjects] + 0
    	3   UIKitCore                           0x0000000184c043e4 -[UISegmentedControl setTitle:forSegmentAtIndex:] + 56
    	4   Ainone                              0x00000001023951a8 $s6Ainone17MyAccountViewCellC14layoutSubviewsyyF + 4348
    	5   Ainone                              0x0000000102396794 $s6Ainone17MyAccountViewCellC14layoutSubviewsyyFTo + 36
    	6   UIKitCore                           0x00000001857cdb1c -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 1492
    	7   QuartzCore                          0x0000000189f6fdd4 _ZN2CA5Layer16layout_if_neededEPNS_11TransactionE + 440
    	8   UIKitCore                           0x00000001857bd178 -[UIView(Hierarchy) layoutBelowIfNeeded] + 304
    	9   UIKitCore                           0x00000001857c2cf4 +[UIView(Animation) performWithoutAnimation:] + 68
    	10  UIKitCore                           0x00000001854e5174 -[UITableView _createPreparedCellForGlobalRow:withIndexPath:willDisplay:] + 1808
    	11  UIKitCore                           0x00000001854b8134 -[UITableView _updateVisibleCellsForRanges:createIfNecessary:] + 560
    	12  UIKitCore                           0x00000001854b874c -[UITableView _updateVisibleCellsNow:] + 1112
    	13  UIKitCore                           0x00000001854d253c -[UITableView layoutSubviews] + 144
    	14  UIKitCore                           0x00000001857cdb1c -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 1492
    	15  QuartzCore                          0x0000000189f6fdd4 _ZN2CA5Layer16layout_if_neededEPNS_11TransactionE + 440
    	16  QuartzCore                          0x0000000189f7ab30 _ZN2CA5Layer28layout_and_display_if_neededEPNS_11TransactionE + 124
    	17  QuartzCore                          0x0000000189e963bc _ZN2CA7Context18commit_transactionEPNS_11TransactionEdPd + 460
    	18  QuartzCore                          0x0000000189ec5bf0 _ZN2CA11Transaction6commitEv + 652
    	19  UIKitCore                           0x00000001852e2ec4 _afterCACommitHandler + 80
    	20  CoreFoundation                      0x00000001803ed648 __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 32
    	21  CoreFoundation                      0x00000001803e804c __CFRunLoopDoObservers + 528
    	22  CoreFoundation                      0x00000001803e8504 __CFRunLoopRun + 968
    	23  CoreFoundation                      0x00000001803e7d28 CFRunLoopRunSpecific + 572
    	24  GraphicsServices                    0x000000018e7cdbc0 GSEventRunModal + 160
    	25  UIKitCore                           0x00000001852bafdc -[UIApplication _run] + 868
    	26  UIKitCore                           0x00000001852bec54 UIApplicationMain + 124
    	27  UIKitCore                           0x0000000184780ab8 __swift_destroy_boxed_opaque_existential_1Tm + 12244
    	28  Ainone                              0x00000001023be124 $sSo21UIApplicationDelegateP5UIKitE4mainyyFZ + 120
    	29  Ainone                              0x00000001023be09c $s6Ainone11AppDelegateC5$mainyyFZ + 44
    	30  Ainone                              0x00000001023be1a0 main + 28
    	31  dyld                                0x000000010414d558 start_sim + 20
    	32  ???                                 0x00000001043460e0 0x0 + 4365508832
    	33  ???                                 0x2b0e800000000000 0x0 + 3102557930793205760
    )
    libc++abi: terminating due to uncaught exception of type NSException
    
  5. その状態でシミュレータを起動するとまた別のエラーが出ました。
    スクショとデバッグを貼っておくのでもし原因が分かりましたら教えていただけると幸いです

    MyAccountViewCell.swift#145で落ちています。
    原因は、segmentedControlの初期化誤りです。segmentedControlのセグメント数はインスタンス生成時に設定しておくか、insertする必要があります。MyAccountViewCell.swift#145:146を次のように変更します。

    -        segmentedControl.setTitle("募集", forSegmentAt: 0)
    -        segmentedControl.setTitle("プロフィール", forSegmentAt: 1)
    +        segmentedControl.insertSegment(withTitle: "募集", at: 0, animated: false)
    +        segmentedControl.insertSegment(withTitle: "プロフィール", at: 1, animated: false)
    

    せっかくデバッグモードで実行しているのですから、Xcodeでのデバックの仕方を教えます。(今回、原因を突き止めた手順)(スクショはクリックすると拡大表示されます)

    # スクショ 説明
    1 scr1.png 赤のエラーメッセージを確認する。
    Thread 1: "*** -[__NSArrayM objectAtIndexedSubscript:]: index 0 beyond bounds for empty array"
    「Arrayがemptyで落ちた」と認識したが、何のarray?
    そこで、左側のスタックトレースに注目。(緑で囲ったところ)最後のメソッドがMyAccountViewCell.layoutSubviews()で、ここをクリックすると、該当するソースコードに移る
    2 scr2.png MyAccountViewCell.swiftの145行目segmentedControl.setTitle("募集", forSegmentAt: 0)の延長で落ちたことがわかる。
    (145の数字をクリックして)ここにブレークポイントを設定。一度、実行を停止し、再度起動する。
    3 scr4.png 止まりました。各プロパティをチェック。(左下を拡大したスクショで説明する)
    scr5.png
    1. セグメント数を確認
      p segmentedControl.numberOfSegmentsを入力。結果(Int) 0。セグメント数=0はおかしい。
    2. セグメント数=2を設定する。p segmentedControl.numberOfSegments=2を入力。結果error: <EXPR>:8:18: error: cannot assign to property: 'numberOfSegments' is a get-only property。numberOfSegmentsは参照のみで更新はできないプロパティ。
    3. なら、どこでセグメント数を設定するのか、APIを確認する。
    4. UISegmentedControlやネットを検索して、セグメント数を設定する方法を確認する。
      インスタンス生成時に設定するか、動的に設定するなら insertSegment / removeSegment で挿入/削除する。

    今回はinsertSegmentにしましたが、この2行を削除して、インスタンス生成時に設定
    let segmentedControl = UISegmentedControl(items: ["募集", "プロフィール"])でもよい。

    デバッガコマンド pは変数やプロパティを参照する。関数やメソッドを呼ぶことも可能。代入も可能。
    ブレークポイントで停止させ、変数の値を一時的に変更して処理続行などができる。


    上記を変更し再度シミュレータで実行すると、Welcomeが表示され、サインアップして、MyAccountに遷移しました。

    accountButtonボタンをクリックすると、今度は、MyAccountViewCell.swift#209let string = urlLabel.text!で落ちました。
    理由は、urlLabelにtextが未設定のため、nil参照です。

  6. @KAinone

    Questioner

    segmentedControlへのご指摘ありがとうございます。

    また、デバックの仕方を分かりやすくご丁寧に教えてくださり大変感謝しております。
    今後は教えていただいた方法で自己解決を目指します。
    ありがとうございました!

  7. お役に立てて 何よりです!

    もしよろしければ、一番最初の回答の下の♡マークをクリックして「いいね」をいただけると大変嬉しいです。

Your answer might help someone💌