blog

Photo of wall and gate by Henning Kesselhut on Unsplash

Gate External Links in Kids’ Apps

by | Dec 19, 2013 | Developer Blog | 0 comments

Release after release, Apple raises the bar on its requirements for inclusion in its app store.  Sometimes these are welcome technical changes, like explicit user permission to access contacts.  Other times they feel more like hurdles for app developers and users to jump – or in this case, the appropriate metaphor is stepping through a flimsy backyard gate.

iOS 7 introduced a new requirement for kids apps:

24.3 Apps primarily intended for use by kids under 13 must get parental permission or use a parental gate before allowing the user to link out of the app or engage in commerce

This requirement was probably inspired by the Children’s Online Privacy Protection Act (COPPA), which establishes rules related to collecting personal data from children.  Apple applies the requirement to interface elements like iTunes app store links and social sharing buttons.  However, the requirement is remarkably non-specific as to what constitutes a sufficiently sturdy parental gate.

iOS 7 does not include an API for constructing a gate, and Apple does not provide any further clarification.  Is the gate as simple as a yes or no question or a birthdate entry field, like a website age verification form?  Or as secure as requiring the user to enter a secret passcode?

Many apps are implementing gates that require the user to perform some action that would be difficult for a young child but easy for an adult, like:

  • Answer a simple math question
  • Tap and hold a button
  • Perform a multi-finger swipe

A blog post at Moms with apps showcases a nice screenshot gallery of parental gates implementing these ideas.

Implementation

There are at least two publicly available implementations, including:


Writing your own implementation based on UIAlertView with a text field is quite straight-forward.  Here’s an example that uses a success block.

@interface ParentalGate : UIAlertView
typedef void (^ParentalGateSuccess) (ParentalGate* gate);
@property (nonatomic, copy) ParentalGateSuccess success;
- (id)initWithSuccess:(ParentalGateSuccess)success;
@end
@implementation ParentalGate
- (id)initWithSuccess:(ParentalGateSuccess)success;
{
   self = [super initWithTitle:@"35 + 55"
                       message:nil
                      delegate:self
             cancelButtonTitle:@"Cancel"
             otherButtonTitles:@"Continue", nil];
   if (self)
   {
      self.success = success;
      self.alertViewStyle = UIAlertViewStylePlainTextInput;
   }
   return self;
}
- (BOOL)HasCorrectAnswer
{
   NSInteger answer = [[self textFieldAtIndex:0].text integerValue];
   return 90 == answer;
}
- (BOOL)alertViewShouldEnableFirstOtherButton:(UIAlertView*)alertView
{
   return [self HasCorrectAnswer];
}
// Use didDismiss rather than clickedButton because a display bug can occur
// if the caller tries to show another alert view before this alert view
// has been dismissed.
- (void)alertView:(UIAlertView*)alertView
didDismissWithButtonIndex:(NSInteger)buttonIndex
{
   if (1 == buttonIndex && [self HasCorrectAnswer])
   {
      self.success(self);
   }
}
@end

The alert view enables the "Continue" button only when the correct answer is provided. When the alert view is dismissed from the "Continue" button, the success callback function is run.

Example usage:

ParentalGate* gate = [[ParentalGate alloc] initWithSuccess:^(ParentalGate* gate)
{
   [[UIApplication sharedApplication] openURL:iTunesLink];
}];
[gate show];

It can, of course, be made more secure by randomizing the equation numbers with a random number generator, like:

// Generate a random number between 10 and 100.
10 + arc4random() % 91

Will Apple accept this gate? Past performance is no guarantee of future results, and I would consider a sturdier gate for an app targeting 9-11 year olds. But until Apple provides further clarification directly or through responses to app developers, it appears to be good enough.

+ more

Accurate Timing

Accurate Timing

In many tasks we need to do something at given intervals of time. The most obvious ways may not give you the best results. Time? Meh. The most basic tasks that don't have what you might call CPU-scale time requirements can be handled with the usual language and...

read more