115

XCode 4.5 と iOS 6 を使用して、カスタム セルを含む単純なテーブル ビューを備えたアプリを開発しています。iOS 5 以下でこれを 100 回実行しましたが、何らかの理由で新しい autoLayout システムが多くの問題を引き起こしています。

IB でテーブル ビューとプロトタイプ セルをセットアップし、サブビューを追加して IBOutlets として接続し、デリゲートとデータソースをセットアップしました。ただし、最初のセルがからフェッチされるたびにcellForRowAtIndexPath、次のエラーが発生します。

*** -[ShopCell layoutSublayersOfLayer:]、/SourceCache/UIKit_Sim/UIKit-2372/UIView.m:5776 でのアサーションの失敗

*** キャッチされない例外 'NSInternalInconsistencyException' が原因でアプリを終了します。理由: '-layoutSubviews の実行後も自動レイアウトが必要です。-layoutSubviews の ShopCell の実装では、super を呼び出す必要があります。

サブクラス化されたセル (ShopCell) に -layoutSubviews メソッドを実装していません。それを実行しようとしてスーパー コールを追加しても、同じエラーが発生します。IB のセルからサブビューを削除し、それを標準の UITableViewCell に変更すると、すべてが期待どおりに機能しますが、もちろんセルにはデータがありません。

欠けている単純なものがあることはほぼ確実ですが、間違ったことを示唆するドキュメントやガイドが見つかりません。どんな助けでも大歓迎です。

編集: IBでUITableViewCellに変更して、すべてのサブビューをそのままにしてみましたが、それでも同じエラーです。

4

31 に答える 31

57

コードに制約を手動で追加しているときに、同じ問題が発生しました。コードでは、次のことを行っていました。

{
    [self setTranslatesAutoresizingMaskIntoConstraints:YES];
    [self addSubview:someView];
    [self addSubview:someOtherView];
    [self addConstraint:...];
}

仮説

私が知る限り、問題は、を無効にすると、 UITableViewCell が自動レイアウトの使用を開始し、の基礎となる実装がスーパーを呼び出さないtranslatesAutoresizingMaskIntoConstraintsため、当然失敗することです。layoutSublayersForLayerホッパーまたはその他のツールを使用している誰かがこれを確認できます。IB を使用しているので、なぜこれが問題なのか疑問に思うでしょう... それは、IB を使用するtranslatesAutoresizingMaskIntoConstraintsと、制約を追加するビューが自動的に無効になるためです (その場所に幅と高さの制約が自動的に追加されます)。

解決

私の解決策は、すべてをに移動することでしたcontentView

{
   [self.contentView addSubview:someView];
   [self.contentView addSubview:someOtherView];
   [self.contentView addConstraint:...];
}

これがInterface Builderで機能するかどうかは100%確信が持てませんが、セルからすべてを押し出すと(セルに直接何かがあると仮定して)、機能するはずです。これがお役に立てば幸いです!

于 2012-09-27T22:42:33.093 に答える
53

どうやら、UITableViewCell の layoutSubviews 実装は、自動レイアウトの問題である super を呼び出さないようです。以下のカテゴリをプロジェクトにドロップすると問題が解決するかどうかを確認したいと思います。テストプロジェクトで役立ちました。

#import <objc/runtime.h>
#import <objc/message.h>

@implementation UITableViewCell (FixUITableViewCellAutolayoutIHope)

+ (void)load
{
    Method existing = class_getInstanceMethod(self, @selector(layoutSubviews));
    Method new = class_getInstanceMethod(self, @selector(_autolayout_replacementLayoutSubviews));

    method_exchangeImplementations(existing, new);
}

- (void)_autolayout_replacementLayoutSubviews
{
    [super layoutSubviews];
    [self _autolayout_replacementLayoutSubviews]; // not recursive due to method swizzling
    [super layoutSubviews];
}

@end

