web-dev-qa-db-ja.com

InterfaceBuilderでIBDesignablexibを読み込めませんでした

xibchildXib)ファイルがその所有者を介してカスタムUIView Swiftファイルにリンクされています。

これが私のカスタムUIViewを初期化する方法です。

// init for IBDesignable
override init(frame: CGRect) {
    super.init(frame: frame)

    let view = loadViewFromNib()
    view.frame = bounds

    addSubview(view)
}

required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
    addSubview(loadViewFromNib())
}

func loadViewFromNib() -> UIView {

    let bundle = NSBundle(forClass: self.dynamicType)
    let nib = UINib(nibName: "CommentCellView", bundle: bundle)
    let view = nib.instantiateWithOwner(self, options: nil)[0] as! UIView

    return view
}

このxibchildXib)を別のxibparentXib)に追加すると、次のエラーが発生します。

エラー:IB Designables:MyRootViewのインスタンスのレンダリングに失敗しました:エージェントが例外をスローしました。

ここで、MyRootViewparentXibにリンクされているファイルです。

エラー:IB Designables:自動レイアウトステータスの更新に失敗しました:エージェントが「NSInternalInconsistencyException」例外を発生させました:バンドルにNIBをロードできませんでした:「NSBundle(ロード済み)」、名前は「MyIBDesignableCustomViewFilename」

ここで、MyIBDesignableCustomViewFilenamechildXibにリンクされているファイルです。

Custom classからIdentity inspectorDebugをクリックしてデバッグすると、その行からは機能しません。

let view = nib.instantiateWithOwner(self, options: nil)[0] as! UIView

すべてのxibファイルはCopy Bundle ResourcesBuild Phasesにあります。

何が問題なのか分かりますか?

22
Nico

最初の一歩:

IBDesignableとIBInspectableの概要を説明し、新機能を活用する方法を紹介します。デモを作成する以外に、機能を詳しく説明する方法はありません。そこで、「Rainbow」というカスタムインターフェイスを一緒に構築します。

IBDesignableおよびIBInspectable

IBDesignableとIBInspectableを使用すると、開発者はInterface Builderでリアルタイムにレンダリングするインターフェイス(またはビュー)を作成できます。一般に、この新機能を適用するには、UIViewまたはUIControlをサブクラス化してビジュアルクラスを作成し、Swiftでクラス名の前に@IBDesignableキーワードを付けるだけです。 Objective-Cを使用している場合は、代わりにIB_DESIGNABLEマクロを使用します。 Swiftのサンプルコードは次のとおりです。

@IBDesignable 
class Rainbow: UIView {
}

Xcodeの古いバージョンでは、ユーザー定義のランタイム属性を編集して、Interface Builderでオブジェクト(layer.cornerRadiusなど)のプロパティを変更できます。問題は、プロパティの正確な名前を入力する必要があることです。 IBInspectableは一歩前進します。ビジュアルクラスのプロパティの前にIBInspectableを付けると、プロパティはInterface Builderに公開されるため、値を非常に簡単に変更できます。

enter image description here

繰り返しますが、Swiftでアプリを開発している場合は、選択したプロパティの前にキーワード@IBInspectableを付けるだけです。サンプルコードスニペットは次のとおりです。

@IBInspectable var firstColor: UIColor = UIColor.blackColor()
 {
     // Update your UI when value changes
 }



@IBInspectable var firstColor: UIColor = UIColor.blackColor()
{
     // Update your UI when value changes
 }

Xcodeプロジェクトのビルド

Xcodeで新しいプロジェクトを作成し、テンプレートとしてシングルビューアプリケーションを選択して、RainbowDemoという名前を付けてみましょう。このプロジェクトではプログラミング言語としてSwiftを使用するので、プロジェクトを作成するときに忘れずに選択してください。

終了したら、プロジェクトナビゲータでMain.storyboardを選択し、ViewオブジェクトをオブジェクトライブラリからViewControllerにドラッグします。色を#38334C(または任意の色)に変更し、サイズを600 x 434に設定します。次に、メインビューの中央に配置します。メインビューの色をビューオブジェクトの同じ色に変更することを忘れないでください。ヒント:コードのRGBカラー値を変更する場合は、カラーパレットを開き、[スライダー]タブに切り替えてRGB値を変更します。

