External variable not updating - iphone

i'm trying to set the value of a boolean. I can set it successfully, however, in another class, the changes reflected don't show up.
Here's an example:
File1:
#implementation ClassOne //UIViewController
extern BOOL theValue;
- (void)loadFile {
theValue = YES;
}
...
#end
File2:
#implementation ClassTwo //UIViewController
BOOL theValue;
- (void)switchValueChanged {
theValue = NO;
}
#end
I initally set the value in class one, with the initial value of YES. However, when I set the value in ClassTwo to equal NO and return back to ClassOne, the value is still YES.
I'm a little bit stuck. You would think it would update. But it doesn't.
Any help appreciated.

Easiest way to accomplish what you are after is to declare the BOOL in your appDelegate's interface file:
#interface AppDelegate : ....
{
BOOL theValue;
}
#property BOOL theValue;
Then from ClassOne or ClassTwo you can get/set the variable directly by:
MyAppDelegate *appDelegate = (MyAppDelegate * )[[UIApplication sharedApplication] delegate];
appDelegate.theValue = YES;
OR
If you really want to access it globally, simply declare the variable outside your #interface ... #end block
BOOL theValue
#interface AppDelegate : ...
{
...
}
And then you can access the variable theValue from anywhere in your code by simply importing the AppDelegate header file:
#import "AppDelegate.h"
#implementation ClassOne : ....
...
theValue = YES;

I figured it out. When my app launches, it sets theValue to YES by default. Problem was that I was using a viewWillAppear:animated method for this and every time the ClassTwo's view was dismissed the viewWillAppear:animated method was called and the value that was set had been reset. I changed the method to viewDidLoad and everything works fine.

Looks like you're be better off using the Singleton Design Pattern... http://www.galloway.me.uk/tutorials/singleton-classes/

Related

How to declare a variable that can be used in both class1.m and class B.m

i have "classmap.m" and annotation.m i have a value of coordinates in "classmap.m" and i need to assign a value in the other class annotation.m.
ex:
class1.m
double start_long;
i want to give pass the value in another one class (annotation.m)
annotation.m
annotation.longitude=Start_long;
how can i do that please give some examples is there.
thanks in advance
A better, more efficient, effective and cleaner way is to use Singleton Pattern. A good approach is to keep AppDelegate cleaner and avoid keeping global variables there. Always try to use Singleton classes and objects to keep global variables.
If both classmap.m and annotaion.m are inherited from NSObject then it's simple annotation:classmap . will give access to the properties of classmap
ClassMap
#interface classmap : NSObject
#property double longitude;
#end
#import "classmap.h"
#implementation classmap
#synthesize longitude;
#end
Annoataion
#interface annotation : classmap
#property double start_long;
#end
#import "annotation.h"
#implementation annotation
#synthesize start_long;
#end
Now the assigning can be done easily in annotation.longitude=Start_long the place you need
Take the variable in the Appdelegate and access it anywhere in the project .
Access it like
Assign Value
AppDelegate *app = [[UIApplication sharedApplication]delegate];
appd.start_long = -17.002// assign some value here
Read Value
AppDelegate *app = [[UIApplication sharedApplication]delegate];
double dVal = appd.start_long ;
The Singleton pattern is a weapon which should be used sparingly as it makes a concrete dependancy on the ClassMap object for everything which uses it.
While using a Singleton will achieve what you want right now which is access to a property in ClassMap but you set yourself up for future coding issues.
What happens when you have multiple ClassMap instances for example?
Singletons are better suited to things which do universal jobs. Things which are tools. e.g [NSUserDefaults standardUserDefaults] or [NSFileManager defaultManager]
A different solution is to use Dependancy Injection which creates a direct connection between the object Annotation which needs the ClassMap object.
In brief ClassMap declares a property
#property double start_long;
you pass the ClassMap object to the Annotation object when you instantiate.
Annotation.h
#interface Annotation:NSObject
-(instancetype)initWithClassMap:(ClassMap *)amap;
#end
and…
Annotation.m
#interface Annotation() {
ClassMap *_map;
}
#end
#implementation Annotation
-(instancetype)initWithClassMap:(ClassMap *)amap {
self = [super init];
if(self) {
_map = amap;
}
return self;
}
-(void)doSomething {
self.longitude = _map.start_long;
}
#end
Another method is to use delegation.In your classmap.m declare
#protocol classmapDelegate <NSObject>
-(void)didchangeCoordinateValue:(double)longitude;
#end
annotation should confirm to this protocol and when ever the value in classmap is changed, you could get the event tin Annotation class.

