Передача данных из контроллера представления в контроллер панели вкладок в iOS

Я разрабатываю приложение для iOS и сейчас в растерянности. Я пытаюсь передать данные из первого контроллера представления на первую вкладку TabBarViewController (с использованием раскадровки). Я нашел много руководств, в которых объясняется, как передавать данные между контроллерами представления, но с моей панелью вкладок ничего не работало. Я знаю, что контроллер панели вкладок содержит своего рода массив представлений. Связь между контроллером представления и контроллером панели вкладок реализуется с помощью перехода (push). Итак, я подумал, что использовать метод prepareForSegue () просто. Как это:

 - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
 if ([[segue identifier] isEqualToString:@"tab"]) {

 // ...

    } 
 }  

К сожалению, связь между контроллером панели вкладок и каждым представлением панели вкладок не вызывает никаких сомнений. Это всего лишь «отношения». Это означает, что нет идентификатора перехода, который я мог бы использовать для вышеупомянутого метода. Есть ли возможность использовать в этом случае prepareForSegue? Если нет, есть идеи, как решить эту проблему? Я знаю, что есть аналогичный вопрос, но ответ был не очень полезным. Нужно ли мне создавать новый файл для каждой вкладки (представления) в контроллере панели вкладок? Или возможно иметь один класс (m. & H.) Для всего контроллера панели вкладок, доступ к нескольким представлениям с помощью objectAtIndex ()?

Заранее спасибо!


person Keks    schedule 19.07.2013    source источник


Ответы (6)


Вот моя установка, которая сработала:

  1. Setup Segue:
    1. Setup View Controller with segue to Tab Bar Controller with 2 child View Controllers in Storyboard
    2. Укажите идентификатор перехода (tab)
  2. Setup Classes in Storyboard:
    1. View Controller class = ViewController
    2. Класс контроллера панели вкладок = TabBarController
    3. Контроллер панели вкладок Класс дочернего контроллера представления = TabsViewController (общий для обоих)
  3. Настройте свойство labelString в контроллере панели вкладок:

    1. In TabBarController.h:

      @property (nonatomic, strong) NSString *labelString;
      
    2. In TabBarController.m:

      @synthesize labelString;
      
  4. Настройте метод prepareForSegue в ViewController.m:

    #import "TabBarController.h"
    
    ...
    
    -(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
        if ([[segue identifier] isEqualToString:@"tab"]){
            TabBarController *tabBar = [segue destinationViewController];
            [tabBar setLabelString:[NSString stringWithFormat:@"This has been set"]];
        }
    }
    
  5. Настройте UILabels для контроллеров представления панели дочерних вкладок.

    1. Drag default UILabel controls into both child View Controllers
    2. Создать недвижимость в TabsViewController.h:

      @property (nonatomic, strong) IBOutlet UILabel *label;
      
    3. Подключите 5.1 и 5.2 в раскадровке

  6. Настройте ViewDidLoad метод в TabsViewController.m:

    #import "TabBarController.h"
    
    ...
    
    @synthesize label;
    
    ...
    
    - (void)viewDidLoad
    {
        [super viewDidLoad];
    
        TabBarController *tabBar = (TabBarController *)self.tabBarController;
        label.text = [NSString stringWithFormat:@"Tab %i: %@",[tabBar.viewControllers indexOfObject:self],tabBar.labelString];
    }
    

Теперь при нажатии на 1-ю и 2-ю вкладки будут отображаться метки Tab 0: This has been set и Tab 1: This has been set соответственно.

