Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

As will be seen from my question, I'm a beginner to iOS development. I have looked at several tutorials and several questions but none seem to be covering my case (I'm probably missing something). I am simply trying to add elements to an array from one class, then call the method that reloads the table data from another class. However, when I try to reload the data after calling the relevant method from another class, the table fails to be loaded (no new data seems to be added). In fact, even the previous values of the array in the table seem to be gone.

Class A:


MyClassA.h

@interface MyClassA : UIViewController <UITableViewDelegate, UITableViewDataSource>
{
     UITableView *tableView;
     NSMutableArray *Elements;
}
@property UITableView *tableView;
@property NSMutableArray *Elements;

-(void) addElement: (NSString *) ElementName;

@end

MyClassA.m

@implementation MyClassA
{
    NSString *ElementName[10];
}

- (void) viewWillAppear:(BOOL)animated
{
    NSLog(@"MyClassA: viewWillAppear");

    ElementName[0] = @" 1 ";
    ElementName[1] = @" 2 ";
    ElementName[2] = @" 3 ";

    Elements = [[NSMutableArray alloc]initWithObjects:ElementName[0], ElementName[1],  ElementName[2],nil];
    self.tableView.dataSource = self;  // The table successfully loads with the data element
}

-(void) addElement: (NSString *) ElementName
{
    NSLog(@"Entered addElement");  // This method is successfully accessed
    Elements = [[NSMutableArray alloc]initWithObjects:ElementName[0], ElementName[1], ElementName[2],nil];   // The problem is here, printing data in this array shows they have no value
    [self.tableView reloadData];    // The problem is here. This does not load the data

}

Class B:


MyClassB.h

@class MyClassA
@interface MyClassB : UIViewController

@property (nonatomic, strong) MyClassA *MyClassACall

-(IBAction) MyButtonClicked: (id) sender;
@end

MyClassB.m

@implementation MyClassB
@synthesize MyClassACall;

-(id) init
{
    self = [super init]
    if (self) {
    NSLog(@"MyClassB init");
    MyClassACall = [[MyClassA alloc] init];
    }
    return self;
}
-(IBAction)MyButtonClicked:(id)sender
{
    NSLog("My button is clicked");
    [self.MyClassAcall addElement:@"NewElement"];
}

I successfully get all the NSlogs, and the table loads the first time correctly with the provided data. However, when trying to add data by loading a method from another class, the table data remains the same and does not get reloaded. What am I missing here?

I have not loaded the whole code to keep this simple. I hope that this makes sense and please let me know if I could clarify. If a similar question exists, please point me to it and I appreciate your help.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
128 views
Welcome To Ask or Share your Answers For Others

1 Answer

I've made a mini tutorial here for you.

OK, so let's say we got a scenario like this:

There are two view controllers - ViewControllerA and ViewControllerB.

ViewControllerA will be in charge of adding items.

ViewControllerB will be in charge of displaying the items.

So ViewControllerA will look like this:

screenshot 1

and ViewControllerB will look like this:

screenshot 2

ViewControllerA.h

#import <UIKit/UIKit.h>

@interface ViewControllerA : UIViewController

@property (nonatomic, strong) NSMutableArray *arrItems;

@end

Here, we store the data source called arrItems as a NSMutableArray. We will pass this array to ViewControllerB later.

ViewControllerA.m

#import "ViewControllerA.h"
#import "ViewControllerB.h"

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.

    [self initViews];
}

-(void)initViews
{
    self.view.backgroundColor = [UIColor whiteColor];

    self.navigationItem.title = @"View Controller A";

    UIButton *btnAddItem = [[UIButton alloc] initWithFrame:CGRectMake(60, 200, 200, 50)];
    [btnAddItem setTitle:@"Add Item" forState:UIControlStateNormal];
    btnAddItem.backgroundColor = [UIColor greenColor];
    btnAddItem.layer.cornerRadius = 5.0;

    [btnAddItem addTarget:self action:@selector(addItem) forControlEvents:UIControlEventTouchUpInside];




    UIButton *btnViewData = [[UIButton alloc] initWithFrame:CGRectMake(60, 300, 200, 50)];
    [btnViewData setTitle:@"View Data" forState:UIControlStateNormal];
    btnViewData.backgroundColor = [UIColor blueColor];
    btnViewData.layer.cornerRadius = 5.0;

    [btnViewData addTarget:self action:@selector(viewData) forControlEvents:UIControlEventTouchUpInside];

    [self.view addSubview:btnAddItem];
    [self.view addSubview:btnViewData];


    // init empty array to hold data source items
    self.arrItems = [[NSMutableArray alloc] init];
}

