Apr 09

Say you want each customer to accept your Terms of Service, or some other legalese, before they can use your iPhone application.

Display the screen upon startup

The standard AppDelegate code generated by Xcode creates and displays your first application screen. Here’s a way that you can use the hidden property of UIView to display your new screen first without disrupting the flow of the rest of the application.

// Create window
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
[window setBackgroundColor:[UIColor whiteColor]];
    
// Set up main view navigation controller
MainMenuViewController *navController = [[MainMenuViewController alloc] init];
	
// Create a navigation controller using the new controller
navigationController = [[UINavigationController alloc] initWithRootViewController:navController];
navigationController.navigationBarStyle = UIBarStyleDefault;
	
[navController release];

// Create Terms of Service screen	
tosController = [[TermsOfServiceViewController alloc] init];
[window addSubview:[tosController view]];
navigationController.view.hidden = YES;

// Add the navigation controller's view to the window
[window addSubview:[navigationController view]];
[window makeKeyAndVisible];

Most of this is boilerplate code, more or less generated by Xcode. What’s new starts at line 14. Instantiate the new TermsOfServiceViewController and add it to the view. Standard stuff. The important line is #17, which hides the navigationController.

Dismiss the new screen

Now that the Terms of Service screen is displayed and the Main Menu is hidden we need a way to dismiss the ToS screen and return to the normal application flow.

In your AppDelegate class create a new method:

- (void)termsOfServiceAccepted
{
	tosController.view.hidden = YES;
	navigationController.view.hidden = NO;
}

In the TermsOfServiceController you would have a button that the user has to tap:

UIButton *acceptButton = [[UIButton buttonWithType:UIButtonTypeRoundedRect] retain];
acceptButton.frame = CGRectMake(kLeftMargin, 
						applicationFrame.size.height - kBottomMargin - kButtonHeight, 
						applicationFrame.size.width - kLeftMargin - kRightMargin, 
						kButtonHeight);
[acceptButton setTitle:NSLocalizedString(@"ButtonAcceptTermsOfService", @"") forStates:UIControlStateNormal];
[acceptButton addTarget:self action:@selector(termsOfServiceAccepted:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:acceptButton];

When the button is tapped, the selector is called which in turn calls the above method in the AppDelegate.

- (void)termsOfServiceAccepted:(id)sender
{
	id applicationDelegate = [[UIApplication sharedApplication] delegate];
	[applicationDelegate termsOfServiceAccepted];
}

Only show the screen once

With this code the ToS screen is displayed every time the application is started. That will quickly get annoying. So let’s add some code to only show it once by using a boolean stored in NSUserDefaults.

NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
if (![userDefaults boolForKey:TERMS_OF_USE_ACCEPTED]) {
	tosController = [[TermsOfServiceViewController alloc] init];
	[window addSubview:[tosController view]];
	navigationController.view.hidden = YES;
}

And in the termsOfServiceAccepted method set the boolean in NSUserDefaults.

- (void)termsOfServiceAccepted
{
	tosController.view.hidden = YES;
	navigationController.view.hidden = NO;

	// Store acceptance in UserDefaults
	NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
	[userDefaults setBool:YES forKey:TERMS_OF_USE_ACCEPTED];
}

Now the ToS screen is only shown until the user taps the accept button. Your customers will be happy, as will your lawyers.

written by Nick \\ tags: , ,

7 Responses to “How To Create a Terms of Service Screen”

  1. Kane Says:

    This example looks great, but it seems to be missing some parts that us newbies need to get this to work. (translation: I tried adding the code and am at a loss for how to get it to work)

    Do you by chance have a sample zip that has a working version of this? I have been trying to find examples of switching between views and have found nothing that really explains it so I don’t know what to do to make this work.

    Thanks,
    Kane

  2. Nick Dalton Says:

    Kane,

    To switch between views in a controller, all you have to do is change the self.view property. Set the value to the new view and it will instantly change. If you want a nice push transition you can use [CATransition animation].

    Once the NDA has been lifted I will be posting a lot more code here. Stay tuned!

    Thanks,
    Nick

  3. kiran Says:

    hi,
    i have tried ur code but am getting an error
    TermsOfServiceViewController not found
    in which framework does it contain and does it work for iphone

  4. Pankaj Says:

    Hiii,,

    I’m new in iPhone applications development. I’m building an application for iPhone. so I need list of email addresses stored in iPhone. Can anybody help me regarding this.

    Thanks,

    Pankaj

  5. Anthony Man Says:

    Any chance of the code sample now the NDA has been lifted, I would be interested to see how it all plugs together also.

    Specifically which methods you are calling the check for terms of service in

  6. Ben Blaukopf Says:

    This is great – but isn’t it superfluous? Apple prefer all the terms of service stuff to be done on the AppStore – they don’t want any T&Cs appearing in the application itself. See the HIG.

  7. Nick Says:

    Ben,

    In my experience, some content providers require an explicit acceptance of TOS. I think it would be a difficult legal position to argue that by purchasing an app from the App Store you are agreeing to a contract spelled out in the application description. Not that a click-contract is much better, but in this case it appeased my client’s lawyers.

Leave a Reply