99 votes

Façon correcte de charger une Nib pour une sous-classe UIView

Je suis conscient que cette question a déjà été posée, mais les réponses se contredisent et je ne sais plus où j'en suis, alors je vous prie de ne pas m'enflammer.

Je veux avoir une carte réutilisable UIView dans toute mon application. Je veux décrire l'interface en utilisant un fichier nib.

Disons maintenant qu'il s'agit d'une vue d'indicateur de chargement avec un indicateur d'activité. Je voudrais qu'un événement instancie cette vue et l'anime dans la vue d'un contrôleur de vue. Je pourrais décrire l'interface de la vue sans problème de manière programmatique, en créant les éléments de manière programmatique et en définissant leur cadre dans une méthode init, etc.

Mais comment faire en utilisant une plume ? En conservant la taille donnée dans le constructeur d'interface sans avoir à définir un cadre.

J'ai réussi à faire comme ça, mais je suis sûr que c'est faux (c'est juste une vue avec un sélecteur dedans) :

 - (id)initWithDataSource:(NSDictionary *)dataSource {
        self = [super init];
        if (self){
            self = [[[NSBundle mainBundle] loadNibNamed:[NSString stringWithFormat:@"%@", [self class]] owner:self options:nil] objectAtIndex:0];
            self.pickerViewData = dataSource;
            [self configurePickerView];
        }
        return self;
    }

Mais j'écrase le self, et quand je l'instancie :

FSASelectView *selectView = [[FSASelectView alloc] initWithDataSource:selectViewDictionary];
    selectView.delegate = self;

    selectView.frame = CGRectMake(0, self.view.bottom + 50, [FSASelectView width], [FSASelectView height]);

Je dois définir manuellement le cadre plutôt que de le faire récupérer par IB.

EDIT : Je veux créer cette vue personnalisée dans un contrôleur de vue, et avoir accès au contrôle des éléments de la vue. Je ne veux pas d'un nouveau contrôleur de vue.

Merci

EDIT : Je ne sais pas si c'est la meilleure pratique, je suis sûr que ce n'est pas le cas, mais c'est comme ça que je l'ai fait :

FSASelectView *selectView = [[[NSBundle mainBundle] loadNibNamed:[NSString stringWithFormat:@"%@",[FSASelectView class]] owner:self options:nil] objectAtIndex:0];
    selectView.delegate = self;
    [selectView configurePickerViewWithData:ds];
    selectView.frame = CGRectMake(0, self.view.bottom + 50, selectView.width, selectView.height);
    selectView.alpha = 0.9;
    [self.view addSubview:selectView];
    [UIView animateWithDuration: 0.25 delay: 0 options:UIViewAnimationOptionAllowUserInteraction |UIViewAnimationOptionCurveEaseInOut animations:^{
                            selectView.frame = CGRectMake(0, self.view.bottom - selectView.height, selectView.width, selectView.height);
                            selectView.alpha = 1;
                        } completion:^(BOOL finished) {
                        }];

Une pratique correcte toujours souhaitée

Aurait-il fallu utiliser un contrôleur de vue et init avec le nom de la nib ? Aurais-je dû définir la nib dans une méthode d'initialisation de UIView dans le code ? Ou est-ce que ce que j'ai fait est correct ?

2voto

Rakesh Points 2218

Vous pouvez soit initialiser le fichier xib à l'aide d'un contrôleur de vue et utiliser viewController.view, soit procéder comme vous l'avez fait. En faisant seulement un UIView en tant que contrôleur pour UIView est une mauvaise idée.

Si vous n'avez pas de points de vente à partir de votre vue personnalisée, vous pouvez utiliser directement un fichier UIViewController pour l'initialiser.

Mise à jour : Dans votre cas :

UIViewController *genericViewCon = [[UIViewController alloc] initWithNibName:@"CustomView"];
//Assuming you have a reference for the activity indicator in your custom view class
CustomView *myView = (CustomView *)genericViewCon.view;
[parentView addSubview:myView];
//And when necessary
[myView.activityIndicator startAnimating]; //or stop

Sinon, vous devez créer un UIViewController (à faire en tant que propriétaire du dossier pour que les prises soient correctement câblées).

YourCustomController *yCustCon = [[YourCustomController alloc] initWithNibName:@"YourXibName"].

Partout où vous voulez ajouter la vue, vous pouvez utiliser.

[parentView addSubview:yCustCon.view];

Cependant, passer le contrôleur d'une autre vue (déjà utilisé pour une autre vue) comme propriétaire lors du chargement du xib n'est pas une bonne idée car la propriété view du contrôleur sera modifiée et lorsque vous voudrez accéder à la vue originale, vous n'aurez pas de référence à celle-ci.

EDIT : Vous rencontrerez ce problème si vous avez configuré votre nouveau xib avec le propriétaire du fichier comme le même propriétaire principal. UIViewController et a lié la propriété view à la nouvelle vue xib.

c'est-à-dire

  • YourMainViewController -- gère -- mainView
  • CustomView -- doit être chargé à partir d'un xib au fur et à mesure des besoins.

Le code ci-dessous causera de la confusion plus tard, si vous l'écrivez à l'intérieur de la vue a fait le chargement de YourMainViewController . C'est parce que self.view à partir de maintenant, vous ferez référence à votre vue personnalisée.

-(void)viewDidLoad:(){
  UIView *childView= [[[NSBundle mainBundle] loadNibNamed:@"YourXibName" owner:self options:nil] objectAtIndex:0];
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X