Лучшая практика: представление подкласса UIView (с собственным xib) в качестве подпредставления UIViewControllers - PullRequest
3 голосов
/ 19 августа 2011

Моя цель состоит в том, чтобы иметь подкласс UIView (давайте назовем его infoView), разработанный в его собственном XIB, чтобы я мог представить его во многих UIViewController.

Проблема: До сих пор, когда я добавлял UIView к UIViewController, мне всегда приходилось делать UIViewController владельцем файла .xib * UIView файла, чтобы загрузить представление с чем-то вроде:

...
//this is inside the calling UIViewController's method
// InfoView *infoView is ivar and a subclass of UIView
infoView = nil; 
NSArray *bundle = [[NSBundle mainBundle] loadNibNamed:@"InfoView"
                                                owner:self options:nil];

for (id object in bundle) {
    if ([object isKindOfClass:[InfoView class]])
        infoView = (InfoView *)object;
}   

[[self view] addSubview:infoView]; 
...

Но я хочу использовать один и тот же UIView во многих различных UIViewController, поэтому я на самом деле не хочу владельца файла, за исключением, может быть, самого класса. В вопрос Томаса он сам устанавливал UIView в качестве владельца файла, но безуспешно.

В ответах я нашел решение установить для владельца файла значение nil. Для этого мне пришлось добавить все вызывающие объекты UIViewController из библиотеки объектов Interface Builder в файл InfoView.xib и соединить их с их infoView выходами.

Но это не так. Так что здесь я хотел бы собрать решения для
инкапсулируйте UIView вместе с его xib-файлом, чтобы использовать его во многих различных контроллерах представления. Как вы, ребята, справляетесь с этим?

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

EDIT:

infoView - это что-то вроде наложения, которое появляется, когда пользователь нажимает кнопку на одном из контроллеров представления. Это НЕ «основной» вид контроллеров View. Это дает подробную информацию о представлении его контроллера представления superviews и исчезнет впоследствии. Я только заполню infoView разным содержимым, выкинул все вызывающие контроллеры вида.

Ответы [ 4 ]

3 голосов
/ 15 августа 2012

Как и Hollance ответ указывал, что я использую UINib.

Чтобы использовать его, оставьте владельца файлов .xib nil и поместите все настройки infoView внутриinitWithCoder: метод реализации вашего класса InfoView.Это будет вызвано, если вы получите InfoView.xib вроде:

// here InfoView is the name of the .xib file
UINib *infoNib = [UINib nibWithNibName:@"InfoView" bundle:nil];

NSArray *topLevelObjects = [infoNib instantiateWithOwner:self options:nil];

QInfoView *infoView = [topLevelObjects objectAtIndex:0];
1 голос
/ 03 апреля 2013

И еще один способ - создать свой собственный «контроллер» на основе NSObject для определения собственного жизненного круга (вместо стандартного UIViewController жизненного круга).

Например:

BaseSubview.h:

@interface BaseSubview : NSObject {
    UIView* _view;
}

@property (nonatomic, retain) IBOutlet UIView* view;

- (void)myMethod;

@end

BaseSubview.m:

#import "BaseSubview.h"

@implementation BaseSubview

@synthesize view = _view;

- (id)init
{
    self = [super init];
    if (self) {
        // ...
    }
    return self;
}

- (void)dealloc
{
    [_view removeFromSuperView];
    [super dealloc];
}

- (void)myMethod
{
    // view specific logic here
    _view.backgroundColor = [UIColor redColor];
}

@end

InfoView.h:

#import "BaseSubview"
@interface InfoView : BaseSubview {
    UILabel* _labelInfo;
}

@property (nonatomic, retain) IBOutlet UILabel* labelInfo;

@end

InfoView.m:

#import "InfoView.h"

@implementation InfoView

@synthesize labelInfo = _labelInfo;

- (id)init
{
    self = [super init];
    if (self) {
        // ...
    }
    return self;
}

- (void)myMethod
{
    // view specific logic here
    _labelInfo.text = @"current time...";
    [super myMethod];
}

@end

InfoView.xib:

  • fileвладелец InfoView
  • назначение выходов как обычно
  • представление является родительским для всех других элементов управления (таких как метки и т. д.)

HugeAndComplicatedViewController.h:

// ...
// among other var definitions
InfoView* _infoView;
// ...

HugeAndComplicatedViewController.m , самая интересная часть:

// when you decide to show your view
// probably in loadView
_infoView = [[InfoView alloc] init];
[[NSBundle mainBundle] loadNibNamed:@"InfoView" owner:_infoView options:nil];
[self.view addSubview:_infoView.view];

// possibly perform specific logic
[_infoView myMethod];

// no need sub-view any more
// probably in dealloc
[_infoView release];

Так что теперь у вас есть собственный подвид слогика и дизайн отделены от "огромного и сложного" view-контроллера.Он может иметь любой жизненный цикл, необходимый для вашего текущего проекта.

1 голос
/ 19 августа 2011

Итак, вы хотите загрузить UIView из кончика, который вы хотите использовать в более чем одном UIViewController, и вы хотите подключить его к розетке на каждом из этих контроллеров представления.Это правильно?

Затем создайте подкласс UIViewController (назовем его FakeViewController) со свойством IBOutlet.Установите FakeViewController в качестве владельца файла пера и подключите UIView к его выходу.

Готово.

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

О, и если у вас ОС 4.0 и выше, используйте UINib для загрузки файла пера.

0 голосов
/ 19 августа 2011

нужно ли infoView быть подпредставлением?

в вашем представлении Контроллер:

-(id) init {
    self = [super initWithNibName:@"myNib" bundle:nil]; 
    if (self) {
        // code here
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...