テーブルセルでbackgroundViewを使用すると、セルにサブビューとして追加されるため、問題が発生する可能性があります(ほとんどのサブビューは、通常はうまくいくはずのテーブルセルのcontentViewに追加する必要があります)。

注:このバグは iOS7 で修正されたようです。このコードを削除するか、少なくとも実行時チェックを追加して、iOS6 で実行されている場合にのみ実行されるようにすることができました。

于 2012-10-17T18:51:59.630 に答える
33

私は数ヶ月間同じバグを抱えていました。しかし、私は何が問題なのかを見つけました。

IB ファイルを作成すると、aUIViewが既に追加されています。このビューを使用すると、自動レイアウトが無効になっているときにアプリがクラッシュすることはありません (ただし、他にも問題があります)。自動レイアウトを使用する場合は、オブジェクト ライブラリで適切なビューを選択する必要がありますUITableViewCell

実際、すべてのサブビューが の に追加されるため、常にこのアイテムを使用する必要がcontentViewありUITableViewCellます。

それで全部です。すべてうまくいきます。

于 2013-02-28T15:45:05.303 に答える
17

カスタムUITableViewHeaderFooterView+ xibでも同じ問題がありました。

ここでいくつかの回答を見ましたが-layoutSubviews、カスタムフッタービュークラスのどの実装が問題を修正するかを見つけました:

-(void)layoutSubviews
{
    [super layoutSubviews];
    [self layoutIfNeeded]; // this line is key
}
于 2014-12-05T09:56:09.240 に答える
15

iOS 7 でも同じ問題がありました (iOS 8 では修正されているようです)。私にとっての解決策は、メソッド[self.view layoutIfNeeded]の最後で呼び出すことでした。viewDidLayoutSubviews

于 2014-10-17T17:55:51.690 に答える
7

私は同様の問題を抱えていましたが、それ自体ではありませんでしUITableViewCellUITableView。Google での最初の結果なので、ここに投稿します。それが問題であることが判明しましたviewForHeaderInSection。を作成し、UITableViewHeaderFooterViewに設定translatesAutoresizingMaskIntoConstraintsしましたNO。ここで興味深い部分が来ます:

iOS 7:

// don't do this on iOS 7
sectionHeader.translatesAutoresizingMaskIntoConstraints = NO;

これを行うと、アプリがクラッシュします

-layoutSubviews の実行後も自動レイアウトが必要です。UITableView の -layoutSubviews の実装は、super を呼び出す必要があります。

OK、テーブルビューのヘッダーでは自動レイアウトを使用できず、サブビューでのみ使用できると思いました。しかし、後でわかるように、それは完全な真実ではありません。要約すると、iOS 7 でヘッダーの自動サイズ変更マスクを無効にしないでください

iOS 8:

// you have to do this, otherwise you get an auto layout error
sectionHeader.translatesAutoresizingMaskIntoConstraints = NO;

これを使用しない場合、次の出力が得られます。

制約を同時に満たすことができません。

iOS 8 では、ヘッダーの自動サイズ変更マスクを無効にする必要があります。

なぜこのように動作するのかはわかりませんが、Apple は iOS 8 でいくつかのことを修正したようで、自動レイアウトは iOS 7 と iOS 8 で異なって動作します。

于 2014-11-11T12:59:43.330 に答える
7

カスタム テーブル ビュー セルのすべてのサブビューで「自動レイアウト」をオフにすることで、この問題を解決しました。

カスタム セルの xib で、サブビューを選択し、[File Inspector] > [Interface Builder Document] > [Use Autolayout] のチェックを外します

于 2013-02-14T11:11:04.370 に答える
5

上記の誰かが既に述べたように、UITableView で使用するビューを作成するときは、デフォルトで作成されたビューを削除し、UITableViewCell または UITableViewHeaderFooterView をルート ビューとしてドラッグする必要があります。ただし、その部分を見逃した場合に備えて、XIB を修正する方法があります。XIB ファイルをテキスト エディターで開き、ルート タグとその直接の子で属性translatesAutoresizingMaskIntoConstraintsYESに追加/変更する必要があります。たとえば、

