Можете ли да замените NIB файла с UIViewController, който вече е на екрана?

Например:

  1. Създайте нов UIVC, като използвате initWithNibName, като използвате "nib-v1"
  2. Покажете го, напр. използвайки [(UINavigationController) nav pushViewController: myVC]
  3. Променете NIB, който myVC използва на "nib-v2"

Доколкото мога да видя, това е "правилният" подход към дизайна на приложения за много приложения, когато прелиствате информация, където имате нужда от два леко различни екрана на потребителския интерфейс за информацията, която се показва.

Например, повечето от вашите страници са текстови, но някои от тях имат и изображение (помислете за RSS четец, където някои RSS записи имат текст + изображение, някои са само текст).

Справих се с това преди, като имах един NIB файл с втори, невидим, именуван екземпляр на UIView, който наслоих над първия и включвах/изключвах в зависимост от контекста, използвайки флага „скрит“.

Но това очевидно е грешно и губи памет.

Не виждам обаче очевиден начин за „презареждане“ на изгледа от NIB файла. Предполагам, че искам по някакъв начин да възпроизведа магията, която initWithNibName прави?

Подозирам, че това е възможно, но съм сигурен, че ако го направите "по грешния начин", тогава приложението просто ще се срине ужасно.


person Adam    schedule 06.01.2010    source източник
comment
Моля, обяснете какво се опитвате да постигнете с какви проблеми се сблъсквате. Това ще ни помогне много да ви дадем отговори.   -  person sosborn    schedule 15.09.2011
comment
Превключването на изгледи от nib файлове може да бъде тежко. Бих предложил да заредите един nib файл и да превключвате между изгледи, вече заредени в този nib.   -  person sudo rm -rf    schedule 15.09.2011


Отговори (5)


Съгласен съм с Роб, но ако наистина искате да се забърквате със смяната на перото (което е лошо, тъй като може лесно да доведе до висящи указатели и други подобни), може би бихте могли да заредите изгледа от новия перо с метода - (NSArray *)loadNibNamed:(NSString *)name owner:(id)owner options:(NSDictionary *)options на NSBundle и да направите изгледа разменяйки себе си.

По-скоро трябва да използвате различни контролери за изглед за различни типове съдържание. Ако те се различават само леко, все пак можете да помислите за създаване на един базов клас и подкласиране на различните варианти.

person MrMage    schedule 06.01.2010
comment
което е лошо, тъй като може лесно да доведе до висящи указатели -- знаете ли за някакви конкретни примери как може да се случи това? Предполагам, че 100% правилен подход може да бъде пренаписването на NIB-зареждащия код на Apple (който използва интроспекция, AFAICS) - тъй като той вече се разхожда в дървото на обектите, това би предотвратило подобни проблеми - не? да? Мисля да опитам това, но не знам колко проблеми ще си позволя :) - person Adam; 09.01.2010
comment
Използвам тази техника от известно време в различни проекти и винаги работи добре. Никога не съм срещал проблеми с висящи показалци. - person Adam; 10.08.2010
comment
NB: този отговор беше най-добрият по това време, но сега, когато iOS4 е наоколо, UINib е по-добър начин да направите същото нещо - вижте отговора на Матю по-долу - person Adam; 04.04.2012

Винаги можете да изпълнявате

[[NSBundle mainBundle] loadNibNamed:@"FileName" owner:viewController options:nil]];

но това несъмнено наистина ще обърка нещата, ако не сте сигурни какво правите, особено ако view е свързан и в двата писца

Трябва да препроектирате йерархията на своя контролер за изглед, за да превключвате между два различни контролера, които се зареждат от два различни nib файла.


Алтернативно, можете да накарате контролера да управлява размяна на изгледи, които зарежда от различни файлове, които не са свързани с неговия nibName. В такъв случай можете да ги заредите по горния начин. И ще искате техните изходи (например към subviewOne и subviewTwo) да са свързани в различни върхове.

person bshirley    schedule 15.09.2011

Трябва да проверите класа UINib, за да видите дали прави това, което искате. Това ще ви позволи да заредите nib файл и да го запазите в паметта.

