Динамическая подгрузка xib интерфейсов на iPhone
написал Владимир Пузанов - October 16, 2008 – 15:19Программам общего назначения может быть полезен механизм подгрузки скомпилированных xib прямо из сети. Я уже проводил эксперимент с динамическим меню (где в plist-файле описывалось древовидное меню и действия, вызываемые по разным пунктам). Сейчас захотелось попробовать полноценный динамический интерфейс.И так, приступим. Пример я писал на базе стандартного темплейта с UIView и его контроллером. Ключевой момент - в “самостоятельном” UIView я не нашел простого механизма получения полей. Таким образом, любой передаваемый нам по сети xib должен содержать не простой UIView, а его наследника - RootView.
В самом классе есть одно поле
NSMutableDictionary *fields;
И соответствующее ему read-only свойство:
@property (nonatomic,readonly,retain) NSDictionary *fields;
Главный фокус в том, что если создать поля в Interface Builder, то значения будут устанавливатся через великий и могучий KVC. Для начала засунем на нашу форму три UITextField и кнопку. Кнопка для простоты задачи будет завязана на действие в File’s Owner (суть наш контроллер), а для UITextField мы создадим три поля на RootView (не объявляя их в самом классе), и привяжем к ним соответствующие элементы:
Теперь реализуем основную магию RootView:
@synthesize fields; - (void)setValue:(id)value forUndefinedKey:(NSString *)key { if(!fields) fields = [[NSMutableDictionary alloc] init]; [fields setObject:value forKey:key]; } - (void)dealloc { [fields release]; [super dealloc]; }
С помощью этого нехитрого кода все “виртуальные” поля, описанные в IB попадают в наш словарь fields, который можно использовать в контроллере без прямых привязок:
- (IBAction)doCalculate { UITextField *f1 = [[[self view] fields] objectForKey:@"field1"]; UITextField *f2 = [[[self view] fields] objectForKey:@"field2"]; UITextField *f3 = [[[self view] fields] objectForKey:@"field3"]; f3.text = [NSString stringWithFormat:@"%d", [f1.text intValue] + [f2.text intValue]]; }
(gdb) print-object [[[self view] fields] valueForKey:@"field1.text"] Cannot access memory at address 0x0 (gdb) print-object [[self view] valueForKey:@"fields.field1"] Breakpoint 2, 0x965ffe17 in objc_exception_throw ()
Над этим еще стоит поразмыслить. Но, так или иначе, поставленная задача выполнена.
Обновлено. Что-то я запутался случайно, и перепутал valueForKey, и valueForKeyPath, получить текст поля можно сразу через
[[self view] valueForKeyPath:@"fields.field1.text"]
при этом не нужны никакие приведения к типам. Так же в принцие можно убрать свойство fields, KVC будет находить поле и по iVar.

