Додайте об'єкти до NSMutableArray у своєму контролері базового перегляду з другого контролера перегляду, ios

Я весь ранок шукав, як це зробити. У мене є 2 View Controllers . З кореневого View Controller ( ViewControllerA - який є контролером перегляду таблиці) ви можете перейти до другого контролера перегляду ( ViewControllerB ).

In the ViewControllerB, there are two fields: contacts & textBody. When the user is done they can click on "Add". This will then go back to ViewControllerA. What I am trying to do now, is for every time that process occurs, all the information from ViewControllerB the user just added goes into a cell in ViewControllerA. The user can then add as many cells as they like.

Проте, що я не можу зробити, це отримати інформацію через контролери перегляду. Я дивився весь ранок, використовуючи делегат додатків, синглтони, протоколи, спільні властивості тощо! Але я все ще застряг.

What I want to do, but can't, is for every time the user clicks "Add" on ViewControllerB, contacts & texts are put into an array. This array is then put into another array which holds all the smaller arrays which the user has created? If you have an ideas, or links to similar/sample code or tutorials, that would be much appreciated!

2

9 Відповіді

Спробуйте це, використовуючи метод делегації, як показано нижче

Завантажити пробний проект з XIB

Завантажте пробний проект зі стажуванням

ParentViewController.h

#import 

@interface ParentViewController : UIViewController {    
    NSMutableArray *dataArray;
}
- (void)passData:(NSMutableArray *)array;
@end

ParentViewController.m

#import "ParentViewController.h"
#import "ChildViewController.h"

@implementation ParentViewController

- (void)viewDidLoad {
    [super viewDidLoad];

   //Initialise the mutable array.
    dataArray = [[NSMutableArray alloc] init];
}

- (IBAction)btnGoToSecondView:(id)sender {
    ChildViewController *secondVC = [[ChildViewController alloc] initWithNibName:@"ChildViewController" bundle:nil];
    secondVC.delegate = self;
    [self presentViewController:secondVC animated:YES completion:nil];
}

- (void)passData:(NSMutableArray *)array {
    [dataArray addObject:array];
    NSLog(@"Data Passed = %@",dataArray);
}
@end

ChildViewController.h

#import 
#import "ParentViewController.h"

@class ParentViewController;

@interface ChildViewController : UIViewController {    
    NSMutableArray *tempArray;
}

@property (strong, nonatomic) IBOutlet UITextField *txtContact;
@property (strong, nonatomic) IBOutlet UITextField *txtTextBody;
@property(nonatomic, assign) ParentViewController *delegate;
@end

ChildViewController.m

@implementation ChildViewController

- (void)viewDidLoad {
    [super viewDidLoad];

   //Initialise the mutable array.
    tempArray = [[NSMutableArray alloc] init];
}

- (IBAction)btnPassDataBack:(id)sender {
    if([self.delegate respondsToSelector:@selector(passData:)]) {

        [tempArray addObject:_txtContact.text];
        [tempArray addObject:_txtTextBody.text];

        [self.delegate passData:tempArray];
    }
    [self dismissViewControllerAnimated:YES completion:nil];
}

- (void)viewDidUnload {
    [self setTxtContact:nil];
    [self setTxtTextBody:nil];
    [super viewDidUnload];
}
@end

З розколом

If you are using storyboard then create a ParentViewController segue ChildViewController and give it a identifier in my sample it showChildView

Потім використовуйте наступний код, щоб встановити делегат

// Calling the segue to go to the child view and setting up the delegate.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    if ([segue.identifier isEqualToString:@"showChildView"]) {
        ChildViewController *childVC = segue.destinationViewController;
        childVC.delegate = self;
    }
}

Потім, щоб відхилити назад до ParentViewController, використовуйте такий код (з мого зразка)