person Yazid    schedule 19.07.2013
comment
Вроде логика. Я пытался осознать это, но получаю исключение. В данный момент я не знаю почему .. - person Keks; 19.07.2013
comment
В своем ответе я запутал себя всеми именами классов панели вкладок, поэтому, возможно, я поменял некоторые из них в своем исходном сообщении. Совсем недавно отредактировал для более логичного отображения. Подтверждено, что я работаю с моей стороны. - person Yazid; 19.07.2013
comment
Я думаю, что есть проблема с 'setLabelString', потому что: 2013-07-19 15: 20: 54.412 Мастер iCRS [1364: 11303] - [UITabBarController setLabelString:]: нераспознанный селектор отправлен в экземпляр 0x7550810 2013-07-19 15: 20: 54.414 Мастер iCRS [1364: 11303] *** Завершение работы приложения из-за неперехваченного исключения 'NSInvalidArgumentException', причина: '- [UITabBarController setLabelString:]: нераспознанный селектор отправлен на экземпляр 0x7550810'. - person Keks; 19.07.2013
comment
Как ни странно, я тоже получил это, создавая его с нуля. Вы пробовали очистить папку сборки (Option-Shift-Command-K), а затем перезапустить? - person Yazid; 19.07.2013
comment
@Kalpesh Да, я пробовал, и это тоже возможно. Вы просто переместите свойство в TabsViewController, а в prepareForSegue вам просто нужно будет пройти через весь Контроллер представления дочерних элементов панели вкладок и установить каждый 1, просто у @Keks уже есть TabBarController. - person Yazid; 19.07.2013
comment
@Yazid & Kalpesh: Большое вам спасибо. Оно работает! Причина исключения в итоге заключалась в том, что я забыл настроить классы в раскадровке. ;-) глупая ошибка. Но ваши примеры кода мне действительно помогли! - person Keks; 19.07.2013
comment
@Keks Без проблем :) Рад, что помог. Пожалуйста, примите ответ или хотя бы проголосуйте, если вы уже приняли другой. Спасибо! - person Yazid; 19.07.2013

Если ваша иерархия - Viewcontroller-> UItabbarcontroller-> ViewCOntroller

в моем случае мне нужно отправить данные в marketviewcontroller. В tabcontroller marketviewcontroller присутствует с индексом 0.

  - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
  {
 if ([[segue identifier] isEqualToString:@"tab"])
  {
    UITabBarController *tabar=segue.destinationViewController;
    MarketViewController *marketViewcontroller=[tabar.viewControllers objectAtIndex:0];

   // pass data to market view controller
    [marketViewcontroller passobject:Yourdata];
 //   or 
  marketViewcontroller.value=Yourdata
  } 
  }  

in MarketViewController.h 
 @property(nonatomic,retain) NSString * value;
person Kalpesh    schedule 19.07.2013
comment
Да, иерархия такая. Вы используете один класс для всего контроллера панели вкладок? Или MarketViewController - это первое представление панели вкладок? - person Keks; 19.07.2013
comment
Ладно, думаю, я так и создал. Но что с этим «пассовым объектом»? Я получил следующую ошибку: Нет видимого @interface для «TabOneViewController» объявляет селектор «passpbject». Вы знаете мою ошибку? - person Keks; 19.07.2013
comment
Извините, сейчас было так много ответов. Я очень удивлен. Я попробовал реализовать версию Язида, и теперь она работает. Но я думаю, ваша идея похожа. Большое спасибо за вашу быструю реакцию! - person Keks; 19.07.2013

Как вы показываете свой TabBarViewController из UIViewController?

Я догадываюсь с переходом. Если вы это делаете именно так, вы можете передавать данные этому UITabBarController, который является «родительским» для всех контроллеров внутри вкладок.

Скажем, вы хотите передать строку в UITabBarController, вы должны определить свойство в этом контроллере и установить его перед переходом.

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
  {
      if ([[segue identifier] isEqualToString:@"tab"])
      {
          UITabBarController *tabBarVC=segue.destinationViewController;
          tabBarVC.stringToSet = @"hi";
      }
  }

Затем с помощью метода делегата у вас есть выбранный контроллер представления, поэтому вы можете передать родительское свойство дочерним элементам:

