Failing the App Store's Review

Posted by Angus Cheng on Sunday, February 27, 2022

Thursday was a good day, I was in a “get that shit done and out the door” sort of mood. Originally I was planning to have the following features in CantoRead:

  1. Extract Chinese text from user provided images
  2. Show an advertisement while processing a user’s image
  3. Allow users to buy a monthly/yearly subscription to turn off ads

On Thursday I decided to cut feature #3, Apple’s payment APIs are quite confusing to work with. I decided it would be better to implement feature #3 after passing Apple’s certification for the first time. I spent the day cleaning up various issues with the app, stripping out features and of course filling out endless forms about what I’m going to do with end user data.

At 1:35 AM I submitted CantoRead for review, by 6.24 PM it had failed review. I was really impressed with the turn around time, Apple has gotten a lot faster. Back in 2015 it took over a week to get a review result from Apple. It took me about a month to get my first app through review back in 2015.

Failure #1, Needless Login

Apple do not let you place a login page to your application unless you have a good reason to require a login. All you can do in the latest build of CantoRead is choose a photo, and view the definitions for the words in that photo. In a future build I will let users create flash cards from the text in their photos, those flash cards will be attributed to your user account. To deal with this, I removed the login requirement.

Before

func createViewModel() -> CantoneseProViewModel {
    let preferences = Preferences()
    let viewModel = CantoneseProViewModel()

    if let token = preferences.readToken() {
        viewModel.token = token
        viewModel.setState(UIState.HOME)
    }
    else {
        viewModel.setState(UIState.LOGIN_VIEW)
    }

    return viewModel
}

After

func createViewModel() -> CantoneseProViewModel {
    let viewModel = CantoneseProViewModel()
    viewModel.setState(UIState.HOME)
    return viewModel
}

Failure #2, Not Asking for Permission to Track

I show ads provided by AdMob in CantoRead. Admob’s SDK uses The Identifier for Advertisers (IDFA) to track users for targeted advertising. Apple requires that you ask the user for permission to access their IDFA. I forgot to do this. After reading around online I determined that all I needed to do was call this line of code after launching the app:

ATTrackingManager.requestTrackingAuthorization(completionHandler: { status in

})

I put the line of code in didFinishLaunchingWithOptions, but the dialog box didn’t appear. I read around a bit more and learned that the line of code is ignored if the app is not in the active state. Annoying. I added some code to my HomeView that shows the dialog box when the app is active.

ZStack {
    // a bunch of views that are irrelevant
}.onReceive(NotificationCenter.default.publisher(for: UIApplication.didBecomeActiveNotification)) { _ in
    ATTrackingManager.requestTrackingAuthorization(completionHandler: { status in
        debugPrint(status)
    })
}

CantoRead lets you choose a photo from your gallery or take a photo right in the app. If you take a photo in the app, I figured you’d probably want that photo in your gallery. To write items into a user’s gallery you need to provide a reason. I wrote Adds photos you take to your photo library. Apple didn’t like that, they said it was too vague. They’re probably right. I didn’t care enough about this feature to change the text, so I just removed the feature. Now when you take photos in the app they aren’t saved to your gallery.

Resubmitting

After those simple fixes I was ready to resubmit. I tried to upload the build but got an error. You do not have an App Store Connect account. What the hell? Did I get banned or something? Eventually I realised my Apple membership expired, so I paid up the $100 USD and resubmitted. Hopefully I’ll get through this time.