由于不可重现的错误,使用 Flutter 制作的 iOS 应用程序被拒绝

Posted

技术标签:

【中文标题】由于不可重现的错误,使用 Flutter 制作的 iOS 应用程序被拒绝【英文标题】:iOS app made with Flutter rejected due to unreproducible bug 【发布时间】:2021-08-17 07:13:09 【问题描述】:

我的应用被 Apple 拒绝,因为某项功能在 iPad (ios 14.6) 上无法正常运行。 我已经审查了代码和 XCode 设置并重新提交了几次,但 Apple 审查员说它仍然无法在 iPad 上运行。

该应用程序是使用 Flutter 制作的。有问题的功能是用 sqflite 实现的,它从本地数据库中读取存储的数据。 就代码而言,snapshot.hasData 似乎在FutureBuilderbuilder 属性中仍然是false,而它应该是true

但是,当我在 iPad/iPhone 模拟器上进行调试运行时,它运行良好。 (我没有真正的 iPhone 和 iPad,因此无法通过 TestFlight 进行检查)该应用的 android 版本已在 Google Play 商店上发布,并且可以在 Android 设备上正常运行。

我不确定出了什么问题,但我怀疑以下几点;

sqflite 的实现:我需要为 iOS 实现一些特殊的东西吗? XCode 签名和配置文件设置:我已将目标设置为 iOS 和 iPad,并将证书设置为“Apple Distribution”,所以应该没问题... 要访问 iOS 设备的本地存储,我需要设置一些额外的“功能”吗?

我想知道是否有人在 Apple 评论中遇到过同样的问题,或者是否有人对此了解更多。

flutter doctor -v的输出和出现bug的代码如下。

flutter doctor -v

[✓] Flutter (Channel beta, 2.2.0, on macOS 11.4 20F71 darwin-x64, locale en-JP)
    • Flutter version 2.2.0 at /Users/xxx/development/flutter
    • Framework revision b22742018b (2 weeks ago), 2021-05-14 19:12:57 -0700
    • Engine revision a9d88a4d18
    • Dart version 2.13.0

[✓] Android toolchain - develop for Android devices (Android SDK version 30.0.2)
    • Android SDK at /Users/xxx/Library/Android/sdk
    • Platform android-30, build-tools 30.0.2
    • Java binary at: /Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build 11.0.8+10-b944.6916264)
    • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Xcode 12.5, Build version 12E262
    • CocoaPods version 1.10.1

[✓] Chrome - develop for the web
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Android Studio (version 4.2)
    • Android Studio at /Applications/Android Studio.app/Contents
    • Flutter plugin can be installed from:
      ???? https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      ???? https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 11.0.8+10-b944.6916264)

[✓] VS Code (version 1.52.1)
    • VS Code at /Applications/Visual Studio Code.app/Contents
    • Flutter extension version 3.18.0

[✓] Connected device (2 available)
    • iPad (8th generation) (mobile) • CA6F44F0-33C5-421B-A7D4-5A73832AE926 • ios            • com.apple.CoreSimulator.SimRuntime.iOS-14-5 (simulator)
    • Chrome (web)                   • chrome                               • web-javascript • Google Chrome 91.0.4472.77

• No issues found!
child: FutureBuilder(
  future: _itemList, // List that is loaded by databaseHelper's Read method
  builder: (_, snapshot) 
    if (!snapshot.hasData) 
      return Center(
        child: CircularProgressIndicator(), // Apple reviewer says it shows infinately.
      );
     else if (snapshot.data.length >= 1) 
      return ListView.builder(
        itemCount: snapshot.data.length,
        itemBuilder: (_, int index) 
          return _buildItems(snapshot.data[index]); // This method returns the list of items.
        ,
      );
     else 
      return Text('no data');
    
  ,
),

【问题讨论】:

最有可能将snapshot.hasError 设置为true 数据是否已经添加到数据库中?还是在 api 获取后添加? @pskink 谢谢。我添加了if (snapshot.hasError) return Text(snapshot.error.toString()); 并重新提交给 Apple 以解构此问题。 @DarShan 触发此功能时数据库中已添加的数据。 可以发_itemList & db相关方法吗? 【参考方案1】:

感谢您的帮助!此问题已解决。 原因是_initDb方法生成的路径错误。

之前:

Future<Database> _initDb() async 
  Directory dir = await getApplicationDocumentsDirectory();
  String path = dir.path +
      'items_table.db'; 
  final itemsDb =
      await openDatabase(path, version: 1, onCreate: _createDb);
  return itemsDb;

此时print(path);, 安卓:/data/user/0/com.example.app_name/app_flutteritems_table.db -> 虽然路径不正确,但在实际的 Android 设备上运行良好。 iOS:/var/mobile/Containers/Data/Application/XXXXXX-XXXXX/Documentsitems_table.db -> 这会导致DatabaseException(open_failed) 作为snapshot.hasError == true 的输出。

要解决此问题,请修改代码以生成正确的路径。 我在数据库名称字符串前添加了/

Future<Database> _initDb() async 
  Directory dir = await getApplicationDocumentsDirectory();
  String path = dir.path +
      '/items_table.db'; 
  final itemsDb =
      await openDatabase(path, version: 1, onCreate: _createDb);
  return itemsDb;

然后,生成正确的路径。 安卓:/data/user/0/com.example.app_name/app_flutter/items_table.db iOS:/var/mobile/Containers/Data/Application/XXXXXX-XXXXX/Documents/items_table.db

【讨论】:

以上是关于由于不可重现的错误,使用 Flutter 制作的 iOS 应用程序被拒绝的主要内容,如果未能解决你的问题,请参考以下文章

测试中遇到不可重现的Bug怎么办?

索引超出了数组的范围,不可重现

Flutter 入口页面及底部导航栏实例制作

Flutter 入口页面及底部导航栏实例制作

03-Flutter移动电商实战-底部导航栏制作

如何制作一个出色的 R 可重现示例