- (IBAction)btnPassDataBack:(id)sender {
    if([self.delegate respondsToSelector:@selector(passData:)]) {

        [tempArray addObject:_txtContact.text];
        [tempArray addObject:_txtTextBody.text];

        [self.delegate passData:tempArray];
    }
    [self.navigationController popToRootViewControllerAnimated:YES];
}
2
додано
@falky спробуйте вказаний вище код. його робота відповідно до вашої потреби. Ви можете безпосередньо завантажити та перевірити приклад коду зразка
додано Автор icodebuster, джерело
@falky перевірити зразок проекту. Я додав код зразка розкадрування, а також пояснення.
додано Автор icodebuster, джерело
Це було дійсно корисним! спасибі. Єдине, що я не знаю, як реалізувати його за допомогою розкадрування (я не використовую ніби). Також в файлі childViewController.h з'явилася помилка в цьому рядку: @property (nonatomic, assign) ParentViewController * delegate; І я не знаю, як це виправити. Дякую за вашу допомогу
додано Автор falky, джерело
Зразок з розкадруванням буде чудовим. Я прийму це як відповідь теж. Дуже дякую! По-перше, я використовую контролер UINvaigation, по-друге, помилка для властивості: "Проаналізувати проблему, невідоме ім'я типу" ViewControllerA "... Чи важливо, що це tableViewController?
додано Автор falky, джерело
Дуже корисний! Ура :)
додано Автор falky, джерело

Якщо інформація насправді є "глобальною" - у неї є лише один екземпляр по всьому додатку, то вам слід створити синглтон як запропонований DB80Buckeye.

Якщо інформація є чимось, що справді належить ViewController1, і ви хочете, щоб його було змінено в ViewController2 (тобто ViewController2 дійсно є частиною ViewController1, це просто відбувається на іншому екрані), тоді ви повинні передати це як частину конструктора ViewController2 .

-(void)view_controller_1_that_push_view_controller_2_onto_the_stack {
     ViewController2* vc2 = [[ViewController2 alloc] initWithInformation:your_information];
     [self.navigationController pushViewController:vc2 animated:YES];
}

@interface ViewController2 

-(id)initWithInformation:(YourInformationClass*)info;

@end

Інший спосіб - використовувати сповіщення.

1
додано

Якщо інформація насправді є "глобальною" - у неї є лише один екземпляр по всьому додатку, то вам слід створити синглтон як запропонований DB80Buckeye.

Якщо інформація є чимось, що справді належить ViewController1, і ви хочете, щоб його було змінено в ViewController2 (тобто ViewController2 дійсно є частиною ViewController1, це просто відбувається на іншому екрані), тоді ви повинні передати це як частину конструктора ViewController2 .

-(void)view_controller_1_that_push_view_controller_2_onto_the_stack {
     ViewController2* vc2 = [[ViewController2 alloc] initWithInformation:your_information];
     [self.navigationController pushViewController:vc2 animated:YES];
}

@interface ViewController2 

-(id)initWithInformation:(YourInformationClass*)info;

@end

Інший спосіб - використовувати сповіщення.

1
додано

Альтернативно для делегата пропонується використовувати наступне: ViewControllerA.h:

 @property (nonatomic, strong) ViewControllerB* viewControllerB; 

У ViewControllerA.m

if (!self.viewControllerB)
{
     self.viewControllerB = [[ViewControllerB alloc] initWithNibName: @"ViewControllerBr"                                                                                                 bundle: nil];      
}
[self.navigationController pushViewController: self.viewControllerB
                                     animated: YES];

...

- (void) viewWillAppear: (BOOL) animated

   if (self.viewControllerB)
   {
       NSString* contact = self.viewControllerB.contact;
       NSLog(@"%@", contact);
   } 

...

1
додано

Альтернативно для делегата пропонується використовувати наступне: ViewControllerA.h:

 @property (nonatomic, strong) ViewControllerB* viewControllerB; 

У ViewControllerA.m

