Lorsque j'écris ma propre classe étendue UIButton
- et que je la crée @IBDesignable
, je reçois deux erreurs dans Interface Builder, à savoir:
Voici mon code:
import UIKit
@IBDesignable
class RandjeUIButton: UIButton {
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.backgroundColor = UIColor.blackColor()
}
}
Je travaille dans Xcode 7 bêta 2 sur OS X 10.11 bêta 2. (Exécution dans la VM)
Interface Builder de Xcode nécessite que vous implémentiez les initialiseurs both ou ni pour les classes @IBDesignable
afin que le rendu s'effectue correctement dans IB.
Si vous implémentez required init(coder aDecoder: NSCoder)
, vous devrez également remplacer init(frame: CGRect)
, sinon "l'agent va planter" comme indiqué dans les erreurs renvoyées par Xcode.
Pour ce faire, ajoutez le code suivant à votre classe:
override init(frame: CGRect) {
super.init(frame: frame)
}
J'ai rencontré le même problème et l'ai résolu de cette façon:
erreur: IB Designables: échec de la mise à jour du statut de présentation automatique: l'agent est tombé en panne
Ensuite, le Xcode vous dira où se trouve le prolem . Dans mon cas, je laisse tomber la IBDesignable
avant le cours.
Puis j'ai nettoyé et reconstruit, l'erreur a disparu
Dans Xcode 7.3, aucune des solutions ci-dessus ne fonctionnait pour moi, mais la réponse acceptée à cette question était la suivante: Impossible de restituer une instance de IB Designables
- Effacer les données dérivées Xcode pour le projet. Ils sont dans ~/Library/Developer/Xcode/DerivedData
- Nettoyez votre version actuelle en appuyant sur ⌘⇧K
- Construisez votre projet
- Dans le storyboard, allez dans le menu de l'éditeur et actualisez toutes les vues; attendez que la construction soit terminée et que les erreurs disparaissent
Je n'avais pas besoin de faire la 4ème étape pour résoudre le problème (et obtenir mon PaintCode-drawRect'd UIView to Paint dans le storyboard), inclus ici juste au cas où.
Crédits à @Mojtaba et @WeZZard
Il y a une multitude de problèmes qui peuvent causer cela. Lancez la console et recherchez le rapport d'incident IBDesignablesCocoaTouch...
Je viens de résoudre un problème avec une tierce partie désignable qui avait des problèmes avec la sémantique valueForKey
.
Pour moi, ce n’était pas l’utilisation de #if !TARGET_INTERFACE_BUILDER
qui m’avait. En gros, j'avais un code qui aurait pour résultat l'accès à un chemin dans mon Bundle ...
Bundle.main.path(forResource: "Foo", ofType: "plist")
Le problème est que lors de l'exécution dans IB (et non dans votre application), Bundle.main
n'est pas votre application ...
(lldb) po Bundle.main
NSBundle </Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/Library/Xcode/Overlays> (loaded)
La solution consiste donc simplement à examiner votre code @IBDesignable UIView
avec soin et à utiliser #if !TARGET_INTERFACE_BUILDER
pour tout élément (dans mon cas, les appels à CoreLocation
par exemple) qui n'a pas de sens lors de l'exécution au moment de la conception.
Voici ce que vous voyez lorsque vous utilisez le Editor -> Debug Selected View
lorsque vous sélectionnez votre @IBDesignable UIView
dans votre storyboard:
Dans mon cas, comme vous pouvez le constater, initXXXX
effectuait une assert
, qui se bloquait au moment de la conception, car elle recherchait une valeur dans le fichier de mon Bundle - Xcode, au moment de la conception.
J'ai trouvé quelque chose de vraiment important lors de l'utilisation d'un UIImage dans n'importe quelle classe marquée @IBDesignable. L’initiation classique d’UIImage planterait l’agent:
let myImage = UIImage(named: String) // crash the agent
La solution consiste à utiliser cette méthode init de UIImage:
let myImage = UIImage(named: String, in: Bundle, compatibleWith: UITraitCollection)
Exemple de code de travail:
let appBundle = Bundle(for: type(of: self))
let myImage = UIImage(named: "myImage", in: bundle, compatibleWith: self.traitCollection))
Où self est votre classe avec le mot clé @IBDesignable. Xcode 9.4, Swift 4.1
Il suffit de rouvrir un code sur un autre système de configuration Xcode. Dans mon cas cela a fonctionné.
Voici comment je résous ce problème:
import UIKit
@IBDesignable class TestView: UIView {
@IBOutlet weak var label: UILabel!
@IBInspectable var textLabel1: String? {
get {
return label.text
}
set {
label.text = newValue
}
}
// MARK: Setup
var view1: UIView!
var nibName: String = "TestView"
override init(frame: CGRect) {
super.init(frame: frame)
xibSetup()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
xibSetup()
}
private func xibSetup() {
view1 = loadViewFromNib()
view1?.frame = self.bounds
view1?.autoresizingMask = [.FlexibleWidth, .FlexibleHeight]
if view1 != nil {
addSubview(view1!)
//textLabel1 = "ok"
}
}
private func loadViewFromNib() -> UIView? {
let bundle = NSBundle(forClass: self.dynamicType)
let nib = UINib(nibName: nibName, bundle: bundle)
for object in nib.instantiateWithOwner(self, options: nil) {
if let view: UIView = object as? UIView {
return view
}
}
return nil
}
}
Usage:
XCode 10, Swift 4.2
J'ai trouvé une réponse ici
La solution était simple: changer la façon dont le paquet était résolu dans la méthode required init?(coder aDecoder: NSCoder)
de ma classe d'affichage personnalisé.
Bundle.main.loadNibNamed(String(describing: TestView.self), owner: self, options: nil)
devait être changé pour
let bundle = Bundle(for: TestView.self)
bundle.loadNibNamed(String(describing: TestView.self), owner: self, options: nil)