Developing for a jailbroken device.
I've looked here for a soultion to my problem. Using NSUserDefaults for storing UISwitch state but people say alot of the codes don't work.
I'm using a UISwitch to load/unload a launch daemon for iOS. I've gotten very close but the switch state won't save. This is the code im using.
#synthesize toggleSwitch;
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
if([[NSUserDefaults standardUserDefaults] boolForKey:#"switch"]) toggleSwitch.on = [[NSUserDefaults standardUserDefaults] boolForKey:#"switch"];
}
- (void)switchValueChanged {
if (toggleSwitch.on) {
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:TRUE];
switchlabel.text = #"Enabled";
const char *onchar = [[NSString stringWithString:#"launchctl load -wF /System/Library/LaunchDaemons/com.launch.daemon.plist"] UTF8String];
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:FALSE];
setuid(0); system(onchar);
if (system(onchar) == 0){
[[NSUserDefaults standardUserDefaults] setBool:self.toggleSwitch.on forKey:#"switch"];
[[NSUserDefaults standardUserDefaults] synchronize];
} else {
[[NSUserDefaults standardUserDefaults] setBool:self.toggleSwitch.on forKey:#"switch"];
[[NSUserDefaults standardUserDefaults] synchronize];
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:FALSE];}
} else {
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:TRUE];
switchlabel.text = #"Disabled";
const char *offchar = [[NSString stringWithString:#"launchctl unload -wF /System/Library/LaunchDaemons/com.launch.daemon.plist"] UTF8String];
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:FALSE];
setuid(0); system(offchar);
if (system(offchar) == 0){
[[NSUserDefaults standardUserDefaults] setBool:self.toggleSwitch.on forKey:#"switch"];
[[NSUserDefaults standardUserDefaults] synchronize];
} else {
[[NSUserDefaults standardUserDefaults] setBool:self.toggleSwitch.on forKey:#"switch"];
[[NSUserDefaults standardUserDefaults] synchronize];
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:FALSE]; }
}
The bool value is written in my app plist. I don't seem to know what I did wrong. I pieced afew examples from questions on overflow with no luck. Regardless if the command fails, the switch should save.
Could someone explain and show me what should be edited. This has been driving me absolutely nuts.
Related
I have setup my app to support a base internationalization for English and added a local for Spanish. I'm trying to provide an option to force the app to use a locale select by the user via a segmented control.
What I would like to do is have the screen "refresh" or "redraw" with the new selected locale.
Here is my action for the segmented control:
- (IBAction)segmentSwitch:(id)sender {
UISegmentedControl *segmentedControl = (UISegmentedControl *) sender;
NSInteger selectedSegment = segmentedControl.selectedSegmentIndex;
NSUserDefaults *prefs;
prefs = [NSUserDefaults standardUserDefaults];
if (selectedSegment == 0) {
[prefs setObject:#"en" forKey:#"language"];
[[NSUserDefaults standardUserDefaults] setObject:[NSArray arrayWithObjects:#"en", nil] forKey:#"AppleLanguages"];
[[NSUserDefaults standardUserDefaults] synchronize];
NSLog(#"English");
}
else
{
[prefs setObject:#"es" forKey:#"language"];
[[NSUserDefaults standardUserDefaults] setObject:[NSArray arrayWithObjects:#"es", nil] forKey:#"AppleLanguages"];
[[NSUserDefaults standardUserDefaults] synchronize];
NSLog(#"Spanish");
}
[self.view setNeedsDisplay];
}
My hope is that the screen would refresh and display the selected language view. If I close out the app and restart, it does display new view.
Here is my viewWillAppear:
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
// get the saved language preference
NSUserDefaults *prefs;
prefs = [NSUserDefaults standardUserDefaults];
NSString *stringVal = [prefs stringForKey:#"language"];
// Make sure we have a valid value
if (stringVal != nil) {
// Set the language preference
[[NSUserDefaults standardUserDefaults] setObject:[NSArray arrayWithObjects:stringVal, nil] forKey:#"AppleLanguages"];
[[NSUserDefaults standardUserDefaults] synchronize]; //to make the change immediate
// Turn on the appropriate segment
if ([stringVal isEqual: #"en"]) {
NSLog(#"English");
languageSwitch.selectedSegmentIndex = 0;
} else {
NSLog(#"Spanish");
languageSwitch.selectedSegmentIndex = 1;
}
} else {
// default to English
languageSwitch.selectedSegmentIndex = 0;
[[NSUserDefaults standardUserDefaults] setObject:[NSArray arrayWithObjects:#"en", nil] forKey:#"AppleLanguages"];
[[NSUserDefaults standardUserDefaults] synchronize]; //to make the change immediate
}
}
I had thought that following would force a screen refresh but it doesn't seem to be working:
[self.view setNeedsDisplay];
Any thoughts or suggestions would be appreciated. Thanks in advanced.
I made an UISwitch, and when it is switched on, my app sends 10 notifications with a "repeat interval". It works all fine. But the problem is, when I want to save (remember) the state of my UISwitch and load it, the UILocalNotification aren't being sent anymore.
This is my code:
For the save of the UISwitch state and notification launch:
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
BOOL test= [[NSUserDefaults standardUserDefaults] boolForKey:#"switch"];
NSLog(#"%#",test?#"YES":#"NO");
[self.alarmSwitch setOn:test animated:YES];
}
- (void) switchIsChanged:(UISwitch *)paramSender{
if ([paramSender isOn]){
[[NSUserDefaults standardUserDefaults] setBool:self.alarmSwitch.on forKey:#"switch"];
[[NSUserDefaults standardUserDefaults] synchronize];
notification1 = [[UILocalNotification alloc]init];
notification1.fireDate = [NSDate dateWithTimeIntervalSinceNow:5.0];
[notification1 setAlertBody:#"U moet uw voeten controleren!"];
[[UIApplication sharedApplication] scheduleLocalNotification:notification1];
notification1.fireDate = [NSDate dateWithTimeIntervalSinceNow:10.0];
[[UIApplication sharedApplication] scheduleLocalNotification:notification1];
}
}
How can I save the state of the UISwitch in another way in order to get this work? Or is there another solution to fix this?
Your switchIsChanged: method isn't going to be firing when you set the on state programatically. I would recommend moving the code that handles the notifications out of the switchIsChanged: method. Example:
-(void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
BOOL test= [[NSUserDefaults standardUserDefaults] boolForKey:#"switch"];
NSLog(#"%#",test?#"YES":#"NO");
[self.alarmSwitch setOn:test animated:YES];
// initially detect if we should fire the bnotifications
if ([self.alarmSwitch isOn]) {
[self fireNotifications];
}
}
-(void)switchIsChanged:(UISwitch *)paramSender{
[[NSUserDefaults standardUserDefaults] setBool:paramSender.on forKey:#"switch"];
[[NSUserDefaults standardUserDefaults] synchronize];
if ([paramSender isOn]){
[self fireNotifications];
}
}
-(void)fireNotifications {
notification1 = [[UILocalNotification alloc]init];
notification1.fireDate = [NSDate dateWithTimeIntervalSinceNow:5.0];
[notification1 setAlertBody:#"U moet uw voeten controleren!"];
[[UIApplication sharedApplication] scheduleLocalNotification:notification1];
notification1.fireDate = [NSDate dateWithTimeIntervalSinceNow:10.0];
[[UIApplication sharedApplication] scheduleLocalNotification:notification1];
}
Note: you may have to make sure that the notifications aren't firing more than once which may cause bugs since viewWillAppear: can be called multiple times.
I am developing app using Estimote beacons, so i have three beacons one for Entry and second for Exit and third for messages.I want to fire push notification based on proximity user is getting so i get the push notification but issue is that it give multiple same notification.
so i use NSUserDefault to stop multiple pushnotification but it also not works so how can i stop this issue.i also check with local notification but it also give me multiple local notification.
Code:-
-(void)beaconManager:(ESTBeaconManager *)manager
didRangeBeacons:(NSArray *)beacons
inRegion:(ESTBeaconRegion *)region
{
if ([beacons count] == 0)
return;
ESTBeacon* beacon = [beacons firstObject];
int dist = [beacon.distance intValue];
if([region.identifier isEqualToString:BeaconIdentifier2]){
switch (beacon.proximity) {
case CLProximityUnknown:{
[[NSUserDefaults standardUserDefaults] setObject:#"FALSE" forKey:#"Far"];
[[NSUserDefaults standardUserDefaults] setObject:#"FALSE" forKey:#"Near"];
[[NSUserDefaults standardUserDefaults] setObject:#"FALSE" forKey:#"Immediate"];
[[NSUserDefaults standardUserDefaults] synchronize];
if([[[NSUserDefaults standardUserDefaults] valueForKey:#"Unknown"] isEqualToString:#"FALSE"])
{
[[NSUserDefaults standardUserDefaults] setObject:#"TRUE" forKey:#"Unknown"];
[[NSUserDefaults standardUserDefaults] synchronize];
NSLog(#"Call Unknown");
[self callPush];
}
}
break;
case CLProximityFar:{
[[NSUserDefaults standardUserDefaults] setObject:#"FALSE" forKey:#"Unknown"];
[[NSUserDefaults standardUserDefaults] setObject:#"FALSE" forKey:#"Near"];
[[NSUserDefaults standardUserDefaults] setObject:#"FALSE" forKey:#"Immediate"];
[[NSUserDefaults standardUserDefaults] synchronize];
if([[[NSUserDefaults standardUserDefaults] valueForKey:#"Far"] isEqualToString:#"FALSE"])
{
[[NSUserDefaults standardUserDefaults] setObject:#"TRUE" forKey:#"Far"];
[[NSUserDefaults standardUserDefaults] synchronize];
//Call webservice
[self callPush];
}
}
break;
case CLProximityNear:{
[[NSUserDefaults standardUserDefaults] setObject:#"FALSE" forKey:#"Unknown"];
[[NSUserDefaults standardUserDefaults] setObject:#"FALSE" forKey:#"Far"];
[[NSUserDefaults standardUserDefaults] setObject:#"FALSE" forKey:#"Immediate"];
[[NSUserDefaults standardUserDefaults] synchronize];
if([[[NSUserDefaults standardUserDefaults] valueForKey:#"Near"] isEqualToString: #"FALSE"])
{
[[NSUserDefaults standardUserDefaults] setObject:#"TRUE" forKey:#"Near"];
[[NSUserDefaults standardUserDefaults] synchronize];
//Call webservice
[self callPush];
}
}
break;
case CLProximityImmediate:{
[[NSUserDefaults standardUserDefaults] setObject:#"FALSE" forKey:#"Unknown"];
[[NSUserDefaults standardUserDefaults] setObject:#"FALSE" forKey:#"Far"];
[[NSUserDefaults standardUserDefaults] setObject:#"FALSE" forKey:#"Near"];
[[NSUserDefaults standardUserDefaults] synchronize];
if([[[NSUserDefaults standardUserDefaults] valueForKey:#"Immediate"] isEqualToString:#"FALSE"])
{
[[NSUserDefaults standardUserDefaults] setObject:#"TRUE" forKey:#"Immediate"];
[[NSUserDefaults standardUserDefaults] synchronize];
//Call webservice
[self callPush];
}
}
break;
}
}
}
Thanks in advance.
Try this,
BOOL isFar=TRUE;
- (void)locationManager:(CLLocationManager *)manager
didRangeBeacons:(NSArray *)beacons inRegion:(CLBeaconRegion *)region{
if (self.beaconRegion) {
if([beacons count] > 0)
{
//get closes beacon and find its major
CLBeacon *beacon = [beacons objectAtIndex:0];
switch (beacon.proximity)
{
case CLProximityUnknown:
break;
case CLProximityImmediate:
NSLog(#"Immediate");
if (isFar) {
isFar=false;
// Call WebService
}
break;
case CLProximityNear:
if (isFar) {
// Call WebService
}
isFar=false;
break;
case CLProximityFar:
NSLog(#"far");
if (!isFar) {
// call websercie
}
isFar=TRUE;
break;
default:
break;
}
}
}
}
I would like to change application language inside the app without restarting.
There are Localizable.strings files for both languages. All my XIBs and main Storyboard too.
Te below code can change the language only after restarting an app
main.m:
int main(int argc, char *argv[])
{
NSString *currLang = [[NSUserDefaults standardUserDefaults] stringForKey:#"Lang"];
if (!currLang) {
NSString *languageCode = [[NSLocale preferredLanguages] objectAtIndex:0];
if ([languageCode isEqualToString:#"ru"]) {
[[NSUserDefaults standardUserDefaults] setValue:languageCode forKey:#"Lang"];
}
else [[NSUserDefaults standardUserDefaults] setValue:#"en" forKey:#"Lang"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
currLang = nil;
currLang = [[NSUserDefaults standardUserDefaults] stringForKey:#"Lang"];
if ([currLang isEqualToString:#"ru"]) {
[[NSUserDefaults standardUserDefaults] setObject:[NSArray arrayWithObjects:#"ru", #"en", nil]
forKey:#"AppleLanguages"];
}
else
[[NSUserDefaults standardUserDefaults] setObject:[NSArray arrayWithObjects:#"en", #"ru", nil]
forKey:#"AppleLanguages"];
[[NSUserDefaults standardUserDefaults] synchronize];
#autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
There are 2 buttons (Eng & Ru) ant the method:
- (IBAction)changeLang:(UIButton *)sender
{
if ([sender isEqual:btnSetRuLang]) {
if ([[userDefaults stringForKey:#"Lang"] isEqualToString:#"ru"]) {
return;
}
[userDefaults setValue:#"ru" forKey:#"Lang"];
[userDefaults synchronize];
}
else {
if ([[userDefaults stringForKey:#"Lang"] isEqualToString:#"en"]) {
return;
}
[userDefaults setValue:#"en" forKey:#"Lang"];
[userDefaults synchronize];
}
NSString *currLang = [userDefaults stringForKey:#"Lang"];
NSString *alertBody;
if ([currLang isEqualToString:#"ru"]) {
[userDefaults setObject:[NSArray arrayWithObjects:#"ru", #"en", nil]
forKey:#"AppleLanguages"];
alertBody = #"Перезапустите приложение для смены языка";
}
else {
[userDefaults setObject:[NSArray arrayWithObjects:#"en", #"ru", nil]
forKey:#"AppleLanguages"];
alertBody = #"Restart application for change language";
}
[userDefaults synchronize];
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Hom" message:alertBody delegate:self cancelButtonTitle:#"Ok" otherButtonTitles: nil];
[alertView show];
}
So, how should I change lang without restarting app?
Thank you.
I have did the same in one of my application, When user changes the language I did the same and reload all my View controllers which are in navigation stack by calling setNeedsDisplay, that renders the view again with new language settings.
EDIT
for each instance of your view controller call [self setNeedsDisplay] or you can replace the self by the instance of your view controller.
I would suggest you to use
NSLocalizedStringFromTable(key, tbl, comment)
instead of NSLocalizedString(key, comment)
This way all you need to do is maintain a variable of table name. Instead of Localizable.strings, use en.strings and ru.strings files and when the language changes pass the table name as en or ru
Also as #Parser suggests, you must refresh your views.
I know how I can detect if the application first time opened using NSUserDefault:
BOOL didRunBefore = [[NSUserDefaults standardUserDefaults] boolForKey:#"didRunBefore"];
if (!didRunBefore) {
//Your Launch Code
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"didRunBefore"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
The Issue: I want an Alert for ever view explaining about what features it contains and only open this alert when the app is first launched?
As an OOP programmer you can make a common public method.
+ (BOOL)checkWhetherRunBefore:(NSString *)key
{
return [[NSUserDefaults standardUserDefaults] boolForKey:key];
}
+ (void)hasRunForMyClass:(NSString *)key
{
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:key];
[[NSUserDefaults standardUserDefaults] synchronize];
}
And in your ViewController , you can code in the viewWillAppear or viewDidAppear like this :
- (void)viewWillAppear
{
if(![HelpController checkWhetherRunBefore:NSStringFromClass([self class])])
{
//do your thing
[HelpController hasRunForMyClass:NSStringFromClass([self class])]
}
}
You just need to put your code in viewDidLoad
viewDidLoad will run only one time when app load your view. (except low memory)
Next time you load the view again in viewDidLoad, you can check bool didRunBefore
You can use any key you want.
In FirstViewController:
BOOL didRunBefore = [[NSUserDefaults standardUserDefaults] boolForKey:#"FirstViewController_didRunBefore"];
if (!didRunBefore) {
//Your Launch Code
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"FirstViewController_didRunBefore"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
In SecondViewController:
BOOL didRunBefore = [[NSUserDefaults standardUserDefaults] boolForKey:#"SecondViewController_didRunBefore"];
if (!didRunBefore) {
//Your Launch Code
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"SecondViewController_didRunBefore"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
yo have to need to detect application first launch, you can detect t like this
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if (![defaults objectForKey:#"firstRun"])
[defaults setObject:[NSDate date] forKey:#"firstRun"];
[[NSUserDefaults standardUserDefaults] synchronize];
You can then test for it later...
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if([defaults objectForKey:#"firstRun"])
{
// do something or not...
}