Je connais la plupart du processus de création d'un XIB pour ma propre sous-classe UIView, mais tout ne fonctionne pas correctement pour moi - c'est principalement à cause de la connexion des IBOutlets. Je peux les amener à travailler de manière apparemment détournée.
Ma configuration est la suivante:
Ma méthode d'init est l'endroit où j'ai des problèmes.
J'ai essayé d'utiliser la méthode 'loadNibNamed' de NSBundle mainBundle et de définir le propriétaire sur 'self', en espérant que je créerais une instance de la vue et que ses sorties seraient automatiquement adaptées à celles de ma classe (je sais comment faire cela et je suis prudent). J'ai alors pensé que je voudrais faire "moi" égal à la sous-vue à l'index 0 dans cette plume, plutôt que de le faire
self = [super init];
ou quelque chose comme ça.
Je sens que je fais des choses mal ici, mais des exemples en ligne ont eu des choses similaires dans la méthode init, mais ils affectent cette sous-vue 0 à la propriété view et l'ajoutent en tant qu'enfant - mais n'est-ce pas alors un total de deux instances MyClass? Un essentiellement non lié à IBOutlets, contenant l'enfant MyClass instancié via loadNibNamed? Ou au mieux, n'est-ce pas une instance MyClass avec une UIView intermédiaire supplémentaire contenant tous les IBOutlets que je voulais à l'origine en tant qu'enfants directs de MyClass? Cela pose un léger désagrément lorsqu'il s'agit de faire des choses comme instanceOfMyClass.frame.size.width, car il renvoie 0, lorsque l'UIView enfant qui a été introduit renvoie la taille de trame réelle que je cherchais.
Est-ce que je fais mal que je joue avec loadNibNamed dans une méthode init? Dois-je faire quelque chose de plus comme ça?
MyClass *instance = [[MyClass alloc] init];
[[NSBundle mainBundle] loadNibNamed:@"MyClass" owner:instance options:nil];
Ou comme ça?
MyClass *instance = [[[NSBundle mainBundle] loadNibNamed:@"MyClass" owner:nil options:nil] objectAtIndex:0];
Merci d'avance pour toute assistance.
La deuxième option est la bonne. Le code le plus défensif que vous puissiez faire est le suivant:
+ (id)loadNibNamed:(NSString *)nibName ofClass:(Class)objClass {
if (nibName && objClass) {
NSArray *objects = [[NSBundle mainBundle] loadNibNamed:nibName
owner:nil
options:nil];
for (id currentObject in objects ){
if ([currentObject isKindOfClass:objClass])
return currentObject;
}
}
return nil;
}
Et appelez comme ceci:
MyClass *myClassInstance = [Utility loadNibNamed:@"the_nib_name"
ofClass:[MyClass class]];
// In my case, the code is in a Utility class, you should
// put it wherever it fits best
Je suppose que votre MyClass est une sous-classe de UIView
? Si tel est le cas, vous devez vous assurer que le UIView
de votre .xib est bien de la classe MyClass. Cela est défini sur le troisième onglet sur la partie droite dans le générateur d'interface, après avoir sélectionné la vue
Il vous suffit de créer la sous-vue via loadNibNamed
, de définir le cadre et de l'ajouter à la sous-vue. Par exemple, j'ajoute trois sous-vues à l'aide de ma classe MyView
, qui est une sous-classe UIView
dont l'interface est définie dans une NIB, MyView.xib
:
Donc, je définis initWithFrame
pour ma sous-classe UIView
:
- (id)initWithFrame:(CGRect)frame
{
NSLog(@"%s", __FUNCTION__);
self = [super initWithFrame:frame];
if (self)
{
NSArray *nibContents =
[[NSBundle mainBundle] loadNibNamed:@"MyView"
owner:self
options:nil];
[self addSubview:nibContents[0]];
}
return self;
}
Ainsi, par exemple, dans mon UIViewController
, je peux charger quelques-uns de ces objets sous-classés UIView
comme ceci:
for (NSInteger i = 0; i < 3; i++)
{
CGRect frame = CGRectMake(0.0, i * 100.0 + 75.0, 320.0, 100.0);
MyView *myView = [[MyView alloc] initWithFrame:frame];
[self.view addSubview:myView];
// if you want, do something with it:
// Here I'm initializing a text field and label
myView.textField.text = [NSString stringWithFormat:@"MyView textfield #%d",
i + 1];
myView.label.text = [NSString stringWithFormat:@"MyView label #%d",
i + 1];
}
J'ai conseillé à l'origine l'utilisation des contrôleurs, et je garderai cette réponse ci-dessous pour référence historique.
Réponse originale:
Je ne vois aucune référence pour afficher les contrôleurs ici. Habituellement, vous auriez une sous-classe de UIViewController
, avec laquelle vous instancieriez
MyClassViewController *controller =
[[MyClassViewController alloc] initWithNibName:@"MyClass"
bundle:nil];
// then you can do stuff like
//
// [self presentViewController:controller animated:YES completion:nil];
Le fichier NIB, MyClass.xib
, pourrait spécifier que la classe de base pour le UIView
, si vous voulez, où vous avez tout le code associé à la vue (par exemple en supposant que MyClass était une sous-classe de UIView
).
Voici une méthode que j'utilise:
UIView
, elle sera appelée MyClass
ParentViewController
.MyClass
.MyClass
seront connectées en cliquant-glissant depuis View (pas le propriétaire du fichier). Si vous souhaitez les connecter aux variables de ParentViewController
, cliquez-glissez depuis le propriétaire du fichier.ParentViewController
, vous devez déclarer une variable d'instance pour MyClass
.ParentViewController.h
ajoutez ce qui suit:
@class MyClass
@interface ParentViewController : UIViewController {
MyClass *myClass;
}
@property (strong, nonatomic) MyClass *myClass;
Synthétisez ceci dans votre implémentation et ajoutez ce qui suit dans votre méthode viewDidLoad
:
- (void)viewDidLoad {
[super viewDidLoad];
[[NSBundle mainBundle] loadNibNamed:@"MyClass" owner:self options:nil];
self.myClass.frame = CGRectMake(X,Y,W,H); //put your values in.
[self.view addSubview:self.myClass];
}