Как «подключить» табличное представление к контроллеру представления - PullRequest
7 голосов
/ 06 июня 2011

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

Это все связано с вопросом здесь (вы ненадо посмотреть на это - я все объясню ниже): Передать параметр при инициализации таблицы

Я работал над этой проблемой несколько дней, но я понимаю, что должно быть что-тобольшой я скучаю.Я гуглил и гуглил, и даже купил (и около 50% читал) две книги по Obj-C несколько дней назад, но я все еще цепляюсь за то, что кажется невероятно легким.Я, очевидно, довольно новичок в ООП, но у меня есть посредственные навыки в HTML, Perl, SQL, Python, а также некоторые древние вещи, такие как паскаль и базовый.Я n00b, но не дебил (ну, на самом деле, этот опыт немного меняет мое мнение).

В любом случае, моя конечная цель здесь - просто создать приложение с 8 «нормальными» кнопками наВ первом представлении (уровень 1) каждое из них делает одно и то же - то есть показывает простое табличное представление (уровень 2) с данными в ячейках, по которым можно щелкнуть, чтобы продолжить детализацию до уровня (уровень 3).Очень простая и понятная концепция.Единственная разница между 8 возможными уровнями 2 - это данные, которые будут показаны.Я уже создал sql-запросы, которые работают так, как я хочу для каждой кнопки.

Итак, вот где я стою: у меня есть отлично работающее приложение, которое выполняет все с уровня 2 точно так, как я ожидаю - запросыработа, столы красивые - это здорово.

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

Надеюсь, вы понимаете этот разрыв, который я пытаюсь преодолеть.Поскольку для уровня 2 существует 8 возможностей (с очень незначительными различиями в запросах SQL в одной и той же таблице SQL), я сначала попытался найти способ «передачи» целого числа в представление уровня 2 (в первом приложении) изатем выбираем SQL-запрос на основе того, что было передано (см. ссылку выше для этого фиаско).После того, как я заработал это, я планировал выяснить, как заставить кнопки выполнять «прохождение» позже.Однако, после 16 часов работы, я просто сдался и решил создать 8 различных контроллеров табличного представления, все с почти идентичным кодом, кроме запроса.Таким образом, если бы я мог просто получить ОДНУ кнопку на уровне 1, чтобы просто нажать ОДИН из уровней 2 без параметров, я был бы ужасным, но успешным программистом.

К сожалению, даже это не сработалодля меня.Я перепробовал все возможные комбинации перетаскивания и окна / представления / таблицы, которые я могу придумать в Интерфейсном Разработчике, но независимо от того, что я пытаюсь, данные никогда не загружаются в представление таблицы, даже если это прекрасно работает в моем первом приложении.Я прошел через все строки кода - они одинаковы, за исключением того, что что-то должно «вызвать» или «запустить» часть уровня 2, и я просто не понимаю.

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

Может ли кто-нибудь объяснить мне на концептуальном уровне, что мне нужно здесь делать или чего мне не хватает? Даже если вы дадите мне ссылку на что-то, чтобы прочитать, я был бы очень признателен. Я смотрел десятки часов учебников на YouTube, но я всегда готов к большему.

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

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

Любая помощь приветствуется - спасибо всем большое.

1 Ответ

4 голосов
/ 07 июня 2011

Если я правильно понимаю ваш вопрос, вы спрашиваете, как инициализировать контроллер представления и передать некоторые данные, чтобы изменить его поведение. Ключевая концепция, которую необходимо понять, заключается в том, как объекты инициализируются в Objective-C. Один из наиболее распространенных вопросов, который задают новички в iOS, это:

Как может I pass data между my просмотров ?

Да, там восемь разных ссылок. (Хорошо, эта восьмая ссылка немного не по теме, но она достаточно близка.) Есть несколько способов сделать это, и я кратко рассмотрю их. Я также опишу пользовательские инициализаторы, которые также важны.

