Подтвердить что ты не робот

IOS loadNibNamed путаница, что лучше всего?

Я знаком с большинством процессов создания XIB для моего собственного подкласса UIView, но не все работает правильно для меня - это в основном связано с привязкой IBOutlets. Я могу заставить их работать в том, что кажется окольным путем.

Моя настройка такова:

  • У меня есть MyClass.h и MyClass.m. У них есть IBOutlets для UIView (называемый view) и UILabel (называемый myLabel). Я добавил свойство "view", потому что некоторые примеры в Интернете, казалось, подсказывали вам, что вам это нужно, и он фактически решил проблему, когда я получал сбой, потому что он не смог найти свойство view, я думаю, что даже в родительском классе UIView.
  • У меня есть XIB файл с именем MyClass.xib, а его собственный пользовательский класс File Owner - MyClass, который предварительно заполнен после моих .h и .m для этого класса.

Мой метод init - это то, где у меня возникают проблемы.

Я попытался использовать NSBundle mainBundle 'loadNibNamed' метод и установить владельца на "я", надеясь, что я создам экземпляр представления, и он автоматически получит свои выходные данные, соответствующие тем, которые были в моем классе (Я знаю, как это сделать, и я осторожен с этим). Затем я подумал, что хочу сделать "я" равным подчиненному в индексе 0 в этом nib, вместо того, чтобы делать

self = [super init];

или что-то в этом роде.

Я чувствую, что я делаю что-то неправильно здесь, но примеры в Интернете имеют похожие вещи в методе init, но они присваивают этому subview 0 свойству вида и добавляют его как дочерний элемент - но это не то в общей сложности два экземпляра MyClass? Один по существу несвязанный с IBOutlets, содержащий дочерний MyClass, созданный с помощью loadNibNamed? Или, в лучшем случае, разве это не экземпляр MyClass с дополнительным промежуточным UIView, содержащим все IBOutlets, которые я первоначально хотел как прямые дети MyClass? Это вызывает небольшое раздражение, когда дело касается таких вещей, как instanceOfMyClass.frame.size.width, поскольку он возвращает 0, когда введенный дочерний UIView возвращает реальный размер кадра, который я искал.

Это то, что я делаю неправильно, что я возился с loadNibNamed внутри метода init? Должен ли я делать что-то подобное?

MyClass *instance = [[MyClass alloc] init];
[[NSBundle mainBundle] loadNibNamed:@"MyClass" owner:instance options:nil];  

Или как это?

MyClass *instance = [[[NSBundle mainBundle] loadNibNamed:@"MyClass" owner:nil options:nil] objectAtIndex:0]; 

Спасибо за любую помощь.

4b9b3361

Ответ 1

Второй вариант правильный. Самый защитный код, который вы можете сделать, выглядит следующим образом:

+ (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;
}

И вызывается вот так:

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

Я предполагаю, что ваш MyClass является подклассом UIView? Если это так, то вам нужно убедиться, что UIView вашего .xib действительно принадлежит классу MyClass. Это определено на третьей вкладке правой части в построителе интерфейса, после выбора вида

Ответ 2

Все, что вам нужно сделать, - создать subview через loadNibNamed, установить фрейм и добавить его в подвью. Например, я добавляю три подзаголовка, используя мой класс MyView, который является подклассом UIView, интерфейс которого определен в NIB, MyView.xib:

Итак, я определяю initWithFrame для моего подкласса 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;
}

Итак, например, в моем UIViewController, я могу загрузить несколько таких объектов с подклассом UIView, например:

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];
}

Сначала я посоветовал использовать контроллеры использования, и я опишу этот ниже ответ на историческую справку.


Оригинальный ответ:

Здесь я не вижу ссылок на контроллеры представлений. Обычно у вас есть подкласс UIViewController, который вы затем создаете с помощью

MyClassViewController *controller = 
  [[MyClassViewController alloc] initWithNibName:@"MyClass" 
                                          bundle:nil];

// then you can do stuff like
//
// [self presentViewController:controller animated:YES completion:nil];

В файле NIB MyClass.xib можно указать базовый класс для UIView, если вы хотите, где у вас есть весь код, связанный с представлением (например, предполагая, что MyClass был подклассом UIView).

Ответ 3

Здесь один метод, который я использую:

  • Создайте подкласс для UIView, это будет называться MyClass
  • Создайте xib файл вида. Открыть в интерфейсе, щелкните File Owner и в Identity Inspector, измените класс к контроллеру родительского представления, например. ParentViewController.
  • Нажмите на представление уже в списке объектов и измените его. класса в Identity Inspector до MyClass.
  • Любые выпуски/действия, которые вы объявляете в MyClass, будут связанный перетаскиванием по клику из представления (не владельца файла). Если вы хотите связать их с переменными из ParentViewController, тогда перетащите мышью из файла Owner.
  • Теперь в вашем ParentViewController вам нужно объявить экземпляр переменная для MyClass.

ParentViewController.h добавьте следующее:

@class MyClass

@interface ParentViewController : UIViewController {
    MyClass *myClass;
}

@property (strong, nonatomic) MyClass *myClass;

Синтезируйте это в своей реализации и добавьте следующее в свой    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];
}