Je crée actuellement une application qui aura plusieurs minuteries, qui sont fondamentalement toutes identiques.
Je veux créer une classe personnalisée qui utilise tout le code pour les minuteries ainsi que la mise en page / animations, afin que je puisse avoir 5 minuteries identiques qui fonctionnent indépendamment les unes des autres.
J'ai créé la mise en page en utilisant IB (xcode 4.2) et tout le code pour les minuteries est actuellement juste dans la classe viewcontroller.
J'ai du mal à comprendre comment tout encapsuler dans une classe personnalisée puis l'ajouter au viewcontroller, toute aide serait très appréciée.
UITableViewCell
ouUICollectionViewCell
. Dans mon cas, j'ai besoin d'une vue petite mais assez complexe que je peux utiliser plusieurs fois dans les contrôleurs et les vues de collection. Et les concepteurs continuent de le retravailler, donc je veux un seul endroit où la mise en page est définie. Par conséquent, une plume.Réponses:
Eh bien, pour répondre conceptuellement, votre minuterie devrait probablement être une sous-classe de
UIView
au lieu deNSObject
.Pour instancier une instance de votre minuterie dans IB, faites-la simplement glisser et
UIView
déposez-la sur la vue de votre contrôleur de vue et définissez sa classe sur le nom de classe de votre minuterie.N'oubliez pas
#import
votre classe de minuterie dans votre contrôleur de vue.Edit: pour la conception IB (pour l'instanciation du code, voir l'historique des révisions)
Je ne suis pas du tout familier avec le storyboard, mais je sais que vous pouvez construire votre interface dans IB en utilisant un
.xib
fichier qui est presque identique à l'utilisation de la version du storyboard; Vous devriez même pouvoir copier et coller vos vues dans leur ensemble depuis votre interface existante vers le.xib
fichier.Pour tester cela, j'ai créé un nouveau vide
.xib
nommé "MyCustomTimerView.xib". Ensuite, j'ai ajouté une vue, et à cela j'ai ajouté une étiquette et deux boutons. Ainsi:J'ai créé une nouvelle sous-classe de classe objective-C
UIView
nommée "MyCustomTimer". Dans mon,.xib
j'ai défini la classe Propriétaire de mon fichier sur MyCustomTimer . Maintenant, je suis libre de connecter des actions et des prises comme n'importe quelle autre vue / contrôleur. Le.h
fichier résultant ressemble à ceci:Le seul obstacle qui reste à sauter est d'obtenir cela
.xib
sur maUIView
sous - classe. L'utilisation d'un.xib
réduit considérablement la configuration requise. Et puisque vous utilisez des storyboards pour charger les minuteries, nous savons que-(id)initWithCoder:
c'est le seul initialiseur qui sera appelé. Voici donc à quoi ressemble le fichier d'implémentation:La méthode nommée
loadNibNamed:owner:options:
fait exactement ce qu'elle ressemble. Il charge le Nib et définit la propriété "File's Owner" sur self. Nous extrayons le premier objet du tableau et c'est la vue racine du Nib. Nous ajoutons la vue en tant que sous-vue et voilà, c'est à l'écran.Évidemment, cela ne fait que changer la couleur d'arrière-plan de l'étiquette lorsque vous appuyez sur les boutons, mais cet exemple devrait vous aider à bien démarrer.
Notes basées sur des commentaires:
Il est à noter que si vous rencontrez des problèmes de récursions infinis, vous avez probablement raté l'astuce subtile de cette solution. Il ne fait pas ce que vous pensez faire. La vue placée dans le storyboard n'est pas vue, mais charge une autre vue en tant que sous-vue. Cette vue qu'il charge est la vue qui est définie dans la pointe. Le "propriétaire du fichier" dans la pointe est cette vue invisible. Ce qui est cool, c'est que cette vue invisible est toujours une classe Objective-C qui peut être utilisée comme une sorte de contrôleur de vue pour la vue qu'elle apporte depuis la pointe. Par exemple, les
IBAction
méthodes de laMyCustomTimer
classe sont quelque chose que vous attendez plus dans un contrôleur de vue que dans une vue.En passant, certains peuvent soutenir que cela rompt
MVC
et je suis quelque peu d'accord. De mon point de vue, c'est plus étroitement lié à une coutumeUITableViewCell
, qui doit aussi parfois faire partie du contrôleur.Il convient également de noter que cette réponse était de fournir une solution très spécifique; créez une pointe qui peut être instanciée plusieurs fois sur la même vue que celle présentée sur un storyboard. Par exemple, vous pouvez facilement imaginer six de ces minuteries sur un écran iPad à la fois. Si vous avez seulement besoin de spécifier une vue pour un contrôleur de vue qui doit être utilisé plusieurs fois dans votre application, la solution fournie par jyavenard à cette question est presque certainement une meilleure solution pour vous.
la source
userInfo
propriété sur la notification@property(nonatomic,copy) NSDictionary *userInfo;
File's Owner
le nom de votre classe est défini, mon problème de récursivité infinie a été résolu.[self addSubview:[[[NSBundle mainBundle] loadNibNamed:@"MyCustomTimerView" owner:self options:nil] objectAtIndex:0]];
Ajouter le deuxième UIView ... Cela semble étrange pour moi, personne d'autre ne ressent la même chose? Si tel est le cas, est-ce quelque chose de conçu par Apple? Ou est-ce que quelqu'un a trouvé la solution en faisant cela?Exemple Swift
Mis à jour pour Xcode 10 et Swift 4
Voici un aperçu de base. J'ai appris beaucoup de choses à l'origine en regardant cette série de vidéos Youtube . Plus tard, j'ai mis à jour ma réponse en fonction de cet article .
Ajouter des fichiers d'affichage personnalisés
Les deux fichiers suivants formeront votre vue personnalisée:
UIView
sous-classeLes détails pour les ajouter sont ci-dessous.
Fichier xib
Ajoutez un fichier .xib à votre projet (Fichier> Nouveau> Fichier ...> Interface utilisateur> Affichage) . J'appelle le mien
ReusableCustomView.xib
.Créez la mise en page que vous souhaitez que votre vue personnalisée ait. A titre d'exemple, je vais faire une mise en page avec a
UILabel
et aUIButton
. C'est une bonne idée d'utiliser la mise en page automatique pour que les choses se redimensionnent automatiquement, quelle que soit la taille que vous définissez plus tard. (J'ai utilisé Freeform pour la taille xib dans l'inspecteur d'attributs afin de pouvoir ajuster les métriques simulées, mais ce n'est pas nécessaire.)Fichier Swift
Ajoutez un fichier .swift à votre projet (Fichier> Nouveau> Fichier ...> Source> Fichier Swift) . C'est une sous-classe de
UIView
et j'appelle la mienneReusableCustomView.swift
.Faire du fichier Swift le propriétaire
Revenez à votre fichier .xib et cliquez sur "Propriétaire du fichier" dans la structure du document. Dans l'inspecteur d'identité, écrivez le nom de votre fichier .swift comme nom de classe personnalisé.
Ajouter un code de vue personnalisé
Remplacez le
ReusableCustomView.swift
contenu du fichier par le code suivant:Assurez-vous que l'orthographe du nom de votre fichier .xib est correcte.
Branchez les prises et les actions
Connectez les prises et les actions en contrôlant le glissement de l'étiquette et du bouton dans la mise en page xib vers le code de vue personnalisé rapide.
Utilisez votre vue personnalisée
Votre vue personnalisée est maintenant terminée. Tout ce que vous avez à faire est d'ajouter un
UIView
où vous le souhaitez dans votre storyboard principal. Définissez le nom de classe de la vue surReusableCustomView
dans l'inspecteur d'identité.la source
Bundle.main
enBundle(for: ...)
fait l'affaire. Apparemment,Bundle.main
n'est pas disponible au moment de la conception.init(frame:)
. Une fois que vous ajoutez ceci (et tirez tout le code d'initialisation dans unecommonInit()
fonction), cela fonctionne bien et s'affiche dans IB. Voir plus d'informations ici: stackoverflow.com/questions/31265906/…Réponse pour les contrôleurs de vue, pas pour les vues :
Il existe un moyen plus simple de charger un xib à partir d'un storyboard. Supposons que votre contrôleur soit du type MyClassController qui hérite de
UIViewController
.Vous ajoutez un
UIViewController
IB utilisant dans votre storyboard; changez le type de classe en MyClassController. Supprimez la vue qui avait été automatiquement ajoutée dans le storyboard.Assurez-vous que le XIB que vous souhaitez appeler s'appelle MyClassController.xib.
Lorsque la classe sera instanciée lors du chargement du storyboard, le xib sera automatiquement chargé. La raison en est due à l'implémentation par défaut de
UIViewController
laquelle appelle le XIB nommé avec le nom de la classe.la source
'Could not load NIB in bundle: 'NSBundle </Users/me/.../MyAppName.app> (loaded)' with name 'uB0-aR-WjG-view-4OA-9v-tyV''
. Notez le whacko nibName. J'utilise le nom de classe correct pour le dans la plume.Ce n'est pas vraiment une réponse, mais je pense qu'il est utile de partager cette approche.
Objectif c
Rapide
Optionnel :
C'est tout, maintenant vous pouvez ajouter votre vue personnalisée dans votre storyboard et elle sera affichée :)
CustomViewWithXib.h :
CustomViewWithXib.m :
CustomViewWithXib.swift :
Vous pouvez trouver quelques exemples ici .
J'espère que cela pourra aider.
la source