objective-c - using a boolean value from one class in another class - iphone

I've looked around and couldn't find a distinct answer to this question. So I'm asking here. I have two classes. ClassA and ClassB. I have a bool value in ClassB. I have a method in ClassA where it is looking for that value in ClassB to be True in order for the method to fire off. I'm not really sure how to get ClassA to see that value. Any help would be great. Thanks in advance!

be careful with the "global definition".
if your class must save the user settings, you can use:
for save:
NSUserDefaults *pref = [NSUserDefaults standardUserDefaults];
[pref setBool:YES forKey:#"AudioIsON"];
[pref synchronize];
for reading:
BOOL myBooleanSetting = [[NSUserDefaults standardUserDefaults] boolForKey:#"AudioIsON"];
instead of, is better to learn the delegate and the property.
hope this help you.

Related

Xcode ignores some of my lines

I have a part in my code that calls a method on a different class.
The different class is a singleton.
I didn't have any issues with this class until today, everything worked properly. I don't know why, but after a few insignificant changes i've made today, the code seems to ignore some of my code. It seems that everything is ok and it passes through all the lines but if i put a breakpoint inside one of the methods in my singleton class, it doesn't stop. It just doesn't call those methods.
Does anyone has an idea why could that be?
I tried cleaning the project, tried quitting Xcode, nothing helped so far.
This is an example of how my method in my singleton ".m" looks like:
-(void)setUserCurrentLocationWithLatitude:(NSNumber *)latitude andLongitude:(NSNumber *)longitude andUserIndex:(NSNumber *)userIndex{
NSMutableArray* tempPlayersArray = [NSMutableArray arrayWithArray: [[NSUserDefaults standardUserDefaults] arrayForKey: #"kgpsUsersArray"]];
NSMutableDictionary * userTempDict = [[NSMutableDictionary alloc] initWithDictionary:[tempPlayersArray objectAtIndex:[userIndex integerValue]]];
NSLog(#"latitude = %f",[latitude floatValue]);
[userTempDict setObject:latitude forKey:#"latitude"];
[userTempDict setObject:longitude forKey:#"longitude"];
[defaults setObject:tempPlayersArray forKey:#"kgpsUsersArray"];
[defaults synchronize];
}
And this is how it is defined in ".h" file:
-(void)setUserCurrentLocationWithLatitude:(NSNumber *)latitude andLongitude:(NSNumber *)longitude andUserIndex:(NSNumber *)userIndex;
And in my viewController.m file the singleton is being called initialized like this:
#import "PlayersData.h"
usersData = [PlayersData sharedInstance];
and the method is called like this:
[usersData setUserCurrentLocationWithLatitude:[NSNumber numberWithFloat:32.125493] andLongitude:[NSNumber numberWithFloat:34.858962] andUserIndex:[NSNumber numberWithInt:j]];
Thanks,
It is possible that the singelton was not created. Debug it, to be sure it is not nil.

Set a new value to a NSString variable with a previous value

I'm developing an iOS application with latest SDK and XCode.
This is a simple question but I don't know how to do it because I don't want any memory leaks on my code.
I'm using ARC on my project and I have the following header declaration:
#interface UserPreferences : NSObject
{
NSUserDefaults* prefs;
}
#property (nonatomic, readonly) NSString* appLanguage;
// More code
- (void) setAppLanguage:(NSString *)appLanguage;
// More code
#end
And this is how I've implemented - (void) setAppLanguage:(NSString *)appLanguage;.
- (void) setAppLanguage:(NSString *)newAppLanguage
{
[prefs setObject:appLanguage forKey:APP_LANGUAGE_KEY];
appLanguage = [NSString stringWithString:newAppLanguage];
}
Is appLanguage = [NSString stringWithString:newAppLanguage]; correct?
I don't know it appLanguage will have a value when I set a new one to it.
Is my code correct?
Your code doesn't have any leaks; ARC automatically releases the previous value for appLanguage for you. I would write appLanguage = [newAppLanguage copy] rather than using stringWithString:, but the effect is the same.
Unless you've omitted some code, this won't work...
You've created an instance variable for NSUserDefaults, but have never instantiated it with a value. When you call [prefs setObject:appLanguage forKey:APP_LANGUAGE_KEY]; prefs will be nil.
At some point, before you use prefs, you need to do something like: prefs = [NSUserDefaults standardUserDefaults];
If you have instantiated prefs somewhere else, you'll still have an issue with this logic. Presumably, you're trying to change the NSUserDefaults to the new language passed in. In that case, the method should be:
- (void) setAppLanguage:(NSString *)newAppLanguage {
_appLanguage = newAppLanguage; // implicit synchronize will set the ivar as _appLanguage
[prefs setObject:newAppLanguage forKey:APP_LANGUAGE_KEY];
[prefs synchronize];
}
Since the _appLanguage instance variable is set to strong by default, ARC will automatically add the necessary release and retain code, preventing a memory leak.
Also, if you are trying to create a private setter method, take - (void) setAppLanguage:(NSString *)appLanguage; out of the interface. If you're not trying to make a private setter, remove readonly from the property declaration.

Use NSString in another class

I simply want to access a NSString from my first class in my second class.
I used properties in my first class and this:
NSLog(#"The text is: %#", self.fileText);
returns the correct string in my first class.
But in my second class, this:
FirstViewController* controller = [[FirstViewController alloc] init];
NSLog(#"text: %#", controller.fileText);
returns (null).
I imported the class correctly.
What could I have done wrong?
Use this
//in your first class
NSUserDefaults *strinToSave= [NSUserDefaults standardUserDefaults];
[strinToSave setObject:self.fileText forKey:#"filTextString"];
and to retrieve saved data in the second class, use this:
NSString *yourString=[[NSUserDefaults standardUserDefaults] valueForKey:#"filTextString"];
//use yourString however you want
NSLog(#"%#",yourString);
Considering the second class is either a sub-class of the first class or jus an instance of the class (which seems more likely).
Be sure what you are doing in your init block of the FirstViewController, because that's all that's being called for the second implementation and if you have not initialized your string there, the value will be null. So yep, check there.

Check if NSString/NSMutableArray already exists in a NSUserDefault?

I'm making this app with a tableview and stuff. I want to make a "Favorites"-tab, and in the detail-view I want to make a star-like button. I'm done with the "add to favorites" stuff and want to make it impossible to add a string to my favoriteViewController more than once.
Basically, I want to check if my NSUserDefaults contains a certain string in its NSMutableArray that matches the indexPath.row in the table view. It's really hard to explain...
Here's a snippet out of the code. I want to check if the "indexPathRowString" already exists in favoriteKey, before adding it again.
-(IBAction)addToFavorite:(id)sender {
NSMutableArray* alreadyFavourites = [[[NSUserDefaults standardUserDefaults] objectForKey:#"favoriteKey"] mutableCopy];
[favoritedAlready addObject:indexPathRowString];
[[NSUserDefaults standardUserDefaults] setObject:alreadyFavourites forKey:#"favoriteKey"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
I'm very thankful for answers, I really need to fix this! :)
You want NSArray's containsObject:.
Because NSString implements the NSObject Protocol method isEqual: to return YES for two strings of the same content, this method will work correctly for you with two different string objects of the same value.
you can check using
if (![favoritedAlready containsObject:indexPathRowString])
{
[favoritedAlready addObject:indexPathRowString];
}

iphone dev - NSUserDefaults check for boolean existence

I've just added a settings bundle to my app and am having trouble reading the bool settings. I know that upon launch of the app, the settings are not read unless the user actually enters them - and that's what I am trying to capture.
However, my code is simply capturing if the answer is NO OR they havent been set. I need to find out if they've been set, THEN set answers!
setting code:
BOOL playSound;
BOOL playVibrate;
//test for some defaults
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
if (![prefs boolForKey:#"pref_sound"]) {
playSound = YES;
playVibrate = YES;
} else {
playSound = [prefs boolForKey:#"pref_sound"];
playVibrate = [prefs boolForKey:#"pref_vibrate"];
}
if (playSound) {
//do stuff
}
the problem is, if the user sets the settings to "NO", the code then changes both vibrate AND sound to yes - which is meant to be the capture for NOT setting....
any ideas?
First of all you have a bug in your if conditional. You're checking the boolean value itself which, according to the boolForKey: documentation, will return a NO if it's not set yet. So boolForKey: is not the right way to do that.
Here's two other ideas.
Consider using another setting with another key to specify whether your settings have been initialized. Check it when you launch your app, or when you first read a setting. Initialize if needed. For instance:
- (void) initializeUserDefaults {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if (nil == [defaults objectForKey:#"initialized_defaults"]) {
[defaults setBool:YES forKey:#"pref_sound"];
[defaults setBool:YES forKey:#"pref_vibrate"];
[defaults setObject:#"dummy_value" forKey:#"initialized_defaults"];
}
}
A simpler solution (but I'm not sure if this would work) would be to change your conditional to read:
if (![prefs objectForKey:#"pref_sound"]) {
Again I don't know if this will do what I imagine it will, but I imagine that objectForKey: will return the underlying boxed boolean object, if it's there, or nil.
If you add a new setting in a new version of your app, you don't want to leave your new settings uninitialized and you don't want to stomp your users' existing settings. This second method makes that effortless, and in the first method it's easier to screw up. But the first method also gathers all your settings in one place so you can see how it's supposed to work, which I like.
I am not sure what ADC docs would consider a best practice though. To find that out, I'd suggest you look at any code samples referenced from the NSUserDefaults class reference.
maybe the best idea is to register some defaults for the NSUserDefaults using
(void)registerDefaults:(NSDictionary *)dictionary
see Apple Documentation at
https://developer.apple.com/library/ios/documentation/Cocoa/Reference/Foundation/Classes/NSUserDefaults_Class/index.html#//apple_ref/doc/uid/20000318-SW5
To come back to your original problem: in the past I was using NSUserDefaults.dictionaryRepresentation in order to check the existence of a key:
BOOL playSound;
BOOL playVibrate;
//test for some defaults
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
if (nil == [prefs dictionaryRepresentation]["pref_sound"]) {
playSound = YES;
playVibrate = YES;
} else {
playSound = [prefs boolForKey:#"pref_sound"];
playVibrate = [prefs boolForKey:#"pref_vibrate"];
}
if (playSound) {
//do stuff
}
Hope this works for you.
Kevin Conner's solution works for me, but there's another thing I think I should point out.
My app has a preference for handedness with right-handed as the default. When I hit run in Xcode, use the app to change my preference to left-handed, and then run it a second time, my preference is still right-handed.
It seems that running in Xcode erases settings. I decided to manually quit the app from inside the simulator, open it again from inside, and then I saw my new preferences.