NSMutableArray возвращает NULL - PullRequest
       12

NSMutableArray возвращает NULL

0 голосов
/ 04 ноября 2011

Я пытаюсь добавить объекты в NSMutableArray из другого класса (secondViewController), а затем добавить его в мой UITableView в моем FirstViewController, но он возвращает ноль, когда я печатаю его с помощью NSLog. Вот моя установка.

FirstViewController.h:

@interface FirstViewController : UIViewController <UITableViewDelegate,UITableViewDataSource>{
    IBOutlet UITableView *mytableview;
    NSMutableArray *mytableinfo;
}
@property (nonatomic,retain) IBOutlet UITableView *mytableview;
@property (retain) IBOutlet NSMutableArray *mytableinfo;

FirstViewController.m

#import "FirstViewController.h"
#import "SecondViewController.h"
@synthesize mytableinfo,mytableview;
-(IBAction)addShift:(id)sender{
SecondViewController *secondViewController = [[SecondViewController alloc]init];
[self presentModalViewController:secondViewController animated:YES];
}
- (void)viewDidLoad
{
    mytableinfo = [[NSMutableArray alloc]init];
    [super viewDidLoad];
}

SecondViewController.m

#import "SecondViewController.h"
#import "FirstViewController.h"

@implementation SecondViewController
@synthesize dateformatter,mydatepicker,startingTime;

-(IBAction)saveShift:(id)sender{
    FirstViewController *firstViewController = [[FirstViewController alloc]init];
    [firstViewController.mytableinfo addObject:@"Hello world"];
    NSLog(@"%@",firstViewController.mytableinfo);
    [self dismissModalViewControllerAnimated:YES];
}

Моя цель - в конечном итоге накормить mytableview из mytableinfo. Я даже не уверен, что это лучший способ сделать это. Любой совет будет оценен.

Ответы [ 5 ]

4 голосов
/ 04 ноября 2011

В SecondViewController вы создаете FirstViewController с помощью alloc init.В этот момент mytableinfo на FirstViewController равна нулю, потому что вы не выделяете до viewDidLoad.

Что загружает SecondViewController?Потому что вы отклоняете это модально.Если это FirstViewController, то когда вы выделяете init первый контроллер представления, вы не вызываете экземпляр, который представил его модально.

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

Как создать массив NSMutable, к которому можно обращаться из разных контроллеров представления

Другой способ связимежду представлениями один делегат передает делегат (обратный вызов) другому представлению.Это позволяет другому представлению не быть связанным с другим представлением - оно знает только о протоколе для делегата.

Что именно делает делегат в проекте xcode ios?

2 голосов
/ 04 ноября 2011

В вашем "SecondViewController" есть странный момент, который вы отклоняете, как будто он модальный. Тогда у меня вопрос ... кто начал модальную презентацию? "FirstViewController"? Если это так, то почему вы создаете новую, после того как вторая, которая запустила, возобновит свою деятельность?
Другая вещь, которую я не понимаю, это то, что назначенный инициализатор для UIViewController -

- (id)initWithNibName:(NSString *)nibName bundle:(NSBundle *)nibBundle

Вы можете передать nil обоим аргументам, если нет необходимости связывать nib.

И, наконец, если вам нужно вернуть NSMutableArray в 1-й ViewController (VC) из 2-го VC, который был представлен модально 1-м, вы можете сделать это во 2-м VC:

- (id)initWithMutableArray:(NSMutableArray *)theArray    {
//... put standard init code here   }

И сделайте это инициализатором по умолчанию вашего второго VC. Но это имеет смысл только в том случае, если 2-му VC абсолютно необходим изменяемый массив.


А теперь из-за моего любопытства, потому что я не понимаю эту строку

@property (retain) IBOutlet NSMutableArray *mytableinfo;

Почему это IBOutlet? Это выглядит как потенциальный источник проблем. IBOutlet - это обычно указатели на элементы пользовательского интерфейса в xib-файле.

1 голос
/ 04 ноября 2011

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

NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];

Затем вы можете назначить объекты для каждой клавиши по умолчанию, что на самом деле является просто списком (который представляет собой просто список клавиш с объектами, связанными с ними.

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

[defaults setObject:mytableinfo forKey:@"tableInformationKey"];

Затем, когда вы захотите получить доступ к этим данным, вы можете сказать:

NSMutableArray* tableInfoCopy = [defaults mutableArrayValueForKey:@"tableInformationKey"];

Это сделает вас копией массива, который вы сохранили в NSUserDefaults (доступ к NSUserDefaults можно получить из любого места в вашем приложении), так что вы сможете вносить изменения в этот изменяемый массив, который вы только что создали. Как только вы закончите вносить изменения, вы можете переназначить их на NSUserDefaults так:

[defaults setObject:tableInfoCopy forKey@"tableInformationKey"];

Итак, когда вы заполняете свой UITableView, в

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 

поставить что-то вроде:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{
    NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Foobar"];
    if (cell == nil) {
        // No cell to reuse => create a new one
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"Foobar"] autorelease];

        // Initialize cell with some customization
        cell.selectionStyle = UITableViewCellSelectionStyleBlue;
        cell.textLabel.textColor = [UIColor blackColor];
    }

    NSArray* arrayOne = [defaults objectForKey:@"tableInformationKey"];

    NSString* title = [arrayTwo objectAtIndex:indexPath.row]; 
    //this goes to the index in the array of whatever cell you are
    // at, which will populate your table view with the contents of this array (assuming the array contains strings)

    // Customize cell
    cell.textLabel.font = [UIFont fontWithName:@"Helvetica" size:25];

    return cell;
}
0 голосов
/ 05 ноября 2011

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

@synthesize array4Test;
- (id)initWithMutableArray:aMutableArray
{
self = [self initWithNibName:nil bundle:nil];
if (self)
{
    self.array4Test = aMutableArray;
}
return  self;
}
- (void)dealloc 
{    
//  HERE clean up the property is set to retain.
self.array4Test = nil;
[super dealloc];
}

Вот код для первого просмотра

-(IBAction)addShift:(id)sender{
SecondViewController *secondViewController = [[SecondViewController alloc] initWithMutableArray:self.mytableinfo];
[self presentModalViewController:secondViewController animated:YES];
}
-(void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
[self.mytableview reloadData];
NSString *aString = [mytableinfo lastObject];
if (aString)
{
    NSLog(@"This just came back from the second View\n%@", aString);
}
}
0 голосов
/ 04 ноября 2011

Использовать их проще всего, поместив массив в ваш AppDelegate

// populate appDelegate's array
AppDelegate *appDelegate = (myAppDelegate *) [[UIApplication sharedApplication] delegate];  
[appDelegate.arrayMyTableInfo addObject:@"HelloWorld"];
...