Давайте представим, что мы создаем приложение для каталога, в котором показана группа продуктов в различных категориях. Представьте, что наше приложение открывает список продуктов, так же как и приложение Apple Store. Скажем, когда пользователь нажимает на товар, мы хотим показать страницу товара.

  1. Вы можете установить свойства на «следующем» контроллере представления. - Просто мы можем создать подкласс UIViewController и установить свойство productID (которое мы создали). Давайте назовем наш новый UIViewController а ProductPageViewController. Вот как это будет выглядеть:

    - (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath
    
      //Create a ProductPageViewController
      ProductPageViewController *ppvc = [[ProductPageViewController alloc] initWithNibName:@"ProductPageViewController" bundle:nil];
      //set the property on our ProductPageViewController
      [ppvc setProductID:42];
      //We would usually present the PPVC here.
      //After presenting, remember to release the view controller
    }
    

    В первой строке мы создаем контроллер вида продукта. Мы звоним alloc, затем init. (Функции упакованы - то есть мы вызываем init непосредственно для результата метода alloc.)

    Затем мы устанавливаем свойство нашего представления. Теперь вид можно настроить в viewWillAppear и все хорошо.

  2. Вы можете поделиться данными через постоянное хранилище. - Этот метод работает немного по-другому. Контроллеры представления вообще не взаимодействуют, за исключением первого, представляющего второй. Всякий раз, когда значение в первом представлении изменяется (что вы хотите сохранить), вы записываете его в Core Data или NSUserDefaults. Затем новое представление считывает значение по мере необходимости.

    В вашем первом контроллере представления:

    //A method to store the data
    - (void)storeData:(id)pageID{
        [[NSUserDefaults setObject:pageID forKey:@"pageID"];
    }
    
    - (void)showNewPPVC{
    
      ProductPageViewController *ppvc = [[ProductPageViewController alloc] initWithNibName:@"ProductPageViewController" bundle:nil];        
      //Show and then release the PPVC
    }
    
  3. Вы можете использовать пользовательские инициализаторы. - Вероятно, это наиболее интуитивно понятный способ сделать это, как только вы поймете концепцию, потому что это единственный, где данные фактически "передаются". (В отличие от метода 2, где данные не передаются напрямую, и метода 1, в котором данные передаются как свойство.)

    Обратите внимание, что в предыдущих примерах я использовал метод initWithNibName:Bundle. Вы также можете заметить, что UITableViewController s использует другой инициализатор, initWithStyle:. Эти два инициализатора принимают некоторую информацию для нового объекта, чтобы он знал, как загрузить. Давайте сначала посмотрим на первый:

    - (id)initWithNibName:(NSString *)nibNameOrNil Bundle:(NSBundle *)bundleNameOrNil;
    

    Первый аргумент сообщает контроллеру представления, какой файл пера загружать. Я пока проигнорирую второй аргумент, поскольку я никогда не видел ничего переданного, кроме nil. Переходя ко второму примеру:

    - (id)initWithStyle:(UITableViewStyle)style;
    

    Здесь вы можете передать одно из двух UITableViewStyle значений. Это один из способов определения стиля табличного представления (другой способ - непосредственное изменение файла пера).

    Давайте немного расширим эту концепцию до нашего примера. Сейчас я покажу вам, как сделать свой собственный инициализатор. Давайте инициализируем наш экземпляр ProductPageViewController:

    - (id) initWithProductID:(int)productID;
    

    Это достаточно просто. Теперь нам нужно реализовать метод и сделать что-то с идентификатором продукта. Здесь мы начнем с кода barebones, необходимого для «имитации» функциональности инициализатора по умолчанию.

    - (id) initWithProductID:(int)productID{
     self = [super init];
    
     return self;
    }
    

    Этот метод вернет инициализированную копию нашего ProductPageViewController, однако он еще не загрузит наш пользовательский интерфейс из NIB, или, если это будет UITableViewController, он не установит UITableViewStyle. Давайте сначала поработаем с NIB, а затем я покажу, как работает UITableViewController. Итак ...

    - (id) initWithProductID:(int)productID{
     self = [super initWithNibName:@"ProductPageViewController" Bundle:nil];
    
     return self;
    }
    

    Теперь. у нас есть инициализированный ProductPageViewController, загруженный из NIB, но он еще ничего не делает. Обратите внимание, что мы не выставляем аргументы NibName и Bundle, а просто передаем их самим себе. Если вы хотите, вы можете теоретически разоблачить их тоже. Теперь давайте возьмем это productID и сделаем с ним что-нибудь.

    - (id) initWithProductID:(int)productID{
     self = [super initWithNibName:@"ProductPageViewController" Bundle:nil];
    
       if(self){
         self.prodID = productID;
       }
    
     return self;
    }
    

    С нашими последними изменениями наш "PPVC" теперь знает о productID. Он может запрашивать базу данных, как вы хотите, и делать вещи с результатами. Затем вы можете запускать различные запросы на основе этого productID.

Еще два быстрых совета:

  1. Возможно, вы хотите передать несколько аргументов. Конечно, вы можете просто добавить к ним сигнатуру метода - (id) initWithProductID:(int)productID andCategoryID(int)categoryID, но что произойдет, если у вас будет пять, шесть или пятьдесят шесть (да, это много) аргументов? Я бы посоветовал передать коллекцию или массив аргументов.

  2. Чтобы использовать пользовательские инициализаторы с UITableView, вы передаете UITableViewStyle вместо имени NIB. Вот как это может выглядеть:

          - (id) initWithProductID:(int)productID{
            self = [super initWithStyle:UITableViewStyleGrouped];
    
            if(self){
              self.prodID = productID;
            }
    
            return self;
          }
    

При создании подразделов я бы предложил комбинацию постоянных данных и пользовательских инициализаторов. Я также советую взглянуть на методы viewDidLoad и viewWillAppear.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...