从iOS中的另一个类重新加载表数据

时间:2014-12-08 00:01:38

标签: ios objective-c xcode uitableview

从我的问题中可以看出,我是iOS开发的初学者。我已经看过几个教程和几个问题,但似乎没有一个问题覆盖我的情况(我可能会遗漏一些东西)。我只是尝试从一个类向数组添加元素,然后调用从另一个类重新加载表数据的方法。但是,当我尝试从另一个类调用相关方法后重新加载数据时,表无法加载(似乎没有添加新数据)。事实上,即使表格中数组的先前值似乎已经消失。

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

}

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"];
}

我成功获取了所有NSlog,并且表首次正确加载了提供的数据。但是,在尝试通过从另一个类加载方法来添加数据时,表数据保持不变并且不会重新加载。我在这里缺少什么?

我没有加载整个代码来保持这个简单。我希望这是有道理的,如果我能澄清,请告诉我。如果存在类似的问题,请指出我并感谢您的帮助。

3 个答案:

答案 0 :(得分:2)

我已经为你做了一个迷你教程。

好的,所以我们说我们有这样的场景:

有两个视图控制器 - ViewControllerA ViewControllerB

ViewControllerA将负责添加项目。

ViewControllerB将负责显示项目。

所以ViewControllerA将如下所示:

screenshot 1

和ViewControllerB将如下所示:

screenshot 2

ViewControllerA.h

#import <UIKit/UIKit.h>

@interface ViewControllerA : UIViewController

@property (nonatomic, strong) NSMutableArray *arrItems;

@end

在此,我们将名为arrItems的数据源存储为NSMutableArray。稍后我们将把这个数组传递给ViewControllerB。

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];
}

绿色&#34;添加项目&#34;按钮,我们使用这样的方法将项目添加到我们的数据源:

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

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

当您点击绿色按钮时,您会注意到,您将获得一个控制台日志,告诉您阵列中当前有多少项目。

现在,当我们完成添加项目时,我们会看到蓝色&#34;查看数据&#34;将ViewControllerB推送到导航堆栈的按钮:

-(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

在这里,我们已经声明了一个带有NSArray参数的init方法。此方法允许我们将ViewControllerA中的数据源数组注入ViewControllerB。

按照惯例,我们在ViewControllerB中也有tableView。

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;
}

请注意,在initWithItems:方法中,我们将传入的参数arrItems中的数据源存储到ViewControllerB&#39; self.arrItems中:

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

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

    return self;
}

然后,ViewControllerB可以使用此数据并将其显示在tableView数据源方法中。

如果您单击Add Item五次,最终会得到类似的结果:

screenshot 3

Xcode的控制台还记录了5个项目:

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

这是否更清楚?

答案 1 :(得分:1)

首先,我认为,使用C语言将数组作为elementName [10]是合格的方式,但是这样它会溢出,你可以简单地使用带有文字的objective-c样式,或者“initWithCapacity:10”。同时简化您的代码,以这种方式进行更改:

@implementation MyClassA
{
    //NSString *ElementName[10]; // you already have NSMutableArray, why did you do this ?
}

- (void) viewWillAppear:(BOOL)animated
{
    NSLog(@"MyClassA: viewWillAppear");    
    Elements = [@[@"1",@"2",@"3"] mutableCopy];
    self.tableView.dataSource = self;
}

-(void) addElement: (NSString *) ElementName
{
    NSLog(@"Entered addElement");  // This method is successfully accessed
   // You already have initialized array, you need simply to add new element
   [elements addObject: elementName];
    [self.tableView reloadData];
}

答案 2 :(得分:1)

好的,好的。几件事......

您定义Elements数组的方式是一种旧方法,您不需要将ivar声明为属性。

MyClassACall = [[MyClassA alloc] init];正在创建MyClassA的新实例,因此您设置的任何内容都不会真正显示在您的视图控制器上。

如果您需要在一个视图控制器上显示模型并在另一个视图控制器中更新它,我建议集中该模型,以便两个视图控制器都可以访问/改变该模型。 Singleton可能是实现这一目标的最简单方法。