web-dev-qa-db-ja.com

IBOutletがawakeFromNibに接続されていません

ここにリンクされているサンプルコードはうまく機能し、UIScrollViewが現在の画像の前後の画像のページングとプレビューを使用して画像を表示できるようにします。

再利用可能な単一のコントロールに例をカプセル化しようとしています。そこで、PagingScrollViewを作成しました。

@interface PagingScrollView : UIView {
    IBOutlet UIScrollView * scrollView;
}

@property (nonatomic,retain) IBOutlet UIScrollView * scrollView;

@end

汚れのある簡単な実装

- (void) awakeFromNib
{
    [super awakeFromNib];

    NSLog(@"awake from nib");
}

PagingScrollView.xibに、元のScrollViewPagingExampleViewController xibとまったく同じように、UIScrollViewとARScrollViewEnhancerを含むビューを配置しました。そのファイルの所有者のクラスはPagingScrollViewに設定され、そのscrollViewアウトレットは子UIScrollViewに設定されます。

ScrollViewPagingExampleViewControllerで、私は単に次のように宣言します。

IBOutlet PagingScrollView   *pagingScrollView;

そしてIBでは、ビューをドラッグし、そのクラスをPagingScrollViewに設定し、そのpagingScrollViewアウトレットをPagingScrollViewに接続します。

AwakeFromNibでは、scrollViewプロパティはnilです。 scrollViewは同じペン先のIBに接続されているので、この時点で利用できるようになると思います。

紛らわしいことに、ScrollViewPagingExampleViewController.xibには、scrollViewという名前の空のアウトレットがあります。これは、PagingScrollView.xibで定義されているものとは異なるPagingScrollViewのインスタンスがあることを示している可能性があります。

その結果、UIScrollViewに実際の子ビューを設定できません。私はここで何が間違っているのですか?

27

ここにこの質問に対する非常に良い答えがあります: awakeFromNibでビューにアクセスしますか?

簡単に言うと、ビューはawakeFromNibに読み込まれる場合がありますが、その内容は遅延して読み込まれます。そのため、達成しようとしていることにはawakeFromNibの代わりにviewDidLoadを使用する必要があります。

13
ashack

Swift 4で適切な答えを探してこれを見つけた人は、ここに行きます。

override func awakeAfter(using aDecoder: NSCoder) -> Any? {
    guard subviews.isEmpty else { return self }
    return Bundle.main.loadNibNamed("MainNavbar", owner: nil, options: nil)?.first
}

ただし、本当の秘密は、.xibファイルのメインビューをサブクラス化しないことです。代わりに、ファイル所有者を希望のクラスにし、クラスinit内にそのようにNibを追加します。

let bundle: Bundle = Bundle(for: type(of: self))
let nib: UINib = UINib(nibName: "<Nib File Name>", bundle: bundle)
if let view = nib.instantiate(withOwner: self, options: nil).first as? UIView {
    view.frame = bounds
    view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
    view.translatesAutoresizingMaskIntoConstraints = true
    addSubview(view)
}
5
Sethmr

Swiftを使用すると、設定後にカスタムビュー内でアイテムを使用できます。

class PointsTableViewCell: UITableViewCell {

    @IBOutlet weak var pointsTitleLabel: UILabel! {
        didSet {
            self.pointsTitleLabel.text = "Points"
        }
    }
}
2
Nadzeya

私はこの問題を抱えていました、そしてあなたのように他の記事は当てはまりませんでした。独自のビューを持つViewControllerがありました。そのViewControllerの.xibファイルにビューを配置し、CustomViewのクラスを指定しました。これは、CustomViewが独自の.xibファイルで定義されているという事実を除いてはうまく機能するため、awakeFromNibでは当然すべてのIBOutletsがnilでした。これは、InterfaceBuilderに.xibファイルをリンクする方法がないためです。そのため、ViewControllerのビューが画面に表示されると、CustomView.xibファイルをロードするのではなく、CustomViewをインスタンス化しようとします。

ここに詳細な回避策があります http://cocoanuts.mobi/2014/03/26/reusable/ 、しかし要点は、CustomViewクラスに以下を実装する必要があったということです

@implementation CustomView

    - (id)awakeAfterUsingCoder:(NSCoder *)aDecoder
    {
        if (![self.subviews count])
        {
            NSBundle *mainBundle = [NSBundle mainBundle];
            NSArray *loadedViews = [mainBundle loadNibNamed:@"CustomView" owner:nil options:nil];
            return [loadedViews firstObject];
        }
        return self;
    }

@end
2
odyth