-(void)addItem
{
    [self.arrItems addObject:@"New Element"];

    NSLog(@"added a new element to arrItems, arrItems now has %u items", self.arrItems.count);
}

-(void)viewData
{
    ViewControllerB *vcB = [[ViewControllerB alloc] initWithItems:self.arrItems];

    [self.navigationController pushViewController:vcB animated:YES];
}

For the green "Add Item" button, we use a method like this to add item to our data source:

-(void)addItem
{
    [self.arrItems addObject:@"New Element"];

    NSLog(@"added a new element to arrItems, arrItems now has %u items", self.arrItems.count);
}

You'll notice when you tap on the green button, you'll get a console log telling you how many items is currently in your array.

Now when we're done adding items, we have the blue "View Data" button which pushes ViewControllerB onto the navigation stack:

-(void)viewData
{
    ViewControllerB *vcB = [[ViewControllerB alloc] initWithItems:self.arrItems];

    [self.navigationController pushViewController:vcB animated:YES];
}

ViewControllerB.h

#import <UIKit/UIKit.h>

@interface ViewControllerB : UIViewController <UITableViewDataSource, UITableViewDelegate>

-(id)initWithItems:(NSArray *)arrItems;

// ----------------------------------------------------------------
// view controller B data source is set from
// view controller A using init method shown above
// ----------------------------------------------------------------
@property (nonatomic, copy) NSArray *arrItems;

@property (nonatomic, strong) UITableView *tableView;


@end

Here, we've declared a init method that takes a NSArray parameter. This method will allow us to inject the data source array from ViewControllerA into ViewControllerB.

Per the usual, we also have the tableView in ViewControllerB.

ViewControllerB.m

-(id)initWithItems:(NSArray *)arrItems
{
    self = [super init];

    if(self)
    {
        self.arrItems = arrItems;
    }

    return self;
}

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.

    [self initViews];
}

-(void)initViews
{
    self.navigationItem.title = @"View Controller B";

    self.tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.height)];
    self.tableView.dataSource = self;
    self.tableView.delegate = self;

    [self.view addSubview:self.tableView];
}

-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return self.arrItems.count;
}

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *cellID = @"cellID";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID];

    if(cell == nil)
    {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellID];
    }

    cell.textLabel.text = self.arrItems[indexPath.row];

    return cell;
}

Notice in the initWithItems: method, we're storing the data source from the passed in parameter arrItems into ViewControllerB's self.arrItems:

-(id)initWithItems:(NSArray *)arrItems
{
    self = [super init];

    if(self)
    {
        self.arrItems = arrItems;
    }

    return self;
}

ViewControllerB can then use this data and display it in the tableView data source methods.

So you end up with something like this if you click Add Item five times:

screenshot 3

Xcode's console also logs 5 items added:

2014-12-08 10:33:39.195 DataPassingDemo[1211:25705] added a new element to arrItems, arrItems now has 1 items
2014-12-08 10:33:40.099 DataPassingDemo[1211:25705] added a new element to arrItems, arrItems now has 2 items
2014-12-08 10:33:40.619 DataPassingDemo[1211:25705] added a new element to arrItems, arrItems now has 3 items
2014-12-08 10:33:41.123 DataPassingDemo[1211:25705] added a new element to arrItems, arrItems now has 4 items
2014-12-08 10:33:41.667 DataPassingDemo[1211:25705] added a new element to arrItems, arrItems now has 5 items

Is that more clear ?


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share

548k questions

547k answers

4 comments

86.3k users

...