Global Variable pulled from App Delegate

I am trying to use a variable integer throughout multiple methods in my view controller. The secondsLeft variable works fine, but the otherNumber variable won't work. I get the error: initializer element is not a compile-time constant. Any ideas on how I am supposed to do this? THank you!
#interface ViewController ()
#end
#implementation ViewController
#synthesize countDown,Timerlbl;
int secondsLeft = 500;
int otherNumber =[(AppDelegate *)[UIApplication sharedApplication].delegate otherNumber];
The problem is that you have declared otherNumber as a global variable and the compiler expects the initial assignment to be a compile-time constant. [delegate otherNumber] results in a selector invocation and this is not a compile-time constant.
The solution is to move the assignment into code. For example:
- (id)init
{
self = [super init];
if(self) {
otherNumber = [(AppDelegate *)[UIApplication sharedApplication].delegate otherNumber];
}
return self;
}
As another note, global variables are generally inadvisable in Objective-C. #property values are generally more recommended. Not only that, your ViewController class now has a dependency with your AppDelegate. Since your AppDelegate most likely is the one responsible for instantiating your ViewController, consider having it inject in the value of otherNumber. For example:
#interface ViewController ()
#property (nonatomic, assign) int otherNumber;
#end
- (id)initWithSomeNumber:(int)otherNumber
{
self = [super init];
if(self) {
self.otherNumber = otherNumber;
}
return self;
}
I assume that AppDelegate is the name of your app delegate class?
Have you tried adding an import for your AppDelegate, like this...
#import "AppDelegate.h"
#interface ViewController ()
You can't declare a variable like this because the compiler can't create an instance of AppDelegate and ask it what the value of otherNumber should be.
Depending on how it's being used, it might be better not to define the otherNumber variable at all, and instead retrieve it from AppDelegate each time it is used. This might mean a little more typing, but it does mean you'll always get the latest correct value of otherNumber
Also, it's a good idea in general to use NSInteger instead of int when defining integer variables.

iPhone sdk Storing the block parameter for later use

I have 2 classes:
Class A:
Registered as observer for NSNotification with name notificationName
.h file declares - typedef void (^block1)(NSError *error);
Private instance variable - block1 _block1_obj;
Then have 2 methods like these:
- (void) doSomethingWithCompletionHandler:(block1)handlerBlock
{
_block1_obj = handlerBlock; // Also tried _block1_obj = [handlerBlock copy];
[classB_obj doAnotherThing];
}
- (void) notificationHandler:(NSNotification *)notification
{
...
_block1_obj(error);
}
Class B:
- (void) doAnotherThing
{
...
[[NSNotificationCenter defaultCenter] postNotificationName:notificationName
object:nil
userInfo:dict];
}
Now I found while debugging that,
_block1_obj is assigned a value in doSomethingWithCompletionHandler
But after some time when control comes in notificationHandler:
_block1_obj is nil.
Not sure why is this. Can any one please explain?
Update:
I also tried creating a property with copy attribute but it did not work too.
You need to copy the block from stack to heap. If is insufficint to declare a copy block if you don't use it, but assign the ivar direcrly without copy.
You need to declare the instance variable as __strong, so ARC will know it has to retain the object.
I would suggest you use a private property, something like this in your .m file:
#interface YourClass ()
#property (strong, nonatomic) block1 block1_obj;
#end
#implementation YourClass
#end
and then assign the block by using the accessor:
self.block1_obj = handlerBlock;

protocol method is not being called by the delegate object