if (!self.viewControllerB)
{
     self.viewControllerB = [[ViewControllerB alloc] initWithNibName: @"ViewControllerBr"                                                                                                 bundle: nil];      
}
[self.navigationController pushViewController: self.viewControllerB
                                     animated: YES];

...

- (void) viewWillAppear: (BOOL) animated

   if (self.viewControllerB)
   {
       NSString* contact = self.viewControllerB.contact;
       NSLog(@"%@", contact);
   } 

...

1
додано

Я б рекомендував використовувати екземпляр singleton з вашого NSMutableDictionary, оскільки вони вивели мене з вашої конкретної ситуації кілька разів (включаючи власні рамки та UITabBarControllers). Ось приклад, який я використовую для реалізації singleton. Ця методологія також є безпечною для ARC

mySingleton.h

#import 

@interface mySingleton : NSObject {

}
+ (NSMutableDictionary *) myMutableDict;

@end

mySingleton.m

#import "mySingleton.h"

@implementation mySingleton

+ (NSMutableDictionary *)myMutableDict
{
    static NSMutableDictionary *singletonInstance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        singletonInstance = [[NSMutableDictionary alloc]init];

    });
    return singletonInstance;
}

@end

As long as you include mySingleton.h in all of your view controllers you can access the data via [mySingleton myMutableDict]. For example: [[mySingleton myMutableDict] setObject:myObject forKey:myKey];

Удачі!

1
додано

Тут є два способи. Стандартною схемою для цього є делегування. Вам не потрібен синглтон. ViewControllerA керує та перераховує ваші дані. ViewControllerB не потрібно нічого знати про всі ці дані, тому немає підстав виставляти його за допомогою singleton тощо.

Створіть протокол делегатів у файлі заголовка ViewControllerB . Щось на зразок цього:

@protocol ViewControllerBDelegate
- (void)addContact:(NSString *)contact withBody:(NSString *)textBody;
@end

Тепер вкажіть, що ViewControllerA реалізує протокол делегатів у своєму заголовку:

@interface ViewControllerA : UIViewController 

Не забудьте імпортувати ViewControllerB.h у верхній частині заголовка ViewControllerA .

В процесі реалізації ViewControllerA введіть метод делегування, вказаний у протоколі:

- (void)addContact:(NSString *)contact withBody:(NSString *)textBody {
    [self.someArray addObject:[[SomeObject alloc] initWithContact:contact body:textBody]];
    [self.tableView reloadData];
}

Це, очевидно, лише приклад - не впевнені, як ви керуєте своєю структурою даних, і, ймовірно, краще вставити комірку в якесь місце, що має сенс.

Оголосити посилання делегата в заголовку ViewControllerB :

@property (weak, nonatomic) id delegate;

Коли ви вказуєте ViewControllerB , встановіть ViewControllerA як делегат.

ViewControllerB *b = [[ViewControllerB alloc] init...];
b.delegate = self;

У селекторі, що спрацьовує кнопка додати в ViewControllerB , поверніться до делегата, перш ніж з'явитись контролер перегляду зі стек навигації:

[self.delegate addContact:contact withBody:text];

де contact та text - це значення, введені користувачем.

Можна також використовувати блок замість делегата, але принцип однаковий - другий контролер перегляду повинен нести відповідальність за введення вхід у вашому випадку і передачу його назад контролеру перегляду, який керує даними.

1
додано

Тут є два способи. Стандартною схемою для цього є делегування. Вам не потрібен синглтон. ViewControllerA керує та перераховує ваші дані. ViewControllerB не потрібно нічого знати про всі ці дані, тому немає підстав виставляти його за допомогою singleton тощо.

Створіть протокол делегатів у файлі заголовка ViewControllerB . Щось на зразок цього:

@protocol ViewControllerBDelegate
- (void)addContact:(NSString *)contact withBody:(NSString *)textBody;
@end

Тепер вкажіть, що ViewControllerA реалізує протокол делегатів у своєму заголовку:

@interface ViewControllerA : UIViewController 

Не забудьте імпортувати ViewControllerB.h у верхній частині заголовка ViewControllerA .

В процесі реалізації ViewControllerA введіть метод делегування, вказаний у протоколі:

- (void)addContact:(NSString *)contact withBody:(NSString *)textBody {
    [self.someArray addObject:[[SomeObject alloc] initWithContact:contact body:textBody]];
    [self.tableView reloadData];
}

Це, очевидно, лише приклад - не впевнені, як ви керуєте своєю структурою даних, і, ймовірно, краще вставити комірку в якесь місце, що має сенс.

Оголосити посилання делегата в заголовку ViewControllerB :

@property (weak, nonatomic) id delegate;

Коли ви вказуєте ViewControllerB , встановіть ViewControllerA як делегат.

ViewControllerB *b = [[ViewControllerB alloc] init...];
b.delegate = self;

У селекторі, що спрацьовує кнопка додати в ViewControllerB , поверніться до делегата, перш ніж з'явитись контролер перегляду зі стек навигації:

[self.delegate addContact:contact withBody:text];

де contact та text - це значення, введені користувачем.

Можна також використовувати блок замість делегата, але принцип однаковий - другий контролер перегляду повинен нести відповідальність за введення вхід у вашому випадку і передачу його назад контролеру перегляду, який керує даними.

1
додано

Тут є два способи. Стандартною схемою для цього є делегування. Вам не потрібен синглтон. ViewControllerA керує та перераховує ваші дані. ViewControllerB не потрібно нічого знати про всі ці дані, тому немає підстав виставляти його за допомогою singleton тощо.

Створіть протокол делегатів у файлі заголовка ViewControllerB . Щось на зразок цього:

@protocol ViewControllerBDelegate
- (void)addContact:(NSString *)contact withBody:(NSString *)textBody;
@end

Тепер вкажіть, що ViewControllerA реалізує протокол делегатів у своєму заголовку:

@interface ViewControllerA : UIViewController 

Не забудьте імпортувати ViewControllerB.h у верхній частині заголовка ViewControllerA .

В процесі реалізації ViewControllerA введіть метод делегування, вказаний у протоколі:

- (void)addContact:(NSString *)contact withBody:(NSString *)textBody {
    [self.someArray addObject:[[SomeObject alloc] initWithContact:contact body:textBody]];
    [self.tableView reloadData];
}

Це, очевидно, лише приклад - не впевнені, як ви керуєте своєю структурою даних, і, ймовірно, краще вставити комірку в якесь місце, що має сенс.

Оголосити посилання делегата в заголовку ViewControllerB :

@property (weak, nonatomic) id delegate;

Коли ви вказуєте ViewControllerB , встановіть ViewControllerA як делегат.

ViewControllerB *b = [[ViewControllerB alloc] init...];
b.delegate = self;

У селекторі, що спрацьовує кнопка додати в ViewControllerB , поверніться до делегата, перш ніж з'явитись контролер перегляду зі стек навигації:

[self.delegate addContact:contact withBody:text];

де contact та text - це значення, введені користувачем.

Можна також використовувати блок замість делегата, але принцип однаковий - другий контролер перегляду повинен нести відповідальність за введення вхід у вашому випадку і передачу його назад контролеру перегляду, який керує даними.

1
додано
IT KPI iOS
IT KPI iOS
74 учасників

Чат обсуждения IOS. - Оффтоп, флуд, оскорбления и вбросы здесь не приняты. - За нарушение - предупреждение или mute на неделю. - За спам и рекламу - ban. Все чаты IT KPI: https://t.me/itkpi/602

ios_jobs_ua
ios_jobs_ua
27 учасників

Mobile Dev Jobs UA
Mobile Dev Jobs UA
20 учасників

Публикуем вакансии и запросы на поиск работы по направлению iOS, Android, Xamarin, RN и т.д.