混乱しますか?心配ない。プロジェクトのデモを終えると、私が何を意味するのか理解できます。

Xcode 6では、すべてのタイプのiOSデバイスをサポートするために、ビューの自動レイアウト制約を構成する必要があります。自動レイアウトは、Xcodeの最新バージョンでは非常に強力です。単純な制約の場合は、[自動レイアウト]メニューの[問題]オプションをクリックして[欠落している制約を追加]を選択するだけで、Xcodeがビューのレイアウト制約を自動的に構成します。

enter image description here

カスタムビュークラスの作成

ストーリーボードでビューを作成したので、次はカスタムビュークラスを作成します。クラスの作成にはSwiftクラステンプレートを使用します。「Rainbow」という名前を付けます。

enter image description here

Then insert the following code in the class:

import UIKit

class Rainbow: UIView {
    required init(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }

    override init(frame: CGRect) {
        super.init(frame: frame)
    }
}

前述のように、ビジュアルクラスはUIViewのサブクラスです。ライブレンダリングでカスタムクラスを使用するには、上記のように両方の初期化子をオーバーライドする必要があります。次に、アシスタントエディタを選択してビューを分割します。

enter image description here

完了したら、アシスタントエディタでメインストーリーボードを選択して、構築しているものをリアルタイムで確認できるようにします。 IDインスペクターで、ビューのクラス名を「Rainbow」に変更することを忘れないでください。

IBDesignableコントロールの実装

ライブレンダリングのコントロールを有効にする最初の手順は、クラス名の前に@IBDesignableを付けて、カスタムビューをDesignableとして設定することです。

@IBDesignable 
class Rainbow: UIView {
    ...
}

ご覧のとおり、簡単です。しかし、この単純なキーワードを使用すると、開発がはるかに簡単になります。次に、円の色を設定するためのいくつかのプロパティを追加します。次のコード行をRainbowクラスに挿入します。

