All,
I just cannot find an answer to this question. The settings View Controller needs to shown once on startup ONLY. So when you download the app from the App Store / test flight.
I have it correct, so it runs it first, thats fine.
when you have finished with the settings page it goes to the main page and when you move the app to the background it carries on from where it left off. thats fine.. But... When you swipe the app away by double pressing the home button and pushing the app up to remove (ios7) it goes back to the settings screen again but it should carry on from where it left off.
So in my App Delegate, I have :
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
NSString *savedValue = [[NSUserDefaults standardUserDefaults] stringForKey:#"SettingsShown"];
NSLog(#"%#", savedValue);
Reachability *reachability = [Reachability reachabilityWithHostname:#"www.outtonightapp.com"];
[reachability startNotifier];
NSUserDefaults *settingsscreen = [NSUserDefaults standardUserDefaults];
[settingsscreen registerDefaults:[NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES],#"firstTime", nil]];
//BOOL firstTime = [settingsscreen boolForKey:#"firstTime"];
BOOL firstTime = [settingsscreen boolForKey:#"SettingsShown"];
if (!firstTime) {
//if ( firstTime==YES) {
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"SettingsShown"];
[[NSUserDefaults standardUserDefaults] synchronize];
self.window.rootViewController = [self.window.rootViewController.storyboard instantiateViewControllerWithIdentifier:#"SetUpNav"];
}
else
{
return YES;
}
This did work until I had to recreate my settings VC.. any advice would be great.
In similar situation I used delegation pattern.
Assume you have your initial view controller initialVC. And special settings view controller (SetUpNav) which is meant to be run only first time when defaults is not set. Then you could do the following:
You define SetUpNavdelegate protocol in SetUpNavViewController.h and property "initiator" conforming to that protocol
#protocol SetUpNavDeleagte;
#interface SetUpNavViewController : UIViewController
#property (strong,nonatomic) id <SetUpNavdelegate> initiator;
// the rest
#end
#protocol SetUpNavdelegate <NSObject>
-(void)setupFinished;
#end
In your InitialVC' viewDidLoad you do:
Check Your defaults are set properly or not by determine "firstTime" BOOL value
and fire setUpNav controller in code
-(void)viewDidLoad
{
// Check your defaults for consistency
if (firstTime){
UIStoryboard *sb = [UIStoryboard storyboardWithName:#"Main OR you SB name" bundle:nil];
UIViewController *setUpNavVC = [loginStoryboard instantiateViewControllerWithIdentifier:#"SetUpNav"];
setUpNavVC.initiator = self;
YouAppDelegateClass *appDelegate = [[UIApplication sharedApplication] delegate];
appDelegate.window.rootViewController = setUpVC;
// Here you don't need animation as I assume it is the very first screen
}
// ... the rest
}
-(void)setupFinished
{
// Here You animately restoring your initial vc.
YouAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
appDelegate.window.rootViewController = self; // This line is for device orientation sync
[UIView transitionWithView:appDelegate.window
duration:FINISH_DURATION
options:UIViewAnimationOptionTransitionCrossDissolve | UIViewAnimationOptionCurveEaseInOut
animations:^{ appDelegate.window.rootViewController = self; }
completion:nil];
// setUpNav controller will be dealloced by ARC
}
In your setUpNavViewController after you finished all defaults job you set notification for your delegation:
[self.initator setupFinished];
In may app this setting work is actually a separate storyboard with it's own workflow in it. By the way using this approach you are able not only show it first time but whenever your app's user defaults is not set properly (like if you using settings bundle). You can show it modally, in navigation stack or in pop over (iPad case). It is a more generic approach.
Summary: The one who starts, he finishes.
Related
I’m new in iOS development. My question is, I’ve two view controllers.
viewController - A viewController - B
Now, if i killed the app from the viewController - A and than relaunch the app. than app must be open the viewController - A. and if i killed the app from the viewController - B and than relaunch the app. than app must be open the viewController - B.
Can anyone help me, I’ve done the RND but can not find the proper solution.
Thanks
Create a sharedDelegate in AppDelegate.m file
+(AppDelegate *)sharedDelegate {
return (AppDelegate *) [UIApplication sharedApplication].delegate;
}
in AppDelegate.h
+ (AppDelegate *)sharedDelegate;
#property (nonatomic, strong) NSString *currentViewContoller;
when push to any contoller then set AppDelegate's currentViewContoller to new VC
YourViewController *vc=[[YourViewController alloc] init];
[self.navigationController pushViewController:vc animated:YES];
[AppDelegate sharedDelegate].currentViewContoller = NSStringFromClass([YourViewController class]);
now when app is terminated
- (void)applicationWillTerminate:(UIApplication *)application {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
[[NSUserDefaults standardUserDefaults]setObject:[AppDelegate sharedDelegate].currentViewContoller forKey:#"currentVC"];
}
now when app launched first time check previous controller when app terminated
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
NSString *string=[[NSUserDefaults standardUserDefaults] valueForKey:#"currentVC"];
and push this class
UIViewController *object = [[NSClassFromString(string) alloc] init...];
}
applicationWillTerminate you can use but it will only get called if user quit app from forground If your app is in background and then user quit app then applicationWillTerminate will not get called.
So, you have to take care of applicationDidEnterBackground.
So, when app enter in background (i.e call applicationDidEnterBackground ) or call applicationWillTerminate save state(your current VC) in your user defaults.
Now in your didFinishLaunchingWithOptions set that view controller as rootviewcontroller or whatever way that you want to manage it.
reference : Apple documentation for applicationWillTerminate
PS : You should not manage app like this. It is horrible way!! If possible then run your app as normal flow!
If you're using Storyboards you can use the Restoration Identifier to communicate the App which controller to launch as first
https://developer.apple.com/library/ios/featuredarticles/ViewControllerPGforiPhoneOS/PreservingandRestoringState.html
All of my apps are currently written in Obj-C. The link https://developer.apple.com/library/content/samplecode/ApplicationShortcuts/Introduction/Intro.html#//apple_ref/doc/uid/TP40016545 for the sample code of implementing Home Screen Shortcuts with 3D Touch is completely compiled in Swift. Anyone come across documentation for Obj-C, so I don't have to go through my AppDelegate and translate it all?
UPDATE:
After adding in all the shortcuts in Info.plist, I added in the AppDelegate.m:
- (void)application:(UIApplication *)application performActionForShortcutItem:(UIApplicationShortcutItem *)shortcutItem completionHandler:(void (^)(BOOL))completionHandler {
UINavigationController *nav = (UINavigationController *) self.tabBarController.selectedViewController;
NSLog(#"%#", shortcutItem.type);
if ([shortcutItem.type isEqualToString:#"com.316apps.iPrayed.addPrayerRequest"]) {
Requests *gonow = [[Requests alloc] init];
[nav pushViewController:gonow animated:YES];
}
if ([shortcutItem.type isEqualToString:#"com.316apps.iPrayed.addPrayer"]) {
PrayerStats *controller = [[PrayerStats alloc] init];
[nav pushViewController:controller animated:YES];
}
if ([shortcutItem.type isEqualToString:#"com.316apps.iPrayed.addFast"]) {
FastStats *controller1 = [[FastStats alloc] init];
[nav pushViewController:controller1 animated:YES];
}
if ([shortcutItem.type isEqualToString:#"com.316apps.iPrayed.addStudy"]) {
StudyStats *controller2 = [[StudyStats alloc] init];
[nav pushViewController:controller2 animated:YES];
}
}
This allows it to work, without putting any other methods in, or adding anything to didFinishLaunchingWithOptions.
There are two states from where the user can open the app through Quick Actions.
TL;DR
You are always doing the same thing regardless of the state in which the app is when the quick action is done, that's why you only need to override application:performActionForShortcutItem:completionHandler: So if you wanted to do different things, then you would want to handle them in the two places, if not then just the overridden is enough.
One is if the app is killed or not running in background where we get the shortcut info on launch.
The other is if the app is running in background where we get the shortcut info on the new app delegate method.
To handle these Quick Action shortcuts when in background you need to override this method on App Delegate:
- (void)application:(UIApplication *)application performActionForShortcutItem:(UIApplicationShortcutItem *)shortcutItem completionHandler:(void (^)(BOOL))completionHandler
And for not running in background (killed) on your
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
or
-(BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions
you should check if the app was launched by a Quick Action:
UIApplicationShortcutItem *shortcutItem = [launchOptions objectForKey:UIApplicationLaunchOptionsShortcutItemKey];
(Link to related Apple Documentation)
Quote from the Official Apple Docs
It’s your responsibility to ensure the system calls this method
conditionally, depending on whether or not one of your app launch
methods (application:willFinishLaunchingWithOptions: or
application:didFinishLaunchingWithOptions:) has already handled a
quick action invocation. The system calls a launch method (before
calling this method) when a user selects a quick action for your app
and your app launches instead of activating.
The requested quick action might employ code paths different than
those used otherwise when your app launches. For example, say your app
normally launches to display view A, but your app was launched in
response to a quick action that needs view B. To handle such cases,
check, on launch, whether your app is being launched via a quick
action. Perform this check in your
application:willFinishLaunchingWithOptions: or
application:didFinishLaunchingWithOptions: method by checking for the
UIApplicationLaunchOptionsShortcutItemKey launch option key. The
UIApplicationShortcutItem object is available as the value of the
launch option key.
If you find that your app was indeed launched using a quick action,
perform the requested quick action within the launch method and return
a value of NO from that method. When you return a value of NO, the
system does not call the
application:performActionForShortcutItem:completionHandler: method.
Implement below 3 simple steps:
Step 1 : Write below method in AppDelegate class to Configure dynamic shortcut items.
NOTE : You can configure shortcut items in info.plist if you want it static.
(Refer Apple documentation.)
/**
* #brief config dynamic shortcutItems
* #discussion after first launch, users can see dynamic shortcutItems
*/
- (void)configDynamicShortcutItems {
// config image shortcut items
// if you want to use custom image in app bundles, use iconWithTemplateImageName method
UIApplicationShortcutIcon *shortcutSearchIcon = [UIApplicationShortcutIcon iconWithType:UIApplicationShortcutIconTypeSearch];
UIApplicationShortcutIcon *shortcutFavoriteIcon = [UIApplicationShortcutIcon iconWithType:UIApplicationShortcutIconTypeFavorite];
UIApplicationShortcutItem *shortcutSearch = [[UIApplicationShortcutItem alloc]
initWithType:#"com.sarangbang.QuickAction.Search"
localizedTitle:#"Search"
localizedSubtitle:nil
icon:shortcutSearchIcon
userInfo:nil];
UIApplicationShortcutItem *shortcutFavorite = [[UIApplicationShortcutItem alloc]
initWithType:#"com.sarangbang.QuickAction.Favorite"
localizedTitle:#"Favorite"
localizedSubtitle:nil
icon:shortcutFavoriteIcon
userInfo:nil];
// add all items to an array
NSArray *items = #[shortcutSearch, shortcutFavorite];
// add the array to our app
[UIApplication sharedApplication].shortcutItems = items;
}
Step 2 : In AppDelegate class application didFinishLaunchingWithOptions method write below code.
// UIApplicationShortcutItem is available in iOS 9 or later.
if([[UIApplicationShortcutItem class] respondsToSelector:#selector(new)]){
[self configDynamicShortcutItems];
// If a shortcut was launched, display its information and take the appropriate action
UIApplicationShortcutItem *shortcutItem = [launchOptions objectForKeyedSubscript:UIApplicationLaunchOptionsShortcutItemKey];
if(shortcutItem)
{
// When the app launch at first time, this block can not called.
//App launch process with quick actions
[self handleShortCutItem:shortcutItem];
}else{
// normal app launch process without quick action
}
}
Step 3 : Write below delegate method and completion handler in AppDelegate class.
/*
Called when the user activates your application by selecting a shortcut on the home screen, except when
application(_:,willFinishLaunchingWithOptions:) or application(_:didFinishLaunchingWithOptions) returns `false`.
You should handle the shortcut in those callbacks and return `false` if possible. In that case, this
callback is used if your application is already launched in the background.
*/
- (void)application:(UIApplication *)application performActionForShortcutItem:(UIApplicationShortcutItem *)shortcutItem completionHandler:(void (^)(BOOL))completionHandler{
BOOL handledShortCutItem = [self handleShortCutItem:shortcutItem];
completionHandler(handledShortCutItem);
}
/**
* #brief handle shortcut item depend on its type
*
* #param shortcutItem shortcutItem selected shortcut item with quick action.
*
* #return return BOOL description
*/
- (BOOL)handleShortCutItem : (UIApplicationShortcutItem *)shortcutItem{
BOOL handled = NO;
NSString *bundleId = [NSBundle mainBundle].bundleIdentifier;
NSString *shortcutSearch = [NSString stringWithFormat:#"%#.Search", bundleId];
NSString *shortcutFavorite = [NSString stringWithFormat:#"%#.Favorite", bundleId];
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
if ([shortcutItem.type isEqualToString:shortcutSearch]) {
handled = YES;
SecondViewController *vc = [storyboard instantiateViewControllerWithIdentifier:#"secondVC"];
self.window.rootViewController = vc;
[self.window makeKeyAndVisible];
}
else if ([shortcutItem.type isEqualToString:shortcutFavorite]) {
handled = YES;
ThirdViewController *vc = [storyboard instantiateViewControllerWithIdentifier:#"thirdVC"];
self.window.rootViewController = vc;
[self.window makeKeyAndVisible];
}
return handled;
}
If you look at the sample code provided for apple, you'll see that they suggest that you write a method that handles your shortcut item so that you can handle it in all three places:
application: performActionForShortcutItem,
application: didFinishLaunchingWithOptions and
willFinishLaunchingWithOptions
An example of what I did was:
- (BOOL)handleShortCutItem:(UIApplicationShortcutItem *)shortcutItem {
BOOL handled = NO;
if (shortcutItem == nil) {
return handled;
}
if ([shortcutItem.type isEqualToString:kFavoritesQuickAction]) {
handled = YES;
}
if (handled) {
// do action here
}
return handled;
}
Then you would just call this method in any place where you are getting a shortcut item. This should help you along your way!
I make an objective-c demo project for home screen quick action.
3D touch home quick action demo : https://github.com/dakeshi/3D_Touch_HomeQuickAction
The Demo project implements the static quick action without Info.plist file to avoid unwanted situations before launching the app at first.
You can easily change it to the dynamic quick action.
As mentioned in apple documentation, you can handle quick action in application:didFinishLaunchingWithOptions: method. In that case, you should return NO to block to call application:performActionForShortcutItem:completionHandler: method.
It works on both swift 3 and 4 (only on home screen shortcuts)
//Add plist items as show in image and write following method in Appdelegate
//3D Touch Method shortcuts from home screen
func application(_ application: UIApplication, performActionFor shortcutItem:UIApplicationShortcutItem, completionHandler: #escaping (Bool) -> Void) {
if shortcutItem.type == "Share" {
//handle action Share
let alert = UIAlertController(title: "3D touch Share", message: "Yahoo!!! 3D touch is working👌", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
self.window?.rootViewController?.present(alert,animated: true,completion: nil)
completionHandler(true)
} else if shortcutItem.type == "Logout" {
//handle action Type02
let alert = UIAlertController(title: "3D touch Logout", message: "Yahoo!!! 3D touch is working👌", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
self.window?.rootViewController?.present(alert,animated: true,completion: nil)
completionHandler(true)
} else {
completionHandler(false)
}
}
In my HomeViewController's viewDidAppear method, I have the following code:
- (void)viewDidAppear:(BOOL)animated{
[super viewDidAppear:animated];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
BOOL didRunBefore = [defaults boolForKey:#"didRunBefore"];
if (!didRunBefore) {
// check to see if children already exist (previous user)
NSArray *children = [CoreDataHelper getObjectsForEntity:NSStringFromClass([Child class]) withSortKey:#"name" andSortAscending:YES andContext:self.managedObjectContext];
if (children.count == 0) {
// send user to create fist child
UIStoryboard *storyboard = self.storyboard;
ChildEditTableViewController *editController = [storyboard instantiateViewControllerWithIdentifier:#"ChildEditControllerID"];
NSManagedObjectContext *newContext = [[NSManagedObjectContext alloc] init];
newContext.parentContext = self.managedObjectContext;
editController.managedObjectContext = newContext;
[self.navigationController pushViewController:editController animated:NO];
}
}
}
Here's the code from ViewDidLoad in ChildEditTableViewController:
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(#"Child Edit controller loaded");
self.availablePicker.delegate = self;
self.bankedPicker.delegate = self;
self.carryOverCellIsShowing = NO;
self.isNewChild = self.child == nil;
self.imageButton.layer.cornerRadius = self.imageButton.frame.size.width/2;
self.imageButton.layer.masksToBounds = YES;
[[self.imageButton imageView] setContentMode: UIViewContentModeScaleAspectFill];
if (self.isNewChild) {
// check to see if it's user's first time running app
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
BOOL didRunBefore = [defaults boolForKey:#"didRunBefore"];
if (!didRunBefore) {
// hide Home back button
[self.navigationItem setHidesBackButton:YES];
// update didRunBefore to yes
[defaults setBool:YES forKey:#"didRunBefore"];
[defaults synchronize];
}
self.child = [NSEntityDescription insertNewObjectForEntityForName:#"Child" inManagedObjectContext:self.managedObjectContext];
self.title = NSLocalizedString(#"Add New", #"Add New Title");
}
else {
if (self.child.profileImage != nil) {
[self.imageButton setImage:[UIImage squaredImageFromImage:[UIImage imageWithData:self.child.profileImage] scaledToSize:self.imageButton.frame.size.height] forState:UIControlStateNormal];
}
self.name.text = self.child.name;
self.autoBankSwitch.on = [self.child.autoBank boolValue];
self.carryOverSwitch.on = ![self.child.resetDailyTotal boolValue];
[self setCarryOverSwitchVisibility:self.autoBankSwitch];
}
// This will remove extra separators from tableview
self.tableView.tableFooterView = [[UIView alloc] initWithFrame:CGRectZero];
}
That code works fine as far as I can see the ChildEditTableViewController load on the screen, but then it automatically pops back to the home controller. I've checked the code in the child controller and the only time I pop the controller is when the user hits a button.
Here's the Save IBAction where I pop the controller:
- (IBAction)save:(UIBarButtonItem *)sender {
[self saveToDB:sender];
[self.navigationController popViewControllerAnimated:YES];
}
If I use self.navigationController setViewControllers instead, this does not happen and ChildEditTableViewController stays loaded on the screen, but clicking the Save button (which pops the view controller) doesn't do anything.
Any ideas? (Thanks!)
**** EDIT *****
I noticed it was working fine in iOS 7.1 and 7.03. The only difference from an UI perspective was this piece of code below:
// enable handling of push notifications
if ([application respondsToSelector:#selector(registerUserNotificationSettings:)]) {
// use registerUserNotificationSettings
UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:(UIRemoteNotificationTypeBadge
|UIRemoteNotificationTypeSound
|UIRemoteNotificationTypeAlert) categories:nil];
[[UIApplication sharedApplication] registerUserNotificationSettings:settings];
} else {
// use registerForRemoteNotifications
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound)];
}
In iOS 8 I was getting a prompt to allow notifications on the simulator (something that doesn't work on the sim in prior versions). After I clicked ok is when the EditChild controller would get popped. So I commented out that code in the app delegate and the controller stays loaded just like in iOS 7.
****** EDIT ******
Below is the ApplicationDidBecomeActive code
- (void)applicationDidBecomeActive:(UIApplication *)application
{
NSLog(#"%s", __PRETTY_FUNCTION__);
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
// move user to home screen so app is locked each time they open it (but not on first use)
SWRevealViewController* revealController = (SWRevealViewController*)self.window.rootViewController;
UINavigationController *nav = (UINavigationController *)revealController.frontViewController;
[nav popToRootViewControllerAnimated:YES];
}
So this is the culprit. This code is getting called again right after the user clicks Accept on the notifications registration alert, for some crazy reason.
I am thinking that the the callbacks in your application delegate are doing something to your view/controller hierarchy. I would add some break points in your application delegate methods applicationWillResignActive:, applicationDidBecomeActive: and see if they are doing anything.
I have an array stored in the ViewController.m. But when the app enters background, i want to post notifications from the array.
so my NSMutableArray "list" was created in ViewController.m but i need to use in AppDelegate.m
- (void)applicationDidEnterBackground:(UIApplication *)application
for (NSString *thing in list) {
UILocalNotification *notif = [[UILocalNotification alloc] init];
notif.alertBody = thing.text;
[[UIApplication sharedApplication] presentLocalNotificationNow:notif];
If ViewController.m is your main VC:
ViewController *yourVC = (ViewController*)self.window.rootViewController;
yourVC.yourMutableArray = whateverYouWant;
I recommend saving the data inside of NSUserDefaults however, then you can just easily access it and read/write anywhere. BTW the presenting of localNotifications from that method in the appDelegate is a bad idea. The app store will not be a fan of immediate notifications when someone tries to leave an app..if you're even able to.
I have some trouble. So i have AvPlayer and UIButton with play/stop.
Also: I have three UiViewControllers. I need that when I click on the first button on the first UIVIewController on the second controller, the third controller button is pressed also, respectively, on the contrary, too. How its make? Any proposition?
It's simple code - push on button - play URL Stream and also when push again stop music.
-(IBAction)playRadioButton:(id)sender
{
if(clicked == 0) {
clicked = 1;
NSLog(#"Play");
NSString *urlAddress = #"http://URLRADIOSTREAM";
NSURL *urlStream = [NSURL URLWithString:urlAddress];
myplayer = [[AVPlayer alloc] initWithURL:urlStream];
[myplayer play];
[playRadioButton setTitle:#"Pause" forState:UIControlStateNormal];
}
else
{
NSLog(#"Stop");
[myplayer release];
clicked = 0;
[playRadioButton setTitle:#"Play" forState:UIControlStateNormal];
}
}
If you have several controllers that you need to notify about an event on another controller you can use NSNotificationCenter
Eg. in one controller in ViewDidLoad
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(playBtnClicked:)
name:#"BTN_CLICKED"
object:nil];
Also in the same controller define the selector e.g.
-(void)playBtnClicked:(NSNotification *)pNotification
{
// do something
}
In the other controller trigger it by using
[[NSNotificationCenter defaultCenter]
postNotificationName:#"BTN_CLICKED" object:nil];
If you don't want to use nsnotifications then use protocol and notify other viewcontrollers by using delegates
First of all, are the 3 view controllers allocated and initialized at once? If not, I recommend you set a property on your AppDelegate class, like this:
#interface AppDelegate
#property (nonatomic, assign) BOOL commonButtonPressed;
// All your code here
#end
And you can set this property like this:
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
appDelegate.commonButtonPressed = YES; // or NO;
Then, from your UIViewController classes:
- (void)viewWillAppear:(BOOL)animated {
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
if (appDelegate.commonButtonPressed) {
// Logic of what happens to the button goes here.
}
}
Another way of doing this, without touching your AppDelegate class is using NSUserDefaults, like this:
[[NSUserDefaults standardDefaults] setBool:(<YES or NO>) forKey:#"commonButtonPressed"];
[[NSUserDefaults standardDefaults] synchronize];
You can read back the value like this:
BOOL buttonPressed = [[NSUserDefaults standardDefaults] boolForKey:#"commonButtonPressed"];