<view contentMode="scaleToFill" horizontalHuggingPriority="1000" id="1" translatesAutoresizingMaskIntoConstraints="YES" customClass="MXWCollapsibleTableHeaderView">

于 2014-01-30T20:39:16.250 に答える
2

私はこれに遭遇しており、他のカスタムUIViewサブクラスが追加されたプロトタイプセルとしてUITableViewCellサブクラスに関連しているようです。UIKitの子を持つセルで成功したため、ここで「カスタム」を強調しますが、作成したビューの制約を作成しようとすると失敗し、作成者の質問に記載されているエラーがスローされます。

AutoLayoutを使用しない独立したペン先にセルを分割する必要がありました。

Appleがこの混乱を一掃することを期待しましょう。

于 2013-02-28T17:00:41.907 に答える
2

セル自体ではなく、セルの contentView にサブビューを追加します。したがって、代わりに:

[self addSubview:someView];

使用する必要があります

[self.contentView addSubview:someView];

于 2013-05-28T15:12:28.113 に答える
1

backgroundViewコネクタをバックグラウンドから切り離し、コネクタをUIImageViewカスタマイズaccessoryViewから切り離すことで、このエラーを排除しましたUIButton。これらは、私が使用していた方法で使用するためのものではなかったと思います。

于 2013-03-22T03:57:38.823 に答える
1

この問題の適切な解決策は得られませんでしたが、フレームを使用し、translatesAutoresizingMaskIntoConstraints プロパティを No に設定しないことで修正できます (デフォルトでは yes なので、設定しないでください)。

CGRect headerViewFrame = CGRectMake(0,0,320,60); //Frame for your header/footer view
UIView *tableHeaderView = [[UIView alloc] initWithFrame:headerViewFrame];
tableHeaderView.translatesAutoresizingMaskIntoConstraints = Yes; //Or don't set it at all
[self.tableView setTableHeaderView:tableHeaderView];
于 2014-07-28T14:26:09.093 に答える
1

UITableViewCell の代わりに UIView を最初に xib ファイルに追加したため、これに遭遇しました。

于 2013-02-25T15:59:17.190 に答える
0

私はまったく同じ問題を抱えていました。私のプロジェクトの問題は次のとおりです
。Interface Builder でカスタム UITableViewCell を作成する作業を行ったとき 、カスタム テーブル セルとしてXcode のオブジェクト コレクション ペインからTable View CellではなくViewをドラッグしました。 同じ状況にある場合の解決策は次のとおりです。 インターフェイスビルダーでビューを削除し、オブジェクトコレクションペインからテーブルビューセルをドラッグして、カスタムテーブルセルビューをやり直してください。古いビューのオブジェクトをコピーして、新しいテーブル ビュー セルのキャンバスに貼り付けることができます。


于 2014-09-19T02:01:48.690 に答える
0

Xcode 6、iOS 7+で設定していたテーブルフッタービューで非常によく似た問題がありました。解決策は nib ファイルの形式でした。どうやら、Xcode 4形式か何かでスタックしていたようです。ファイル設定を「Xcode 6.0で開く」(またはデフォルト)に変更すると、すぐに修正されました。たまたま解決策を見つけました。それは私を夢中にさせていたので、ファイル全体を削除して、明らかにデフォルト設定で再度作成しました。最新の Xcode でファイルを編集しただけでは、通常は Xcode 5+ 形式に変換されない理由がわかりません。

へ

于 2014-10-16T09:54:04.703 に答える
0

代わりにカール・リンドバーグの回答をオーバーライドするように変更UITableViewしましたが、それは私のために働き始めました:

UITableView+AutoLayoutFix.h

@interface UITableView (AutoLayoutFix)
@end

