为什么我的iOS应用对于我的Apple评论者可能会停留在启动屏幕上,但对我来说却不会?

时间:2019-05-15 03:05:35

标签: ios firebase firebase-authentication appstore-approval

我正在构建一个新的iOS应用,提交给App Store进行审核后,该应用被拒绝,审核者说:

  

在运行Wi-Fi的iOS 12.3的iPad上进行审核时,我们发现您的应用中存在一个或多个错误。

     

具体来说,该应用卡在了启动屏幕上。没有其他内容加载。

但是,我个人无法重现此问题。

我已经尝试过在所有使用Xcode的模拟器上进行全新安装,以及在iOS 12.3上的物理iPhone XS Max和物理iPad Pro 11in上进行全新安装。运行iOS 12.3,并且该应用始终能够快速,快速地通过启动/启动屏幕。我所有的安装都是通过Xcode完成的,但是我也尝试通过TestFlight进行安装,并且再次无法重现该问题。

编辑:应该提到我也尝试了没有网络连接并且应用程序成功加载的情况。

代码

我只在启动屏幕上使用情节提要,它仅包含应用程序徽标的单个居中图像。除此之外,我所有的UI都是以编程方式完成的。在AppDelegate didFinishLaunchingWithOptions中,我安装了一个root viewcontroller,它所做的第一件事是通过Auth.auth().addStateDidChangeListener检查Firebase身份验证。如果没有用户,那么我会立即切换到登录视图控制器。

由于首次使用该应用程序的任何人都没有登录,因此我似乎无法理解为什么该应用程序会挂在初始屏幕上,除非Firebase auth侦听器未取得任何进展。

(已编辑为包含)下面的实际代码。

func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    // Override point for customization after application launch.

    // Firebase
    FirebaseApp.configure()

    // Set custom root view controller
    window = UIWindow(frame: UIScreen.main.bounds)
    window?.rootViewController = RootViewController()
    window?.makeKeyAndVisible()

    return true
}
class RootViewController: UIViewController {

    private var current: UIViewController

    init() {
        self.current = SplashViewController()
        super.init(nibName: nil, bundle: nil)
    }   

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        addChild(current)
        current.view.frame = view.bounds
        view.addSubview(current.view)
        current.didMove(toParent: self)
    }
    ...
}
class SplashViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        view.backgroundColor = UIColor.white

        let image = UIImageView(image: UIImage(named: "1024.png")!)
        image.contentMode = .scaleAspectFit
        image.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(image)
        image.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
        image.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
        image.widthAnchor.constraint(equalToConstant: 128).isActive = true
        image.heightAnchor.constraint(equalToConstant: 128).isActive = true

        checkAuthenticationAndChangeScreens()
    }

    private func checkAuthenticationAndChangeScreens() {
        Auth.auth().addStateDidChangeListener { (auth, user) in
            if let user = user {
                UserDefaults.standard.set(user.uid, forKey: "userEmail")
                PushNotificationManager().registerForPushNotifications {
                    PartnerManager.shared.fetchPartnerEmail() {
                        AppDelegate.shared.rootViewController.switchToMainScreen()
                    }
                }
            } else {
                AppDelegate.shared.rootViewController.switchToLogOut()
                UIApplication.shared.unregisterForRemoteNotifications()
            }
        }
    }
}
// Class PushNotificationManager
func registerForPushNotifications(completion: @escaping () -> Void) {
    UNUserNotificationCenter.current().delegate = self
    UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound, .badge]) {
        granted, error in
        guard granted else { return }
        DispatchQueue.main.async {
            Messaging.messaging().delegate = self //Firebase Messaging
            UIApplication.shared.registerForRemoteNotifications()
            self.updateFirestorePushTokenIfNeeded() // Makes a single write to Firestore
            completion()
        }
    }
}
// Class PartnerManager
func fetchPartnerEmail(completion: @escaping () -> Void) {
    let userUID = UserDefaults.standard.string(forKey: "userEmail")
    db.collection("users").document(userUID).getDocument() {
        (document, error) in
        if let partnerEmail = document!.get("partnerEmail") as? String {
            UserDefaults.standard.set(partnerEmail, forKey: "partner")
        } 
        completion()
    }
}

有些奇怪

让我感到困惑的最后一件事是,虽然我向应用商店提交的内容由于该应用卡在启动屏幕上(以及启动屏幕的屏幕截图)而被拒绝,但我提交的Beta测试版本却是由于不同的原因而被拒绝-我没有提供应有的登录详细信息,但是在这里,他们提供了我的登录屏幕的屏幕快照。但这意味着该应用已超出初始屏幕的Beta测试审查范围。

这使我认为也许问题出在Apple的某种测试环境。

Apple评论测试环境是否有所不同?我如何更好地重现此卡死的启动画面问题?为什么Beta测试审阅者似乎能够正确加载应用程序,而App Store审阅者却不能?

1 个答案:

答案 0 :(得分:3)

这可能是因为您的UI更新未在主线程上完成。

尝试:

DispatchQueue.main.async {
    //Update rootViewController now
}

我曾经犯过类似的错误。 不能保证UI更新是一个随机问题,因为它没有明确显示在主线程上。