PDA

View Full Version : [Resolved] Remotely accessing an instance variable




multinode
May 27, 2011, 03:19 AM
"nextPath" is an instance variable in OrderEntryAppDelegate. It's value in the start method in OrderEntryAppDelegate.m is "/Subjects". However, when it's used in SubjectsController.m, it's value is nil. Why? What did I do wrong please?



OrderEntryAppDelegate.h

#import <UIKit/UIKit.h>
#import "SubjectsController.h"

@interface OrderEntryAppDelegate : NSObject <UIApplicationDelegate> {
UIWindow *window;
UIViewController *welcomeController;
SubjectsController *subjectsController;
UINavigationController *navigationController;
NSString *pathToHere, *nextPath;
UIButton *startButton;
}
-(IBAction) start:(id)sender;

@property (nonatomic, retain) IBOutlet UIButton *startButton;
@property (nonatomic, retain) IBOutlet UIWindow *window;
@property (nonatomic, retain) IBOutlet UIViewController *welcomeController;
@property (nonatomic, retain) IBOutlet UINavigationController *navigationController;
@property (nonatomic, retain) NSString *pathToHere, *nextPath;

@end

OrderEntryAppDelegate.m

#import "OrderEntryAppDelegate.h"
#import "SubjectsController.h"
#import "UIKit/UIKit.h"

@implementation OrderEntryAppDelegate

@synthesize window;
@synthesize welcomeController;
@synthesize startButton;
@synthesize navigationController;
@synthesize pathToHere;
@synthesize nextPath;

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:
(NSDictionary *)launchOptions {

pathToHere = @"/";

//activate the start button
[startButton setHidden:NO];

//create navigation controller
navigationController =
[[UINavigationControlleralloc] initWithRootViewController: welcomeController];
[self.window addSubview:navigationController.view];
[self.window makeKeyAndVisible];

return YES;
}


-(void) start:(id)sender{
//create myTableViewController instance
subjectsController = [[SubjectsController alloc] initWithStyle:UITableViewStylePlain];
nextPath = [pathToHere stringByAppendingPathComponent:@"Subjects"];
[navigationController pushViewController:subjectsController animated:YES];
printf("The start button was tapped\n");
}


- (void)dealloc {
[window release];
[super dealloc];
}
@end


SubjectsController.h

#import <UIKit/UIKit.h>
#import "OrderEntryAppDelegate.h"

@interface SubjectsController : UITableViewController {
NSString *pathToHere;
NSArray *dataArray;
}

@property (nonatomic, retain) NSString *pathToHere
@property (nonatomic, retain) NSArray *dataArray;
@end

SubjectsController.m

#import "OrderEntryAppDelegate.h"
#import "SubjectsController.h"

@implementation SubjectsController

@synthesize pathToHere;
@synthesize dataArray;

- (id)initWithStyle:(UITableViewStyle)style {
self = [super initWithStyle:style];
if (self) {
// Custom initialization.
self.title = @"Conference Subjects";
}
return self;
}

-(NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
OrderEntryAppDelegate *delegate = [[UIApplication sharedApplication]delegate];
NSError *error = nil;
self.pathToHere = [delegate nextPath];
dataArray = [[NSFileManager alloc] contentsOfDirectoryAtPath:delegate.pathToHere
error:&error];
return [dataArray count];
}


-(UITableViewCell *) tableView:tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
OrderEntryAppDelegate *delegate = [[UIApplication sharedApplication]delegate];
NSError *error = nil;
self.pathToHere = [delegate nextPath];
dataArray = [[NSFileManager alloc] contentsOfDirectoryAtPath:delegate.pathToHere
error:&error];
UITableViewCell *cell =
[self.subjectsViewdequeueReusableCellWithIdentifier:@"UITableViewCell"];
if (!cell) {
cell = [[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:@"UITableViewCell"] autorelease];
}
cell.textLabel.text = [dataArray objectAtIndex:indexPath.row];
return cell;
}


/*-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
OrderEntryAppDelegate *delegate = [[UIApplication sharedApplication] delegate];
UITableViewCell *selectedCell = [tableView cellForRowAtIndexPath:indexPath];
delegate.nextPath = [pathToHere stringByAppendingPathComponent:selectedCell.textLabel.text];
conferencesController = [[ConferencesController alloc] initWithStyle:UITableViewStylePlain];
[delegate.navigationController pushViewController:conferencesController animated:YES];
printf("next Level\n");
}*/
@end



robbieduncan
May 27, 2011, 04:27 AM
I've not read all your code but this is the first thing that jumps out at me:

You are not using your synthesized accessor to set nextPath.


nextPath = [pathToHere stringByAppendingPathComponent:@"Subjects"];


is not the same as (or even remotely similar to)


self.nextPath = [pathToHere stringByAppendingPathComponent:@"Subjects"];


In the first case you directly set the variable to point to an autoreleased object. You should expect that this will get released at the end of the current run loop. This is what is happening and therefore is the expected behaviour.

In the second case you use some syntactic sugar to call the setter method. This setter method will (due to your property declaration and synthesize call) retain the object and the set the pointer. So the object will not get released at the end of the current run loop.

The lesson to take out of this is never directly set properties. Always use the accessor methods via self. or calling setXXX directly. This is also why it's a good idea to give the variable a different name to the property (convention is to call the variable _propertyName) and use the synthesize directive to make that work. This prevents you making this error.

multinode
May 27, 2011, 05:41 AM
Thanx Robbie. Your correction fixed all my problems. Hours and hours and hours of thinking and thinking and thinking.