- (void)tabBarController:(UITabBarController *)theTabBarController didSelectViewController:(UIViewController *)viewController {
    viewController.stringToSet = self.stringToSet // self is UITabBarController
}
person ade    schedule 19.07.2013
comment
Спасибо за идею. Да, пользуюсь переходом. У меня есть кнопка в первом контроллере представления, который подключен к контроллеру панели вкладок. А метод делегата выше используется для «отправки» строки каждому дочернему элементу? - person Keks; 19.07.2013
comment
Хорошо, я использую prepareForSegue в ViewController. Затем я создаю свойство в контроллере панели вкладок, верно? Где именно вы вызываете метод делегата? И не могли бы вы рассказать мне, как я могу получить доступ к переданным данным, используя их на панели вкладок? - person Keks; 19.07.2013
comment
Извините, что отвечаю так поздно, возможно, вы уже исправили это. Делегат - очень распространенный паттерн в разработке какао. Вы устанавливаете делегат своего UITabBarController, а затем его методы делегата должны вызываться автоматически. Дополнительная информация здесь: developer.apple.com / library / ios / # documentation / general / - person ade; 22.07.2013

Взгляните на синглтоны. Внутри вкладки вы создаете экземпляр вспомогательного класса, который реализует одноэлементный шаблон, гарантируя, что на самом деле существует только один единственный экземпляр. Это означает, что когда вторая вкладка создает экземпляр того же вспомогательного класса, у нее будет доступ к тому же объекту, который вы можете использовать для обмена своими данными ...

например: http://www.galloway.me.uk/tutorials/singleton-classes/

person Martin Mandl    schedule 19.07.2013
comment
Проблема заключалась в передаче данных из другого контроллера представления на вкладку контроллера панели вкладок. Я думаю, ваш ответ будет полезен, если кто-то пытается передавать данные между разными вкладками панели вкладок, не так ли? - person Keks; 19.07.2013
comment
на самом деле вы можете использовать синглтоны для передачи данных между чем угодно, это даже не обязательно должен быть контроллер представления ... - person Martin Mandl; 19.07.2013
comment
Действительно хорошее замечание, @Martin Mandl. Вы меня вдохновили, использование синглтонов намного лучше для масштабируемого сценария. Спасибо! - person Sonic Master; 29.10.2015

Первым делом:

1- По какой-то причине вы хотите передать данные на свою вкладку ...

or:

2- Вы хотите передать данные на свою вкладку, чтобы затем можно было перейти к другой UIViewController?

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

person Rui Peres    schedule 19.07.2013
comment
Я хочу передать данные, потому что: у меня есть NSDictionary в моем ViewController. Теперь мне нужны элементы этого словаря в контроллере панели вкладок для визуализации определенных значений. - person Keks; 19.07.2013

Самый простой способ - создать собственный класс и установить значение из контроллера в пользовательский класс, а затем получить значение из пользовательского класса в контроллер.

Пример кода здесь:

Например, сначала создайте собственный класс

AppUtility.h

+(void)setXxxName:(NSString *)str;
+(NSString *)getXxxName;

AppUtility.m

static NSString *xxxname;

+(void)setXxxName:(NSString *)str{

   xxxname=str;
 }

+(NSString *)getXxxName{

  return xxxname;
 } 

FirstController.m

импортировать настраиваемый класс в контроллер

#import "AppUtility.h"

установите значение из первого контроллера в настраиваемый класс, используйте приведенный ниже код, чтобы установить значение:

[AppUtility setXxxName:@"xyz"];

Второй контроллер.m

импортировать настраиваемый класс в контроллер

#import "AppUtility.h"

здесь получите значение из настраиваемого класса, используйте приведенный ниже код, чтобы получить значение:

NSString *str = [AppUtility getXxxName];

В классе appUtility Используйте операторы nslog, чтобы проверить правильность значений

person user2998756    schedule 19.11.2013