IT IS SOLVED BY @T-X. I’ve marked the changes with “// SOLUTION” in the code!!!
I have the following issue, if I presentModalViewController, the NSMutableArray “projectsArray” gets reset.
Here is my code:
Here the .h file:
// ViewController.h
#import <UIKit/UIKit.h>
@class AddProject;
@interface ViewController : UIViewController <UITableViewDelegate, UITableViewDataSource>
{
IBOutlet UITableView *projectsTableView;
UIAlertView *reallyDelete;
BOOL candelButtonClicked;
NSIndexPath *actualIndexPath;
NSMutableArray *projectsArray;
NSInteger ID;
NSString *NAME;
AddProject *addProject;
**ViewController *viewContr; // SOLUTION**
}
- (IBAction)addNewProject:(id)sender;
- (void)addToTableView:(NSString *)projectName;
@property (nonatomic, retain) UIAlertView *reallyDelete;
@property (nonatomic) NSInteger cancelButtonIndex;
@property IBOutlet UITableView *projectsTableView;
@property (nonatomic, retain) AddProject *addProject;
**@property (nonatomic, retain) ViewController *viewContr; // SOLUTION**
@end
Here the .m file:
// ViewController.m
#import "ViewController.h"
#import "CustomTableCell.h"
#import "AddProject.h"
@interface ViewController ()
@end
@implementation ViewController
**@synthesize viewContr; // SOLUTION**
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
projectsArray = [[NSMutableArray alloc] init];
ViewController *element = [[ViewController alloc] init];
element->ID = 1;
element->NAME = @"Demo project";
NSLog(@"viewdidload");
[projectsArray addObject:element];
NSLog(@"1. Array length: %d", [projectsArray count]);
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if ([projectsArray count] < 1) {
NSLog(@"2. Array length: 0");
return 0;
} else {
NSLog(@"2. Array length: %d", [projectsArray count]);
return [projectsArray count];
}
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 78;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *customTableCellIdentifier = @"CustomTableCell";
CustomTableCell *cell = (CustomTableCell *)[tableView dequeueReusableCellWithIdentifier:customTableCellIdentifier];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"CustomTableCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
ViewController *element = [[ViewController alloc] init];
element = [projectsArray objectAtIndex:indexPath.row];
cell.nameLabel.text = element->NAME;
cell.prepTimeLabel.text = [NSString stringWithFormat:@"%i", element->ID];
NSLog(@"3. Array length: %d", [projectsArray count]);
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
// Delete the row from the data source
reallyDelete = [[UIAlertView alloc] initWithTitle:@"Deleting" message:@"Do your really want to delete that row?" delegate:self cancelButtonTitle:@"No" otherButtonTitles:@"Yes", nil];
[reallyDelete show];
actualIndexPath = indexPath;
}
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
if (buttonIndex != [reallyDelete cancelButtonIndex])
{
//If "Yes" clicked delete
[projectsArray removeObjectAtIndex:actualIndexPath.row];
NSLog(@"delete row");
[self.projectsTableView deleteRowsAtIndexPaths:[NSMutableArray arrayWithObjects:actualIndexPath, nil] withRowAnimation:YES];
[self.projectsTableView reloadData];
}
}
#pragma mark Edit
- (IBAction)addNewProject:(id)sender {
NSLog(@"4. Array length: %d", [projectsArray count]);
AddProject *addProjectView = [[AddProject alloc] initWithNibName:@"AddProject" bundle:nil];
NSLog(@"4.1 Array length: %d", [projectsArray count]);
addProjectView.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
NSLog(@"4.2 Array length: %d", [projectsArray count]);
addProjectView.modalPresentationStyle = UIModalPresentationFormSheet;
NSLog(@"4.3 Array length: %d", [projectsArray count]);
**addProjectView.viewContr = self; // SOLUTION**
[self presentModalViewController:addProjectView animated:YES];
NSLog(@"4.4 Array length: %d", [projectsArray count]);
addProjectView.view.superview.frame = CGRectMake(addProjectView.view.center.x/2.5, addProjectView.view.center.y/3, 800, 600);
NSLog(@"4.5 Array length: %d", [projectsArray count]);
}
- (void)addToTableView:(NSString *)projectName
{
NSLog(@"Project Array: %@", projectsArray);
NSLog(@"addToTableView: %@", projectName);
NSLog(@"5. Array length: %d", [projectsArray count]);
ViewController *element = [[ViewController alloc] init];
element->ID = 2;
element->NAME = projectName;
[projectsArray addObject:element];
NSLog(@"6. Array length: %d", [projectsArray count]);
[self.projectsTableView reloadData];
[self.projectsTableView setNeedsDisplay];
}
- (void)viewDidUnload
{
[self setProjectsTableView:nil];
self.projectsTableView = nil;
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return YES;
}
@end
Here the .h file of the modal presented view:
// AddProject.h
#import <UIKit/UIKit.h>
@class ViewController;
@interface AddProject : UIViewController
{
IBOutlet UITextField *projectName;
ViewController *viewContr;
}
- (IBAction)back:(id)sender;
- (IBAction)next:(id)sender;
@property (nonatomic, retain) ViewController *viewContr;
@end
The .m file of the modal presented file:
// AddProject.m
#import "AddProject.h"
#import "ViewController.h"
@interface AddProject ()
@end
@implementation AddProject
**@synthesize viewContr; // SOLUTION I've mist to synthesize it**
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
**// SOLUTION no new allocation/init of ViewController**
}
- (IBAction)back:(id)sender
{
[self dismissModalViewControllerAnimated:YES];
}
- (IBAction)next:(id)sender
{
[viewContr addToTableView:projectName.text];
[viewContr.projectsTableView reloadData];
[viewContr.projectsTableView setNeedsDisplay];
[self dismissModalViewControllerAnimated:YES];
}
- (void)viewDidUnload
{
projectName = nil;
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return YES;
}
@end
I’ve tested the code by using breakpoints and I could locate the issue when the AddProject class “viewDidLoad” starts loading. But I don’t know why it resets the array.
You navigate from
ViewControllerScreen toAdd projectScreen. InAdd ProjectScreen, you add a new project and want to delegate back this information to theViewControllerScreen where you came from.Now, you are trying to have an instance of
ViewControllerin yourAddProject, which you newly instantiate inviewDidLoadmethod and when project is added, you provide the information to it by calling- (void)addToTableView:(NSString *)projectNameon it.This doesn’t work because – The instance of
ViewControlleryou allocated is a new instance and not the one you navigated from. When you doalloc + inityou get a new object. Thus, although you getaddToTableView:called on yourViewController, it doesn’t work because theViewControllerinstance that is receiving this message is a new instance and not the one you navigated from.Thus, all you needed to do is – have a
ViewControllerproperty in yourAdd Project, which you would set before navigating. And then you can send message to this property – As explained in this transcript.I would like to say – However this thing works, it provides tight coupling between the two controllers.
Ideally, This cane be done by making
ViewController(where you go navigate from) as a delegate ofAdd Project(where you navigate to). And thenAdd Projectcan delegate the added project to it’s delegate by something like- (void) addProjectController:(AddProjectViewController *) controller didAddProject:(NSString *) projectName. This provides lose coupling between the two view controllers. To understand delegation concept, refer to Delegates and Datasources. Alternatively, search for other Stack overflow posts.