UITableView+AutoLayoutFix.m

#import <objc/runtime.h>

@implementation UITableView (AutoLayoutFix)

+ (void)load
{
    Method existingMethod = class_getInstanceMethod(self, @selector(layoutSubviews));
    Method newMethod = class_getInstanceMethod(self, @selector(_autolayout_replacementLayoutSubviews));

    method_exchangeImplementations(existingMethod, newMethod);
}

- (void)_autolayout_replacementLayoutSubviews
{
    [super layoutSubviews];
    [self _autolayout_replacementLayoutSubviews]; // not recursive due to method swizzling
    [super layoutSubviews];
}

@end

次にMyViewController.m、カテゴリをインポートしました:

#import "UITableView+AutoLayoutFix.h"
于 2015-08-21T22:41:18.113 に答える
0

私は同じ問題を抱えていました。DetailViewController に移動し、識別子の名前を UIView に変更しました。以前は UITableView にありました。問題を修正しました。この問題は、あなたの DetailViewController にある必要はありません。それは他のいずれかにある可能性があります。尊重される識別子に名前を変更してみてください。

于 2015-02-09T06:35:54.047 に答える
0

私の場合、

UITableView の自動レイアウト用に参照された UIImageView は、UITableView の backgroundView に割り当てられます。

self.tableView.backgroundView = self.tableBackgroundImageView;

そこで、UIView(ルート ビュー) から backgroundView の UIImageView を削除し、その UIImageView へのすべての自動レイアウト参照をリセット (削除) しました。UIView(ルートビュー)の外側に背景用のUIImageViewを配置しました。そして、コードで UITableView の backgroundView に割り当てます。

その後修正。

于 2013-09-23T09:07:47.620 に答える
0

状況によっては、これによりレイアウトの問題が簡単に解決されます (レイアウトによって異なります)。UITableView サブクラス内で、awakeFromNib または init のいずれかで、自動サイズ変更マスクを設定します。

self.contentView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;

デフォルトでは UIViewAutoresizingNone に設定されています

于 2013-09-18T23:11:30.680 に答える
0

解決策:スーパーレイアウトサブビューを呼び出す前に制約を変更してください

- (void)layoutSubviews
{

    [self _updateConstraints];

    [super layoutSubviews];
}
于 2015-03-19T09:52:50.170 に答える
0

私は解決策を見つけました。

私の場合、ストーリーボードでセルのビューを作成し (自動レイアウトを有効にして)、ViewController.m でカスタム UITableViewCell インターフェイスを定義しました。インターフェイスを ViewController.h に移動する必要があります。

于 2014-07-05T11:34:25.947 に答える
0

私も同じことを経験しています。自動レイアウトを使用する ShopCell .xib/storyboard からサブビューを別のビューのサブビューとしてプログラムで追加すると、制約の構成方法によっては例外がスローされる可能性があることが判明しました。私の推測では、IB で作成された制約が、プログラムでビューをサブビューとして追加するときに問題を引き起こす原因であると思います。これは、viewA --> viewB からの制約を維持している間に、viewB を viewC のサブビューとして追加する可能性があるためです。わかりましたか(その文は私自身を混乱させます)?

私の状況では、問題を引き起こしたのは非常に単純なビューだったので、IBではなくプログラムでビューを作成しました。それで解決しました。これらのビューを他の xib ファイルに抽出し、それらの自動レイアウトを無効にすることができます。私はそれがうまくいくと思います。

于 2012-10-03T18:13:58.913 に答える
0

IB の静的テーブル ビュー セルでも同様の問題がありました。セルの 1 つに、誤って UITextfield のサブクラスに変更されたクラスを持つサブビューがありました。コンパイラは警告/エラーを出しませんでした。しかし、実行時にシステムがView Controllerをロードできず、結果として前述のクラッシュが発生しました。

于 2015-03-05T13:40:13.400 に答える