Но само за пояснение: искате ли да модифицирате самия файл с перо? Или искате да промените съдържанието на nib файла, когато е зареден в паметта?

Извън главата ми, първото би било доста трудно (не можете да модифицирате оригиналния файл, тъй като той е част от пакета на приложението... може би ще го копирате в папката Documents и ще напишете свой собствен кодер/декодер?) второто е по-лесно, но не съм сигурен каква би била причината? Защо просто не модифицирате viewController/view, след като е бил зареден (в awakeFromNib, например) и, ако искате тези промени да продължат, запишете тези промени във файл след това.

Накратко, не знам точно какво бихте искали да направите, но ми се струват големи шансовете да има по-добър начин да го направите.

person Matthew Gillingham    schedule 15.09.2011
comment
По принцип това, което се опитвам да направя, е да плъзгам изгледите и подизгледите на два UIViewControllers на екрана. Използвах nib файловете, за да направя дизайна по-лесен. Имам нужда обаче от променливите, за да запазя определени стойности, така че всичко, което искам да направя, е да заредя различен писец, за да променя оформленията. - person Chad; 15.09.2011
comment
Мисля, че той казва, че иска да промени йерархията на активния изглед, а не nib файловете - person bshirley; 15.09.2011
comment
точно това, което си мислех - защо да изхвърлям? xib не се променя и използва UINib, за да се справи с кеширането, ниската памет и т.н. - person bryanmac; 15.09.2011
comment
Като казвате, че местите контролерите за изгледи са около екрана и че е необходимо променливите да поддържат определени стойности, казвате ли нещо като, потребителят може да препозиционира изгледите на екрана и аз искам тези позиции да бъдат запазени, дори след приложението е прекратено и презаредено? - person Matthew Gillingham; 15.09.2011
comment
С iOS 5 повечето от това, което се опитвах да направя, което беше необходимо, но трудно, беше коригирано от новите класове на View Container, добавени от Apple. - person Adam; 04.04.2012

Не трябва да променяте какъв NIB файл използва UIViewController. Прикачването на NIB към UIViewController трябва да бъде еднократно събитие. Скритите изгледи са добри; със сигурност не грешат явно. Можете също така програмно да добавяте елементи на изглед след зареждане. Ако правите много от това, можете да пропуснете изцяло NIB и програмно да изградите изгледа в -loadView. Всяко от тях е добре, но не превключвайте NIB след инициализация. Дори не препоръчвам да имате множество NIB, между които избирате за даден клас UIViewController; просто е твърде объркващо. Обикновено всеки NIB трябва да се преобразува в специален клас UIViewController с много подобно (или идентично) име.

В свързана бележка препоръчвам да преместите името на NIB в UIViewController, както е описано в по-ранно публикуване.

person Rob Napier    schedule 06.01.2010
comment
Благодаря, но loadView проваля целта на използването на NIB файлове, така че това не помага тук. Работя с екипи от непрограмисти, които трябва да редактират GUI, така че трябва да използваме NIB файлове за всичко. (което работи добре през повечето време, докато не попаднете в ситуации като тази, в които се проявява липсата на далновидност на Apple. За съжаление, тези ситуации са малко по-чести, отколкото се надявах :( ). - person Adam; 09.01.2010

Търсих отговор на същия проблем и в крайна сметка го реших по следния начин:

UIViewController* ctrler = [[UIViewController alloc] initWithNibName:@"NewControllerNIB" bundle:nil];

// Replace previous controller with the new one
UINavigationController* nav = self.navigationController;
[nav popViewControllerAnimated:NO];
[nav pushViewController:ctrler animated:NO];

Не съм сигурен дали е възможно текущият контролер да бъде освободен, преди да се изпълни повикването за натискане на новия контролер, но досега изглежда, че работи (докато просто не преработя приложението с по-добър подход)

person inolasco    schedule 03.04.2012
comment
Да, ако имате Nav контролер И не ви е грижа за изтриването на UIViewController (NB: Беше ме грижа - не искам да изтривам своя контролер, искам да променя неговите UIView. ViewController има състояние, че има значение!), тогава всичко е лесно. Но в 90% от случаите нямате това. - person Adam; 04.04.2012