Issue passing variable across class files - objective-c

I am having difficulty passing variable from one class file to another. I have tried the Global Variable creator extern, but that also doesn't work.
Specifically, I am trying to pass a variable from a new class file I created called NDSClassSiteViewController to the master controller NDSClassMasterViewController.
I have added the #property into the .h file as follows:
#interface NDSClassSiteViewController : UITableViewController {
NSArray *sitesMenu;
}
#property (nonatomic, retain) NSString *siteid;
#end
And then the #synthesize into the .m file as follows:
#import "NDSClassSiteViewController.h"
#import "NDSClassMasterViewController.h"
#interface NDSClassSiteViewController () {
NSMutableArray *_objects;
}
#end
#implementation NDSClassSiteViewController
#synthesize siteid;
I set the variable in the .m file as follows:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"showMenu"]) {
NSInteger row = [[self tableView].indexPathForSelectedRow row];
//NSArray *appcell = [sitesMenu objectForKey:#"Table"];
NSLog(#"AppCell %#", sitesMenu);
NSDictionary *entry = [sitesMenu objectAtIndex:row];
self.siteid = [entry objectForKey:#"SITEID"];
NSLog(#" sample SiteView %#", siteid);
//NDSClassMasterViewController *detailController = segue.destinationViewController;
//detailController.detailItemTwo = siteid;
}
}
Then I try and access it in the Master View controller using the following:
- (void)viewDidLoad
{
[super viewDidLoad];
globalid = siteid;
}
But I get an error: use of undeclared identifier siteid
I don't really know why it won't allow me to use the variable? Am I missing something?

You've declared a property on NDSClassSiteViewController. To access the property you need an instance of an NDSClassSiteViewController within scope, and you also must access it using the syntax for properties - either dot syntax or standard method call syntax.
To read the property:
aSiteViewController.siteID
[aSiteViewController siteID]
To set it:
aSiteViewController.siteID = #"Site ID here";
[aSiteViewController setSiteID:#"Site ID Here"]
When you are in a method of NDSClassSiteViewController then self points to the instance you likely want to use. Otherwise, you'll probably either create it in the method or have it passed in as a parameter. Also, when you are in an instance method of NDSClassSiteViewController you can access the instance variable that backs the property directly - usually this would be _siteID but you manually synthesized so just siteID should work. Note that I did siteID instead of the siteid you're using. I did this for readability and to follow established Objective-C naming conventions.

Related

Use of undeclared identifier?

I am getting error:use of undeclared identifier
here is the code for view controller where I am accessing the object of model class mapMembersData
for (NSMutableDictionary *getMemberElements in arData)
{
mapMembersData *notModelObject = [mapMembersData sharedInstance];//showing error
[notModelObject assignMemberData:getMemberElements];
[memberArray addObject:notModelObject];
}
Here is the code of model class:
#import <CoreLocation/CoreLocation.h>
#import <Google-Maps-iOS-Utils/GMUMarkerClustering.h>
#interface mapMembersData : NSObject<GMUClusterItem>
#property(nonatomic,retain) NSString *chatToken;
#property(nonatomic,retain) NSString *address;
+ (mapMembersData *)sharedInstance;
- (mapMembersData *)assignMemberData:
#end
#import "mapMembersData.h"
#import "Constants.h"
#implementation mapMembersData
#synthesize chatToken,
address,
static mapMembersData *instance;
+(mapMembersData *)sharedInstance{
#synchronized(self)
{
instance = [[super alloc] init];
}
return instance;
}
- (mapMembersData *)assignMemberData:(NSMutableDictionary*)getMemberElements
{
chatToken = [objdelegate checkIfStringIsEmpty:[getMemberElements
objectForKey:#"chatToken"]];
address = [objdelegate checkIfStringIsEmpty:[getMemberElements
objectForKey:#"address"]];
return self;
}
#end
What am I doing wrong?
In your storyboard there must be a controller, in which you had set a class with storyboard id, and you removed that class from that storyboard but the storyboard id is still addressing it, like below image:
So you have to remove that Storyboard ID and uncheck that "Use Story Board ID".
That's all.
After scratching my head for a day. I manage to get ride off the bizarre errors.
Finding starts from below:
1.mapMembersData-class were residing in two different folders of the workspace (In XYZ-folder and one at outside the folder). mapMembersData- the class was referenced by project i.e inside XYZ and other was just placed.
the controller from where I was accessing the mapMembersData, was at outside XYZ-folder, thus creating ambiguity.
I deleted unused referenced classed and confirm controller should access correctly.

How to use #property correctly (Setters) within another class

another question i'm trying to use a setter within another class but I seem to get this odd error here is the code below:
AppDataSorting.h
#import <Foundation/Foundation.h>
#interface AppDataSorting : NSObject{
NSString *createNewFood;
NSNumber *createNewFoodCarbCount;
}
#property (readwrite) NSString *createNewFood;
#end
AppDelegate.m
#import "AppDelegate.h"
#implementation AppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
// Insert code here to initialize your application
}
- (IBAction)saveData:(id)sender {
NSLog(#"%#", self.foodName.stringValue);
self.createNewFood = self.foodName.stringValue;
NSLog(#"%.1f", self.carbAmount.floatValue);
}
#end
I get the error message in AppDelegate.m which is: Property 'createNewFood' not found on object of type 'AppDelegate *'
Could someone please explain the issue here?
You declare this property:
#property (readwrite) NSString *createNewFood;
In AppDataSorting.h so you can access it like self.createNewFood in AppDataSorting.m file not AppDelegate.m. If you want to call it as you do in AppDelegate.m you have move this line:
#property (readwrite) NSString *createNewFood;
to AppDelegate.h file.
Or if you want to use property from AppDataSorting class in AppDelegate you have to create object and call it on that object:
- (IBAction)saveData:(id)sender {
NSLog(#"%#", self.foodName.stringValue);
AppDataSorting *dSorting = [[AppDataSorting alloc] init];
dSorting.createNewFood = self.foodName.stringValue;
NSLog(#"%.1f", self.carbAmount.floatValue);
}
In -saveData:, self refers to an instance of NSAppDelegate. The createNewFood property is defined on instances of the class AppDataSorting.
Also note that Cocoa/CF naming conventions give special meaning to methods that start with "init", "new" and (to a lesser degree) "create". You probably want to avoid such things in your property names. Details here.
In general, properties should represent conceptual "properties" of an object. So if you had a Person class, it might have a name property, but it wouldn't have a createNewOutfit property.
You need to access createNewFood on an instance of AppDataSorting - but you're trying to access the property on the AppDelegate-class which clearly doesn't implement it.
So you would need to create an instance of AppDataSorting and then access the property like so:
AppDataSorting *instance = [[AppDataSorting alloc] init];
instance.createNewFood = self.foodName.stringValue;
Final notes:
The docs provide a good base of information
If you don't need atomicity you should always declare properties with the nonatomic attribute
createNewFood is not a good name for a property since it suggests a method which creates new food - yet it's only meant to store data (in this case an NSString instance)

Access Class without initializing

I want to create a class in objective-c with its methods, so that for accessing the data I don't want to instantiate the class. how can I do it?
Either you can use singleton, or if you are planning to use only static methods, you can just add it in the class and use it directly with class name.
Create methods as static,
+(void)method;
then use it as,
[MyClass method];
This is helpful only if you are creating some utility classes which has only some utility method like processing an image or so. If you need to have property variables, you will need singleton.
For eg:-
Go to new file and create MySingleton class which will create MySingleton.h and MySingleton.m files.
In .h file,
#interface MySingleton : NSObject
{
UIViewController *myview;
}
#property (nonatomic, retain) UIViewController *myview;
+(MySingleton *)sharedSingleton;
In .m file,
+ (MySingleton*)sharedSingleton {
static MySingleton* _one = nil;
#synchronized( self ) {
if( _one == nil ) {
_one = [[ MySingleton alloc ] init ];
}
}
return _one;
}
- (UIViewController *)myview {
if (!myview) {
self.myview = [[[UIViewController alloc] init] autorelease]; //you can skip this, but in that case you need to allocate and initialize the first time you are using this.
}
return myview;
}
Then use it as,
[[MySingleton sharedSingleton] myview] anywhere in your project. Remember to import MySingleton.h though. Similarly you can create any object in singleton and use it. Just implement the getter or setter method accordingly.
One thing you have to be careful is that the object created in a singleton has only a single memory space allocated and hence it is the same object whenever you are using anywhere in your project. The above code will not create multiple copies of myview object in the class. So whenever you are modifying a property of myview that will be reflected everywhere. Use this approach only if it is absolutely needed and you need to have access to a single object from all over the project. Normally we use this only for situations like storing a sessionID which needs to be accessed from different classes etc..
You may use singleton pattern, check this question.
Like this:
+(MySingleton *)sharedInstance {
static dispatch_once_t pred;
static MySingleton *shared = nil;
dispatch_once(&pred, ^{
shared = [[MySingleton alloc] init];
shared.someIvar = #"blah";
});
return shared;
}
Or if you want to just access methods, you may use factory methods (those with +, not with -)
#interface MyClass
#property (nonatomic, assign) NSInteger value;
+ (void) factoryMethod;
- (void) instanceMethod;
...
// then in code
[MyClass factoryMethod]; // ok
[[MyClass sharedInstance] instanceMethod]; // ok
[MyClass sharedInstance].value = 5; // ok
UPDATE:
You may add a property to appDelegate
// in your app delegate.h
#property (nonatomic, retain) UIViewController* view;
// in your app delegate.m
#synthesize view;
and get appDelegate from almost any place like:
myapp_AppDelegate* appDelegate = [[UIApplication sharedApplicaton] delegate];
appDelegate.view = ...; // set that property and use it anywhere like this
Note, that you'll need to #import your UIViewController subclass and your appDelegate.h to make autocomplete work and sometimes avoid warnings.
// someFile.m
#import "appDelegate.h"
#import "myViewController.h"
...
myapp_AppDelegate* appDelegate = [[UIApplication sharedApplicaton] delegate];
appDelegate.view.myLabel.text = #"label text";

Objective-c: Singleton - passing variables

I have a singleton that I'd like to use to manage the onscreen animation of my views. Here's my.
#import <Foundation/Foundation.h>
#interface OAI_AnimationManager : NSObject {
NSMutableDictionary* sectionData;
}
#property (nonatomic, retain) NSMutableDictionary* sectionData;
+(OAI_AnimationManager* )sharedAnimationManager;
- (void) checkToggleStatus : (UIView* ) thisSection;
#end
.m file
#import "OAI_AnimationManager.h"
#implementation OAI_AnimationManager
#synthesize sectionData;
+(OAI_AnimationManager *)sharedAnimationManager {
static OAI_AnimationManager* sharedAnimationManager;
#synchronized(self) {
if (!sharedAnimationManager)
sharedAnimationManager = [[OAI_AnimationManager alloc] init];
return sharedAnimationManager;
}
}
- (void) checkToggleStatus : (UIView* ) thisSection {
//get the section data dictionary
NSLog(#"%#", sectionData);
}
#end
You'll see in the .h file I added a NSMutableDictionary and am using #property/#synthesize for it's getter and setter.
In my ViewController I instantiate the animation manager as well as a series of subclasses of UIView called Section. With each one I store the data (x/y w/h, title, etc.) in a dictionary and pass that to the dictionary delcared in animation manager. In the Section class I also instantiate animation manager and add a UITapGestureRecognizer which calls a method, which passes along which section was tapped to a method (checkToggleStatus) in animation manager.
As you can I see in the method I am just logging sectionData. Problem is I am getting null for the value.
Maybe my understanding of singletons is wrong. My assumption was the class would only be instantiated once, if it was already instantiated then that existing object would be returned.
I do need all the other Section classes data as if one animates others animate in response and I can get around it by passing the tapped Section to the animation manager and doing [[Section superview] subviews] and then looping and getting the data from each that way but it seems redundant since that data is available in the ViewController when they are created.
Am I doing something wrong in trying to transfer that data? Is there a better solution? I am open to suggestions and criticisms.
Thanks
h file
#interface OAI_AnimationManager : NSObject
#property (nonatomic, retain) NSMutableDictionary* sectionData;
+(OAI_AnimationManager* )sharedAnimationManager;
- (void) checkToggleStatus : (UIView* ) thisSection;
#end
m file
static OAI_AnimationManager* _sharedAnimationManager;
#implementation OAI_AnimationManager
#synthesize sectionData = _sectionData;
+(OAI_AnimationManager *)sharedAnimationManager {
#synchronized(self) {
if (!_sharedAnimationManager) {
_sharedAnimationManager = [[OAI_AnimationManager alloc] init];
}
}
return _sharedAnimationManager;
}
- (void) checkToggleStatus : (UIView* ) thisSection {
//get the section data dictionary
NSLog(#"%#", _sectionData);
}
#end
Notice I moved your sectionData variable from the header and moved it to the implementation file. A while back, they changed it to where you can synthesize properties and specify their instance variable names along side it... hence:
sectionData = _sectionData;
I also added and underscore to the instance variable... this is a universal convention for private variables and it also will throw a compile error now if you try to type just sectionData as you did in the return statement of checkToggleStatus:. Now you either have to type self.sectionData or _sectionData.
You didn't include the code that creates an instance of your dictionary but I bet you didn't set it as self.sectionData = [[NSDictionary alloc] init] which means it would not retain the value and you would get null the next time you called it. Classic memory management mistake... I know it well because I learned the hard way hehehe

how to pass a variable between two viewcontroller?

i want to pass a variable from a viewcontroller to another the way i do is
at the first viewcontroller header file i declared a variable
1.h:
NSString *string;
and at the second viewcontroller i have import the 1.h in my 2.m file,the way i call the variable is
2.m:
NSString *string2 = 1.string
however it return an error can somebody teach me how to do,because of i dont have the strong basic at Object Oriented programming ,thanks
Just defining and declaring the two strings is not enough. That makes sure that each class has a variable called string or string2 - but when your program is running, it is actual objects that must refer to specific instances of string1 (or string2).
It's like designing a house with a letterbox - the letterbox is there on the plan of the house, but nothing happens until a specific letter gets sent to a specific house.
What you need to do is wire up the actual instances of your class, possibily in an init method, like this:
// 1.h
#interface ViewController1 : UIViewController
{
// declare our variable
NSString* string1;
}
// declare 'string1' as a property
#property (retain) NSString* string1;
// 1.m
// implements the property for string1
#synthesize string1;
// 2.h
#interface ViewController2 : UIViewController
{
// declare our variable
NSString* string2;
}
// declare 'string2' as a property
#property (retain) NSString* string2;
// 2.m
- (id)initWithTitle:(NSString*)aTitle andString1:aString
{
if (self = [super init])
{
self.title = aTitle;
self.string1 = aString;
}
return self;
}
Then in 1.m, you create the second controller, and wire the strings up, like this:
// 1.m
mySecondController = [[ViewController2 alloc] initWithTitle:#"Controller 2" andString:string1];
Although it is possible to directly access members variables like that (using the -> operator) it is not recommended.
The correct way is to provide an accessor to get/set your member variables.
In Objective-C 2.0 (iPhone and OSX 10.5) you can easily do this using the "property" keyword. As part of the property syntax you can also express how you wish "set" objects to be treated.
retained - the previous object will be released and the new one retained
copy - the object will be copied
assign - the object will be assigned.
These are the basics, I suggest you read up more about properties.
The below shows how you would use properties in your example. Note that because we are dealing with an NSString, which is an NSObject derived class, we use the "retain" option to ensure the reference counts are correctly updated.
// 1.h
#interface ViewController1 : UIViewController
{
// declare our variable
NSString* _string;
}
// declare 'string' as a property
#property (retain) NSString* string;
// 1.m
// implements the property for string
#synthesize string = _string;
// constructor for ViewController1
-(id)initWithNibName:(NSString *)nibName bundle:(NSBundle *)nibBundle {
if (self = [super initWithNibName: name bundle: bundle]) {
// Initialize the string here.
self.string = #"Hello World";
}
}
// 2.m
NSString* oldString = view.string;
view.string = #"New String";