1. Андрей

    05.11.2020 15:54

    Добрый день,
    Никак не могу разобраться, как без использования UINavigationController осуществить переход между формами.

    Подскажите, пожалуйста, какова должна быть структура форм(ы) и кого с кем связать.
    Ссылки на примеры приветствуются.
  2. Evgeniy Krysanov

    05.11.2020 21:47

  3. Андрей

    05.11.2020 23:17

    Спасибо, Евгений. Я читал Вашу статью перед тем, как задал вопрос.
    Дело в том, что используется лишь UIToolBar. UINavigationController и UINavigationBar нет.
    Возможно, я чего-то не понимаю. Стоит задача: переключаться между формами по нажатии на кнопки ВНИЗУ экрана. Будьте добры, объясните, как реализовать данный функционал.
  4. NYN'ja

    06.11.2020 10:54

    Андрей

    у меня несколько видов добавлены к главному контроллеру вида, а он в свою очередь точнее его view является подвидом окна.
    Приблизительно так
    [mainViewController.view addSubview:view1];
    [mainViewController.view addSubview:view2];
    [window addSubview: mainViewController.view];


    (view1 и view2 могут быть видами других контроллеров, например вместо view1 можешь поставить ViewController1.view, в общем любой нужный тебе вид).

    я решил проблему переключения между видами способом отключения видимости
    изначально все временно ненужные виды делаю невидимыми
    например подобной строкой.
    [view1 setHidden:YES];

    а потом при нажатии на кнопку можно спрятаному виду послать ту же комманду только с параметром "NO",
    А вид который надо спрятать - та же комманда, параметр "YES"
    Иными словами вид mainViewController.view постоянно на экране, но рисуется только один из его подвидов.

    Но это только как вариант если необходимо быстро переключаться не уничтожая виды. Потому нужно следить за памятью, особенно если видов много и они перегружены всякими там картинками к примеру - программа может вылететь от нехватки памяти.
    В таком случае лучшим вариантом будет освобождение вида, а когда он снова нужен - реинициализация, В данном случае появится больше тормозов при переключении, но реже будешь получать всякие MemoryWarning.
    Так что выбор - либо память(стабильность работы программы), либо производительность.

    Дополнительно посмотри в документации информацию по UIView.
    особенно его методы в Managing the View Hierarchy
    пара методов оттуда переключающие виды
    – bringSubviewToFront:
    – sendSubviewToBack:
  5. Андрей

    07.11.2020 16:28

    NYN'ja , мне, видимо сильно не хватает теоретических знаний в данной области. У меня не получилось воспроизвести то, что Вы описали.
    Начнем с того, что я так и не понял, какова архитектура приложения:
    1. используется один .xib файл или два или же это вообще не принципиально?
    2. как выглядит иерархия контролов?
    3. какие объекты связаны между собой.

    Короче, споткнулся на ровном месте и буксую уже четвертый день.
    Если б можно было опубликовать где-то исходники самого простого приложения, реализующего данную задачу, было бы здорово.

    Заранее благодарен за помощь.
  6. NYN'ja

    10.11.2020 11:20

    1. У меня все виды и контролы в одном xib-файле.
    2. Для каждого View у меня отдельный UIViewController(наследуемый).
    В дальнейшем в методе applicationDidFinishLaunching делегата приложения(создается автоматом, при создании проекта) я организую саму иерархию контролов.
    Чтобы какой-нибудь view отобразился на экране он должен стать подвидом главного окна приложения(свойство window в *DelegateApp). Также у каждого view(к window это тоже относится) может быть много subview.
    Организовываю эти подвиды следующим образом:
    у одного из контроллеров(UIViewController - назовем его MainViewController, разумеется он наследник от UIViewController) есть свойство view(как и у любого другого контроллера вида). Этот вид я добавляю как подвид к окну:
    [window addSubview: mainViewController.view];
    И до конца программы он у меня прицеплен к этому окну и, так сказать все время видим. Сам по себе этот вид пуст, ничего не отображает. К этому виду(не контроллеру, а виду) мы будем аналогично цеплять в качестве подвидов более значимые виды относящиеся к другим контроллерам.

    [mainViewController.view addSubview:anotherViewController.view];

    или, если у вида нет своего контроллера:

    [mainViewController.view addSubview:view2];

    таким образом на текущий момент организовано следующим образом
    окно(window )
    ......./
    главный_вид(mainViewController.view)
    ,,,,,,/......\
    подвид1 подвид2(anotherViewController.view и view(наследует UIView))

    после этого, вид который ты должен отобразить сразу после загрузки программы должен остаться вдидимым, а всем остальным видам посылаешь сообщение [view2 setHidden:YES] например.
    Затем пользователь чтото нажал в этом виде и появилась необходимость переключиться в другой вид - выполняешь комманды:
    [view2 setHidden:NO];//проявляешь нужный вид
    [anotherViewController.view setHidden:YES];//прячешь старый вид(в памяти он висит)
    Переключился.
    Равно как и наоборот можно вернуться.
    Это вполне рабочий пример из одной из моих программ.
    Если непонятно как созданы виды и контроллеры - то лучше почитать статьи в блоге с начала, желательно все проработать, поищи описание создания класса из Интерфейс Билдера.

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


    3.если насчет связывания через оутлеты в билдере, то помочь вряд ли смогу, все зависит от конкретного проекта. А взаимосвязь в коде между видами я попытался обьяснить. Не знаю получилось ли, если нет, то могу разве что только рекомендовать обратиться к документации по UIView. И экспериментировать. Сам долго разбирался с этими видами.
  7. Rozo4ka

    11.11.2020 01:20

    Всем привет!
    Пытаюсь сделать нечто похожее, сейчас у меня на window цепляются два subview, у каждого свой вью контроллер, лежат они в двух разных xib-файлах.. ну и есть еще xib MainWindow - там Window и контроллеры. Проблема сейчас в том, как мне из метода, срабатывающего по нажатию на кнопку в одном из этих view, спрятать его и сделать видимым другой.. Вопрос мой из разряда "полный newbie", учиться программированию под iPhone начала меньше недели назад, так что очень буду благодарна за совет и помощь :)

    Прячу текущий вью я так:
    [self setHidden:YES];
    а вот как показать второй - не знаю..

    Пробовала так:
    @interface SomeView : UIView {

    //тут кучка переменных и IBOutlet'ов

    vcOptions* vcOptions1; // vcOptions - view controller второй вьюшки
    }
    - (IBAction)ShowAnotherView;
    @property (nonatomic, retain) IBOutlet vcOptions *vcOptions1;

    @end

    и

    @implementation SomeView

    //...
    @synthesize vcOptions1;
    //...

    - (IBAction)OpenOptions {
    [vcOptions1.view setHidden:NO];
    [self setHidden:YES];
    }
    //...
    @end

    Понимаю, что это неправильный вариант, есть предположение, что надо как-то пробраться к делегату, ибо view к окну прикручивались в нем.. но не очень представляю как)
  8. Rozo4ka

    11.11.2020 01:21

    - (IBAction)OpenOptions {
    [vcOptions1.view setHidden:NO];
    [self setHidden:YES];
    }

    тут имелось в виду:

    - (IBAction)ShowAnotherView {
    [vcOptions1.view setHidden:NO];
    [self setHidden:YES];
    }
  9. NYN'ja

    11.11.2020 12:02

    не забудьте подключить в классе вашей версии UIViewController-a класс делегата приложения
    #import "MYAppDelegate.h"

    а потом к делегату добраться легко:
    MYAppDelegate *appDelegate =[[UIApplication sharedApplication] delegate];

    После можно обращаться к окну и другим свойствам(например контроллерам и их видам) делегата

    appDelegate.window (доступ к окну)
    appDelegate.viewController1 (доступ к одному из контроллеров)
    appDelegate.viewController1.view (доступ к виду контроллера)

    Хотя не очень понял структуру видов в вашей программе.
    Я так понимаю у вас есть window в делегате.
    И есть виды(с контроллерами), подключенные к этому окну, или подключен к окну только один вид, а второй, по цепочке, является подвидом первого вида?
    Я к тому что если вдруг они по цепочке друг ко другу подключены, то если superview(надвиду) послать сообщение сделаться невидимым, то все его подвиды тоже исчезнут, независимо от того что сами они "видимые". Переключение таким способом возможно только для видов на одном уровне вложености.

    И опишите как отрабатывает ваш код:
    -один вид исчезает, а второй не появляется
    -вообще не реагирует на нажатие(не заходит в метод, проверяется брекпоинтом)
    -В метод заходит но визуально команды абсолютно не выполняются
    -выдает ошибки, компиляции
    -выдает ошибки во время исполнения
    -или свой вариант

    Или проблема решилась через делегат
  10. Rozo4ka

    11.11.2020 16:03

    Спасибо огромное! Проблема решилась через делегат.

    Не хватало
    MYAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
    Раньше код отрабатывал как в первом варианте - один вид исчезал, а второй не появлялся, теперь всё работает как и было задумано, а виды находятся на одном уровне вложенности, оба подключены к окну.

    Попутно возник вопрос на будущее - как реализовать вариант с освобождением вида и реинициализацией другого вида..

    сейчас соответственно код метода:

    myappDelegate *appDelegate =[[UIApplication sharedApplication] delegate];
    [appDelegate.vcOptions1.view setHidden:NO];
    [self setHidden:YES];

    Правилен ли будет такой вариант?

    myappDelegate *appDelegate =[[UIApplication sharedApplication] delegate];
    [appDelegate.window addSubview:appDelegate.vcOptions1.view];
    [appDelegate.vcGame1 release];

    Попробовала запустить - переключения работают: 1->2->1->2->_TERMINATING_DUE_TO_UNCAUGTH_EXEPTION_

    Удивило то, что первые несколько раз они все же отработали, и только потом словился эксепшн - причем ловится все время в одном и том же месте.. (кнопка на втором виде становится синей и приложение зависает, _nibName принимает значение invalid)
  11. NYN'ja

    11.11.2020 18:48

    Скорее всего свойство vcGame1 имело несколько retainCount(по-моему так пишется).
    То есть на него было несколько ссылок. При сообщении release счетчик уменьшается на 1. И только тогда, когда он достигает 0 обьект удаляется. И в дальнейшем попытка обратиться к нему, вызовет ошибку, потому как его уже не существует.Часто если что-то отрабатывает несколько раз потом грохается - проблема скорее всего в ретайн\релиз.

    Еще у любого view есть метод removeFromSuperview. Которым он сам себя убирает из его, скажем, родителя. При этом он не просто удаляет себя из массива подвидов, но еще и автоматом релизит себя. Если счетчик ссылок на него равнялся до этого единице, то после релиза он освобождает память. Потому лучше его не релизить, а исключать из подвидов. Необходимо исключить обращение к нему после освобождения(и не релизить его больше чем надо).

    Насчет реинициализации - тоже самое что и инициализация нового обьекта через
    [[MyViewClass alloc] init];
    А затем после инициализации подключайте его к окну или к чему бы то ни было.
  12. NYN'ja

    14.11.2020 17:06

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

    Вместо релиза вида нужно послать виду сообщение [view1 removeFromSuperview](в синтаксисе мог ошибиться, наизусть методы не помню).
    Этот метод удаляет вид из массива подвидов его родителя, и автоматом должен саморелизится.
    Если количество ссылок на вид было не больше 1, то вид после этого грохнется из памяти.

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

    Почитайте документацию на NSObject, а конкретно о свойствах и методах: retain, release, dealloc, retainCount, init. По моему все необходимые в этом плане места указал.
  13. Андрей

    24.11.2020 15:37

    Спасибо за ответы.
    Необходимое решение было найдено тут: http://www.appsamuck.com/day2.html
    По нажатию на кнопку i, показывается другой view. Убираем анимацию и наслаждаемся :)
Страницы
(1)

bbcode

.