2012-02-10 2 views
0

Почему этот метод init возвращает объект из области видимости?Почему этот метод init при загрузке ниба возвращает объект из области видимости?

Используя XCode 4.2, базовый SDK 4.3 и ARC, я пытаюсь загрузить UIView из ниба (а не UIViewController). Мне вообще не нужно использовать UIViewController в этом процессе.

После прочтения этого ответа на S.O. Вопрос здесь, похоже, это может быть сделано: How to load a UIView using a nib file created with Interface Builder (Ответ пользователя «MusiGenesis» описывает процесс)

Я создал подкласс UIView с одним ярлыком:

@interface MyView : UIView 
@property (unsafe_unretained, nonatomic) IBOutlet UILabel *textLabel; 
@end 

В реализации я переопределяю initWithFrame:

- (id)initWithFrame:(CGRect)frame 
{ 
    //self = [super initWithFrame:frame]; 
    self = [JVUIKitUtils initWithNibName:@"MyView" withOwner:self]; 
    if(self) 
    { 
     NSLog(@"Created"); 
    } 
    return self; 
} 

В IB Я создал файл с именем «MyView.xib» с одним представлением. Он имеет метку в качестве подзадачи, и я создал свойство label, перетащив его в h-файл. MyView nib file setup

И в другом файле, я создал этот многоразовое статический метод:

+ (id)initWithNibName:(NSString*)nibName withOwner:(id)uiView 
{ 
    id object = nil; 
    NSArray *bundle = [[NSBundle mainBundle] loadNibNamed:nibName owner:uiView options:nil]; // 1 object, out of scope 
    for(id tempObject in bundle) 
    { 
     if([tempObject isKindOfClass:[uiView class]]) object = tempObject; 
     break; 
    } 
    return object; 
} 

Как вы можете видеть на следующем снимке экрана, пучок имеет одну ссылку на объект, но это выходит за рамки.

и отладка: MyView is out of scope

Это мой код для конкретизации:

subView = [[MyView alloc] initWithFrame:CGRectZero]; // ok 
NSAssert(subView != nil, @"MyView was nil"); // fail 

Любые идеи о том, почему другие С.О. плакат смог заставить его работать, но это не так?

+0

Я понятия не имею, что вы пытаетесь сделать с помощью 'self = [JVUIKitUtils initWithNibName: @" MyView "withOwner: self]', но это абсолютно * WRONG *. –

+0

Я пытаюсь загрузить nib из статического класса. Почему это неправильно? – TigerCoding

+0

Кроме того, вы не можете использовать ARC с базовым SDK 4.3. – hwaxxer

ответ

3

Использование владельца кажется немного запутанным в том, как вы загружаете наконечник. Похоже, вы пытаетесь использовать представление в качестве владельца элемента и первого объекта в нем.

Вы пытаетесь загрузить MyView из своего nib (т. Е. Является классом представления внутри ваших файлов nib, определенных как MyView), или вы пытаетесь загрузить подвью MyView из nib?

Если вид внутри вашего ниба является MyView, вот как его загрузить. Создать статический метод как категории на UIView:

@implementation UIView (NibLoading) 

+ (id)viewWithNibName:(NSString*)nibName 
{ 
    NSArray *bundle = [[NSBundle mainBundle] loadNibNamed:nibName owner:nil options:nil]; 
    if ([bundle count]) 
    { 
     UIView *view = [bundle objectAtIndex:0]; 
     if ([view isKindOfClass:self]) 
     { 
      return view; 
     } 
     NSLog(@"The object in the nib %@ is a %@, not a %@", nibName, [view class], self); 
    } 
    return nil; 
} 

@end 

Это позволит вам загружать любые точки зрения из бобов файла (вид должен быть первым элементом определен в бобах). Вы бы создать представление, как это:

MyView *view = [MyView viewWithNibName:@"MyView"]; 

Если вид внутри пера не MyView, но вы хотите, чтобы загрузить его как подвид из MyView с MyView определяется как владелец файла в файле бобах, сделать это следующим образом:

@implementation UIView (NibLoading) 

- (void)loadContentsFromNibName:(NSString*)nibName 
{ 
    NSArray *bundle = [[NSBundle mainBundle] loadNibNamed:nibName owner:self options:nil]; 
    if ([bundle count]) 
    { 
     UIView *view = [bundle objectAtIndex:0]; 
     if ([view isKindOfClass:[UIView class]]) 
     { 
      //resize view to fit 
      view.frame = self.bounds; 

      //add as subview 
      [self addSubview:view]; 
     } 
     NSLog(@"The object in the nib %@ is a %@, not a UIView", nibName, [view class]); 
    } 
} 

@end 

используя этот подход, просто создать свой вид как обычно с помощью initWithFrame, а затем вызвать loadContentsFromNibName в Лоа содержимого от кончика пера.Вы бы загрузить ваш взгляд, как это:

MyView *view = [[MyView alloc] initWithFrame:CGRect(0,0,100,100)]; 
[view loadContentsFromNibName:@"MyView"]; 
+0

Попробуй это в один момент, объединив его с ответом clairware. – TigerCoding

+0

Вам не нужно их комбинировать. Они представляют собой несколько разные варианты одного и того же подхода. Либо должен работать (хотя у меня меньше кода для реализации ;-)) –

+0

Вторая реализация - это то, что мне нужно, ответит мгновенно. – TigerCoding

0

Ваш [JVUIKitUtils initWithNibName:@"MyView" withOwner:self] подход все неправильно. Когда вызывается метод init, объект уже назначается вызовом [MyView alloc]. Причина, по которой вы связываете вызовы с методом суперинтеграции, заключается в том, что это приведет к полной цепочке вплоть до метода init NSObject, который просто возвращает экземпляр, который он есть.

Установив «self» в значение экземпляра (autoreleased), возвращаемое вашим JVUIKitUtils, вы фактически устанавливаете его на адрес памяти, отличный от того, что было выделено вызовом [MyView alloc], что генерирует ошибку вне области видимости.

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

+ (UIView)newViewWithNibName:(NSString*)nibName withClassType:(Class)uiView 
{ 
    id object = nil; 

    // you need some object to assign nib file owner to. use an NSObject. 
    NSObject* owner = [[NSObject alloc] init]; 
    NSArray *bundle = [[NSBundle mainBundle] loadNibNamed:nibName owner:owner options:nil]; // 1 object, out of scope 
    for(id tempObject in bundle) 
    { 
     if([tempObject isKindOfClass:]) object = [tempObject retain]; 
     break; 
    } 
    [owner release]; 
    return object; 
} 

, а затем называют это нравится:

MyView* subView = [JVUIKitUtils viewWithNibName:@"MyView" withClassType:[MyView class]]; 

Я не проверял этот код. Ваше возражение может измениться.