@IBInspectable var firstColor: UIColor = UIColor(red: (37.0/255.0), green: (252.0/255), blue: (244.0/255.0), alpha: 1.0)
@IBInspectable var secondColor: UIColor = UIColor(red: (171.0/255.0), green: (250.0/255), blue: (81.0/255.0), alpha: 1.0)
@IBInspectable var thirdColor: UIColor = UIColor(red: (238.0/255.0), green: (32.0/255)

ここでは、各プロパティをデフォルトの色で事前定義し、ユーザーが値を変更するたびにビューを再描画するように指示します。最も重要なのは、各プロパティの前に@IBInspectableキーワードを付けることです。ビューの検査可能な属性に移動すると、次のプロパティが視覚的に表示されます。

かっこいいですよね?プロパティをIBInspectableとして指定することにより、カラーピッカーを使用して視覚的に編集できます。

では、画面に円を描くために使用されるRainbowクラスのメインメソッドの実装に移りましょう。次のメソッドをクラスに挿入します。

func addOval(lineWidth: CGFloat, path: CGPathRef, strokeStart: CGFloat, strokeEnd: CGFloat, strokeColor: UIColor, fillColor: UIColor, shadowRadius: CGFloat, shadowOpacity: Float, shadowOffsset: CGSize) {

    let arc = CAShapeLayer()
    arc.lineWidth = lineWidth
    arc.path = path
    arc.strokeStart = strokeStart
    arc.strokeEnd = strokeEnd
    arc.strokeColor = strokeColor.CGColor
    arc.fillColor = fillColor.CGColor
    arc.shadowColor = UIColor.blackColor().CGColor
    arc.shadowRadius = shadowRadius
    arc.shadowOpacity = shadowOpacity
    arc.shadowOffset = shadowOffsset
    layer.addSublayer(arc)
}

enter image description here

コードをクリーンで読みやすくするために、呼び出し元から提供されたパラメーターに従って、完全な円または半円を描画するための一般的なメソッドを作成します。 CAShapeLayerクラスを使用して円または円弧を描くのは非常に簡単です。 StrokeStartプロパティとstrokeEndプロパティを使用して、ストロークの開始と終了を制御できます。 stokeEndの値を0.0から1.0の間で変化させることにより、完全な円または部分的な円を描くことができます。残りのプロパティは、ストロークの色や影の色などを設定するために使用されます。CAShapeLayerで使用可能なすべてのプロパティの詳細については、公式ドキュメントを確認してください。

次に、Rainbowクラスに次のメソッドを挿入します。

override func drawRect(rect: CGRect) {
    // Add ARCs
    self.addCirle(80, capRadius: 20, color: self.firstColor)
    self.addCirle(150, capRadius: 20, color: self.secondColor)
    self.addCirle(215, capRadius: 20, color: self.thirdColor)
}

func addCirle(arcRadius: CGFloat, capRadius: CGFloat, color: UIColor) {
    let X = CGRectGetMidX(self.bounds)
    let Y = CGRectGetMidY(self.bounds)

    // Bottom Oval
    let pathBottom = UIBezierPath(ovalInRect: CGRectMake((X - (arcRadius/2)), (Y - (arcRadius/2)), arcRadius, arcRadius)).CGPath
    self.addOval(20.0, path: pathBottom, strokeStart: 0, strokeEnd: 0.5, strokeColor: color, fillColor: UIColor.clearColor(), shadowRadius: 0, shadowOpacity: 0, shadowOffsset: CGSizeZero)

    // Middle Cap
    let pathMiddle = UIBezierPath(ovalInRect: CGRectMake((X - (capRadius/2)) - (arcRadius/2), (Y - (capRadius/2)), capRadius, capRadius)).CGPath
    self.addOval(0.0, path: pathMiddle, strokeStart: 0, strokeEnd: 1.0, strokeColor: color, fillColor: color, shadowRadius: 5.0, shadowOpacity: 0.5, shadowOffsset: CGSizeZero)

    // Top Oval
    let pathTop = UIBezierPath(ovalInRect: CGRectMake((X - (arcRadius/2)), (Y - (arcRadius/2)), arcRadius, arcRadius)).CGPath
    self.addOval(20.0, path: pathTop, strokeStart: 0.5, strokeEnd: 1.0, strokeColor: color, fillColor: UIColor.clearColor(), shadowRadius: 0, shadowOpacity: 0, shadowOffsset: CGSizeZero)

}

drawRectメソッドのデフォルトの実装は何もしません。ビューに円を描画するために、メソッドをオーバーライドして独自の描画コードを実装します。 addCircleメソッドは、arcRadius、capRadius、およびcolorの3つのパラメーターを取ります。 arcRadiusは円の半径であり、capRadiusは丸いキャップの半径です。

AddCircleメソッドは、UIBezierPathを使用して円弧を描画し、次のように機能します。

First it draws a half circle at the bottom
Next it draws a full small circle at the Edge of the arc.
Finally, it draws the other half of the circle

DrawRectメソッドでは、半径と色が異なるaddCircleメソッドを3回呼び出します。この図は、円がどのように描かれるかを示しています。 enter image description here

ヒント:UIBezierPathの詳細が必要な場合は、Appleの公式ドキュメントを確認してください。

IBInspectableプロパティを使用すると、コードに飛び込むことなく、InterfaceBuilderで各円の色を自由に変更できるようになりました。

明らかに、arcRadiusをIBInspectableプロパティとしてさらに公開できます。練習問題として残しておきます。

enter image description here

enter image description here

サンプルコードについては、ここをクリックしてください: https://github.com/appcoda/Rainbow-IBDesignable-Demo

15
princ___y

私は同じ問題を抱えていて、なんとかそれを修正することができました。

Swift

let bundle = Bundle(for: MyView.self)
let view = UINib(nibName: "MyView", bundle: bundle).instantiate(withOwner: self) as! MyView

重要なのはバンドルです

5
NebulaFox

以下のような両方のエラーの場合:

error: IB Designables: Failed to render instance of ....
error: IB Designables: Failed to update auto layout status: The agent raised a "NSInternalInconsistencyException" exception: Could not load NIB in bundle ...

問題をどこで解決すべきかを理解するのに役立つ、簡単な自己検証を行うことをお勧めします。

  1. .xibファイルがプロジェクトに正しく追加されているかどうかを確認します
  2. NibNameが正しく設定されているかどうかを確認します。ここでタイプミスが発生することがあります
  3. アウトレットとアクションの両方が適切に接続されているかどうかを確認し、コードの実装を含めます
0
Allen