Another case of protocol method not being called - NO idea what am I doing wrong here...
Here is the code, omitting unnecessary info...
first header file: AccessNumber.h
#protocol AddItemDelegate <NSObject>
#required
- (void) processSuccessful: (BOOL)success;
#end
#interface AccessNumber : UIViewController <UITableViewDelegate, UITableViewDataSource, ABPeoplePickerNavigationControllerDelegate, UIAlertViewDelegate> {
id <AddItemDelegate> delegate;
}
#property (retain) id <AddItemDelegate> delegate;
#end
first .m file: AccessNumber.m - I am calling the protocol method from viewdidload just for testing purposes, it should basically get called from another method, but same thing for the sake of this convo (tried both of course)
#import "AccessNumber.h"
#import "History.h"
#synthesize delegate;
- (void)viewDidLoad
{
[super viewDidLoad];
....
[[self delegate] processSuccessful:YES];
}
second file header: History.h
#interface History : UIViewController <UITableViewDelegate, UITableViewDataSource, AddItemDelegate> {
....
}
method implementation in history.m
- (void) processSuccessful: (BOOL)success {
NSLog(#"SUCCESS");
}
Appreciate any help. Thanks!
In the code i don't see something like:
theAccessNumber.delegate = self;
You must set the History instance as the delegate property of the AccessNumber instance.
Regards.
The code seems a little bit funny but you are not telling your "AccessNumber" class who is his delegate, even though you are making the "History" class implement the protocol established by yourself (otherwise you would get a warning).
You have to set the delegate for the "AccessNumber" class like this when setting it up from within "AccessNumber.m":
self.delegate = historyInstance;
or like this when setting it up from within "History.m":
accessNumberInstance.delegate = self;
There are very vew situations where you should retain a delegate, normally your delagate will outlive the object. So change your property from retain to assign. And be sure you are setting the delegate. Where are you doing it? If your object really depends on it you should be passing it in the constructor (iniWithDelagate). Try doing a NSLog before calling the delagate method just to see if it isn't nil.

need to define a "modifiable" global variable in objective-c

I have the following issue. I have two classes that manipulate information but they are completely disconnected, i.e. I can't reach the other class.
I need both classes to use a certain value. For example, class A sets the value foo = A and class B needs to be able to read that value and rest foo to nil.
I thought about creating the variable in the main app delegate, but can't figure out how.
Ideas?!!
Global variables are generally bad idea. Based on your description i think you can use KVO to inform class B about the changes in 'foo'.
But if you relly need a global variable you can do this:
#interface YourAppDelegate : NSObject <UIApplicationDelegate> {
}
#property (nonatomic) NSString *foo;
#end
#implementation YourAppDelegate
#synthesize foo;
...
#end
#implementation ClassA
...
- (void)someMethod {
YourAppDelegate *appDelegate = (YourAppDelegate *)[[UIApplication sharedApplication] delegate];
appDelegate.foo = #"NewValueOfFoo";
}
...
#end
#implementation ClassB
...
- (void)otherMethod {
YourAppDelegate *appDelegate = (YourAppDelegate *)[[UIApplication sharedApplication] delegate];
NSLog(#"Value of foo: %#", appDelegate.foo); //This will print: "Value of foo: NewValueOfFoo"
}
...
#end
I'm not sure what you mean by "completely disconnected". Depending on what you're trying to do, you could use NSUserDefaults
http://developer.apple.com/library/ios/#documentation/cocoa/reference/foundation/Classes/NSUserDefaults_Class/Reference/Reference.html
or NSNotifications
http://developer.apple.com/library/ios/#documentation/Cocoa/Reference/Foundation/Classes/NSNotification_Class/Reference/Reference.html
If class A doesn't need to know about class B, you could consider delegation as well.
Why can't he just do this?
A. Add 2 new files to your project: GlobalValues.h and GloblaValues.m.
B. Open GlobalValues.h, and declare all your needed variables.
extern NSString *MyServiceName; // name of the 'service':
C. Open GlobalValues.m, and start the new file by importing GlobalValues.h, and assign values to the variables you declared in the header file:
#import "GlobalValues.h"
NSString *MyServiceName = #"MyService is called THIS";
D. In the implementation files of the classes that need to use these variables, you would put - at the very beginning:
#import "GlobalValues.h"