возвращение объекта обратно в корневой viewcontroller - PullRequest
1 голос
/ 22 декабря 2011

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

В основном то, что я пытаюсь сделать, очень просто.У меня есть контроллер представления с табличным представлением и кнопка +, которая запускает второй контроллер представления, где пользователь может ввести, скажем, имя, и это имя затем добавляется в первое представление таблицы контроллера представления.Подумайте о контактах на iPhone, где вы можете добавить нового человека (или Amazon, где вы можете добавить новую кредитную карту).

Мой вопрос - каков наилучший способ вернуть эту строку (в данном случае)вернуться к контроллеру представления, где находится таблица?

Люди предложили использовать NSDefaults, Delegate или singleton, ни один из которых не подходит для этого случая (каждый по своей причине).Мне просто нужно вернуть простую строку.

Спасибо за вашу помощь.

Ответы [ 5 ]

4 голосов
/ 22 декабря 2011

Если вы переходите из View Controller A ---> View Controller B, что соответствует вашему случаю, и затем вы хотите передать информацию из B -> A, рекомендуется использовать слабую связь, такую ​​как делегирование. Как вы уже обсуждали, есть несколько вещей, таких как NSUserDefaults, singleton, NSNotification, и может быть гораздо больше.

Но делегирование - лучший и стандартный подход для этого.

1 голос
/ 22 декабря 2011

Вот что вам нужно сделать (обратите внимание, я набираю это у меня в голове, чтобы у компилятора могли возникнуть проблемы с моим синтаксисом).

В интерфейсе контроллера вашего дочернего представления:

@protocol ChildDelegate <NSObject>
- (void)didConfirmName:(NSString*)name
@end

@interface ChildViewController : UIViewController
...

@property (nonatomic, assign) id<ChildDelegate> delegate;

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

- (void)myCustoMethod
{
    ...
    if ([self.delegate respondsToSelector:@selector(didConfirmName:)])
        [self.delegate didConfirmName:NAME_STRING];
}

И в вашем родительском контроллере представления, когда вы создаете экземпляр дочернего контроллера представления, назначьте SELF в качестве делегата:

ChildViewController *vc = [[ChildViewController alloc] init...];
vc.delegate = self;

И внедрить:

- (void)didConfirmName:(NSString*)name
{
    // Do whatever you want with the name here...
}

Также убедитесь, что вы сообщаете компилятору о реализации протокола:

@interface ParentViewController () <ChildDelegate>
@end
1 голос
/ 22 декабря 2011

Три хороших варианта:

1) Пусть первый контроллер вида передаст себя второму контроллеру вида, , чтобы второй контроллер мог отправлять сообщения первому.В идеале, создайте протокол, который принимает первый контроллер, чтобы второй контроллер не зависел от типа первого контроллера, а заботился только о том, чтобы он реализовал протокол:

@protocol Nameable
@property(copy) NSString* name;
@end;

@interface FirstViewController <Nameable>
//...
@end

@implementation FirstViewController
@synthesize name;
//...
@end

Тогда первый контроллер можетсделайте это:

SecondViewController *second = [[SecondViewController alloc]
initWithNibName:nil]; second.thingToName = self;
[self.navigationController pushViewController:second animated:YES];

И когда придет время, второй контроллер сможет это сделать:

self.thingToName.name = nameString;

Детали не так уж и важны - главное знать здесьв том, что если вы хотите отправить сообщение объекту, вам сначала нужен указатель на объект.Когда первый контроллер представления устанавливает second.thingToName = self, он предоставляет этот указатель.

2) Пусть первый контроллер представления создает объект данных , в котором второй контроллер представления может хранить данные, напримерthis:

@interface Person <Nameable>
//...
@end

@implementation Person
@synthesize name;
//...
@end

Теперь первый контроллер представления может создать нового Person и передать следующее:

SecondViewController *second = [[SecondViewController alloc]

Person *person = [[Person alloc] init];
[self.people addObject:person];
initWithNibName:nil]; second.thingToName = person;
[person release];

[self.navigationController pushViewController:second animated:YES];

Это похоже на первый подход, только то, что получает имя, нездесь не контроллер представления, это какой-то контейнер данных (Person).

Здесь вы также можете увидеть значение протокола - обратите внимание, что класс SecondViewController вообще не меняется между первыми вторые подходы. не волнует , разговаривает ли он с контроллером представления, экземпляром Person или чем-то еще ... до тех пор, пока объект реализует протокол Nameable, он счастлив.

3) Обратное направление связи. Вместо того, чтобы заставлять контроллер второго вида отправлять строку, у ее родителя получить строку.Это может быть самым простым решением, хотя оно требует, чтобы у родителя был какой-то способ узнать, что ребенок сделан.Это будет выглядеть примерно так:

@implementation FirstViewController
//...

- (IBAction)addNewName:(id)sender
{
    self.secondController = [[SecondViewController alloc] initWithNibName:nil bundle:nil];
    [self.navigationController pushViewController:self.secondController animated:YES];
}

- (void)viewWillAppear
{
    if (self.secondController != nil) { // we must be returning from the child
        self.name = self.secondController.name;
        self.secondController = nil;
    }
}
@end
1 голос
/ 22 декабря 2011

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

YourViewController * yvc = [(YourAppDelegate *) [[UIApplication sharedApplication] делегат] viewController];

[yvc updateString: @ "Обновленная строка"];

Не забудьте:

#import "YourAppDelegate.h"

Но, честно говоря, я бы использовал шаблон делегата или NSNotification.

1 голос
/ 22 декабря 2011

Вы не возвращаете новую вещь в TableView.Вам нужно обновить источник информации, которая питает ваш tableView.
Таким образом, где данные находятся в месте, куда вам нужно пойти и добавить их, когда вы вернетесь к UITableViewController, вам может потребоваться указать UITableView:reload это данные.

У каждого UIViewController есть дескриптор его родителя, если вам абсолютно необходимо с ним связаться.

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