26、iOS 应用发布与用户体验优化指南

iOS 应用发布与用户体验优化指南

1. iOS 应用发布

1.1 发布前准备

相较于 Android,iOS 应用的发布更为复杂。开发时可在自己的设备上进行测试,但要将应用公开,需拥有有效的 Apple Developer 账户,且具备在 App Store 发布的权限,因为 App Store 是唯一支持的应用发布渠道。

首先,要在 Xcode 项目设置中查看应用的相关信息,就像在 AndroidManifest.xml 中操作一样。之后,需检查 ios/Runner 目录下是否存在 GoogleService - Info.plist 文件。

1.2 App Store Connect 操作

在 Android 中,在 apk 准备好发布之前,无需在 Play Store Console 中进行任何配置。准备好 apk 后,可在 Play Console 创建注册表,填写描述、详细信息和营销设置,然后上传 apk 文件并发布。

而在 iOS 中,流程不同。上传和发布在 Xcode 中管理。要注册应用,需执行以下步骤:
1. 每个 iOS 应用都关联一个 Bundle ID,这是向 Apple 注册的唯一标识符。首先,在 App IDs 中创建记录,填写 Bundle ID,它相当于 Android 的 applicationId。
2. 然后,在 App Store Connect 门户中创建应用,选择上一步注册的 Bundle ID。

1.3 Xcode 设置

在 Xcode 中,需要进行一些更改以使应用准备好部署:
- 应用详情和 Bundle ID :在 Runner 项目的 General 选项卡中,可编辑应用的显示名称,即应用的名称。同时设置 Bundle ID,例如设置为 com.biessek.handson.favorsapp。注意 Version 和 Build 值,分别类似于 Android 中的 version name 和 version code。每次上传到 App Store(无论是正式版还是 TestFlight),都需要在 pubspec.yaml 文件中增加版本值。还可在 Deployment Target 中设置所需的最低 iOS 版本,默认值为 8.0,这是 Flutter 支持的最低版本。
- AdMob 配置 :与 AndroidManifest.xml 文件中的配置不同,在 iOS 中无需更新 AdMob ID。ID 值从传递给 Dart 中 FirebaseAdMob SDK 初始化的值中获取:

FirebaseAdMob.instance.initialize(
  appId: 'YOUR_ADMOB_APP_ID'
);
  • 应用签名 :和 Android 一样,需要一种方式来声明应用的所有权。Xcode 会为我们管理这一点,无需直接触碰任何文件。注册为 Apple Developer 并加入 Apple Developer Program 后,这些设置就已就绪。

1.4 最终发布步骤

完成上述设置后,可使用 flutter build ios 命令构建应用的 iOS 版本。然后在 Xcode 中进行最后一步发布操作:
1. 在 Xcode 中,选择 Product | Archive 生成构建存档。
2. 选择使用 flutter build ios 命令生成的构建存档。
3. 点击 Validate… 按钮。如果报告有任何问题,解决问题并重新生成构建。
4. 存档成功验证后,点击 Upload to App Store…。

完成这些步骤后,iOS 应用就准备好发布了。可以选择在 TestFlight(面向受信任用户的私有测试应用)或 App Store 上发布。

以下是发布流程的 mermaid 流程图:

graph LR
    A[准备 Apple Developer 账户] --> B[检查 Xcode 项目信息]
    B --> C[检查 GoogleService - Info.plist 文件]
    C --> D[App Store Connect 注册 Bundle ID]
    D --> E[App Store Connect 创建应用]
    E --> F[Xcode 设置应用详情等]
    F --> G[flutter build ios 构建应用]
    G --> H[Xcode 生成构建存档]
    H --> I[选择构建存档]
    I --> J[验证存档]
    J -->|有问题| F
    J -->|无问题| K[上传到 App Store]
    K --> L[选择发布方式(TestFlight 或 App Store)]

2. 提升用户体验

2.1 可访问性和国际化

为了让应用达到更高水平,需要使应用能够持续与用户上下文进行交互,即使应用当前未运行。开发国际化且完全可访问的应用有助于应用的逐步发展。

2.1.1 Flutter 的可访问性支持

在移动应用中正确实现可访问性可以提升用户体验,增加安装量并减少卸载量。Flutter 提供了以下组件来支持可访问性:
- 对比度 :Flutter 提供工具,使开发者能够为小部件适当地着色,以确保足够的对比度。可查看 W3C 推荐的对比度规范
- 大字体 :在 Flutter 中,文本小部件在确定字体大小时会遵循操作系统的设置。如果用户需要,字体可以放大。在 Android 和 iOS 中,可通过操作系统配置中的可访问性设置启用大字体。
- 屏幕阅读器 :Android 中的 TalkBack 和 iOS 中的 VoiceOver 使视障用户能够获得屏幕内容的语音反馈。Flutter 提供了 Semantics 小部件,让开发者能够描述小部件的含义,以便屏幕阅读器正常工作。可查看 小部件文档

2.1.2 Flutter 国际化

Flutter 提供了有助于国际化的小部件和类,其库本身也支持国际化。这借助了三个包:intl、intl_translation 和 flutter_localizations。
- intl 包 :Dart 的 intl 包是 Dart 翻译的基础,它提供国际化和本地化功能,包括消息翻译、复数和性别处理、日期/数字格式化和解析以及双向文本处理。可使用该包从 .arb 文件加载翻译内容。
- intl_translation 包 :基于 intl 包,仅在开发阶段需要。它包含一个工具,用于从 .arb 文件生成和解析翻译内容。
- flutter_localizations 包 :提供了 52 种语言(在撰写本文时)供 Flutter 小部件使用。默认情况下,Flutter 小部件仅提供美式英语本地化,因此要支持其他语言,可使用该包。

2.2 为 Flutter 应用添加本地化

2.2.1 添加依赖

首先,在 pubspec.yaml 文件中添加本地化依赖,并使用 flutter packages get 命令获取这些依赖:

dependencies:
  ...
  flutter_localizations:
    sdk: flutter
dev_dependencies:
  intl_translation: ^0.17.3
...
2.2.2 创建 AppLocalization 类

创建一个类来封装应用的本地化值,例如 AppLocalizations 类:

// part of app_localization.dart
import 'l10n/messages_all.dart';
import 'package:intl/intl.dart';
import 'package:flutter/material.dart';

class AppLocalizations {
  static Future<AppLocalizations> load(Locale locale) {
    final String name =
        locale.countryCode == null ? locale.languageCode : locale.toString();
    final String localeName = Intl.canonicalizedLocale(name);
    return initializeMessages(localeName).then((bool _) {
      Intl.defaultLocale = localeName;
      return new AppLocalizations();
    });
  }

  static AppLocalizations of(BuildContext context) {
    return Localizations.of<AppLocalizations>(context, AppLocalizations);
  }

  String get title {
    return Intl.message(
        'Hello Flutter',
        name: 'title', 
        desc: 'The application title'
    );
  }

  String get hello {
    return Intl.message('Hello', name: 'hello');
  }
}

AppLocalizations 类可分为四个主要部分:
- load 函数 :从所需的 Locale 加载字符串资源。
- of 函数 :类似于其他 InheritedWidget 的辅助函数,方便从应用代码的任何部分访问字符串。
- get 函数 :列出应用中已翻译的可用资源。
- initializeMessages :由 intl 工具生成的方法,用于加载翻译后的消息。

2.2.3 创建 AppLocalizationsDelegate 类

还需要创建一个类来为应用提供 AppLocalizations 资源:

import 'package:flutter/material.dart';

class AppLocalizationsDelegate extends LocalizationsDelegate<AppLocalizations> {
  const AppLocalizationsDelegate();

  @override
  bool isSupported(Locale locale) {
    return ['en', 'es', 'it'].contains(locale.languageCode);
  }

  @override
  Future<AppLocalizations> load(Locale locale) {
    return AppLocalizations.load(locale);
  }

  @override
  bool shouldReload(LocalizationsDelegate<AppLocalizations> old) {
    return false;
  }
}

该类可分为三个主要部分:
- load 函数 :返回包含相关资源集合的对象。
- isSupported :如果应用支持传入的 Locale,则返回 true。
- shouldReload :如果该方法返回 true,则在加载资源后所有应用小部件将重新构建。

2.2.4 生成 .arb 文件

定义这些类后,需要创建消息翻译。可使用 intl_translation 工具生成 .arb 文件:

flutter pub pub run intl_translation:extract_to_arb --output-dir=lib/l10n lib/app_localization.dart

该命令将在 lib/i10n 中生成一个名为 intl_messages.arb 的文件,作为翻译的模板:

{
  "@@last_modified": "2019-04-22T21:32:20.153408",
  "title": "Hello world App",
  "@title": {
    "description": "The application title",
    "type": "text",
    "placeholders": {}
  },
  "hello": "Hello",
  "@hello": {
    "type": "text",
    "placeholders": {}
  }
}

根据该文件创建所需的翻译,复制并将其重命名为 intl_ 文件,然后翻译所需的资源。

2.2.5 生成 Dart 代码

完成翻译后,使用以下命令生成包含翻译资源的 Dart 代码:

flutter pub pub run intl_translation:generate_from_arb --output-dir=lib/l10n lib/app_localization.dart lib/l10n/intl_en.arb lib/l10n/intl_es.arb lib/l10n/intl_it.arb
2.2.6 使用翻译资源

为了在应用中正确使用翻译资源,需要设置 MaterialApp 类的一些属性:

import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'app_localization.dart';

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      localizationsDelegates: [
        AppLocalizationsDelegate(),
        GlobalMaterialLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate
      ],
      supportedLocales: [Locale("en"), Locale("es"), Locale("it")],
      onGenerateTitle: (BuildContext context) => 
          AppLocalizations.of(context).title,
      theme: new ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: new MyHomePage(),
    );
  }
}

class MyHomePage extends StatelessWidget {
  MyHomePage({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(AppLocalizations.of(context).title),
      ),
      body: Center(
        child: Text(
          AppLocalizations.of(context).hello,
          style: Theme.of(context).textTheme.display1,
        ),
      ),
    );
  }
}

需要设置 localizationsDelegates 和 supportedLocales 属性。重复委托的 supportedLocales,并将 AppLocalizationsDelegate 以及 flutter_localizations 包中的 GlobalDelegates 添加到 localizationDelegates 数组中。

以下是国际化流程的表格总结:
|步骤|操作|
|----|----|
|添加依赖|在 pubspec.yaml 中添加 flutter_localizations 和 intl_translation 依赖|
|创建类|创建 AppLocalizations 和 AppLocalizationsDelegate 类|
|生成 .arb 文件|使用 intl_translation 工具生成模板文件|
|翻译资源|根据模板文件创建各语言的翻译文件|
|生成 Dart 代码|使用工具将翻译文件转换为 Dart 代码|
|使用资源|设置 MaterialApp 类的属性以使用翻译资源|

3. 原生代码与 Flutter 的通信:平台通道

3.1 通信需求与平台通道概述

自 2018 年 Flutter 发布首个稳定版本以来,其用户数量不断增加。开发者选择 Flutter 的一个重要原因是它能帮助开发出美观、动态且流畅的用户界面。然而,移动应用不仅需要出色的界面,还需具备各种功能,这就需要与不同宿主平台的 API 进行交互,例如蓝牙、相机、传感器、位置、用户权限、通知、文件存储和偏好设置以及与其他应用共享信息等。

为了让开发者在使用 Flutter 框架时不会因与平台代码的交互而感到困扰,Flutter 采用了平台通道来实现 Flutter 代码与原生 Swift/Objective - C 和 Kotlin/Java 代码之间的通信。

3.2 平台通道的工作原理

Flutter 应用运行在典型的原生应用中,当运行 Flutter 应用时,实际上有一个原生的 iOS 或 Android 应用在运行,并将 UI 委托给 Flutter。Flutter 自身负责渲染所有 UI,为了实现这一点,Flutter 原生层包含了设置 Android View 或 iOS UIViewController 的代码,以便框架能够正常工作。

与一些依赖代码生成将通用高级语言转换为原生语言的移动框架不同,Flutter 采用了灵活的消息传递方式,即平台通道。其结构如下:

Flutter 应用通过平台通道向应用的宿主/原生(iOS 或 Android)部分发送消息。宿主/原生部分监听平台通道,接收消息并通过自身实现进行处理,利用系统提供的 API,最后将结果返回给调用的 Flutter 部分。

以下是平台通道工作流程的 mermaid 流程图:

graph LR
    A[Flutter 应用] -->|发送消息| B[平台通道]
    B -->|传递消息| C[宿主/原生部分(iOS 或 Android)]
    C -->|处理消息| D[使用系统 API]
    D -->|返回结果| C
    C -->|传递结果| B
    B -->|返回结果| A

3.3 方法通道回顾

在之前开发 Flutter 插件时,我们对方法通道有了初步了解。方法通道是 Flutter 平台通道的一种特殊形式。下面详细介绍其工作机制。

3.4 平台通道的应用场景

除了插件,之前提到的 PlatformViews 也依赖平台通道机制来交换数据。例如,在集成地图等原生视图时,就需要通过平台通道实现 Flutter 与原生代码之间的数据交互。

3.5 总结

通过上述内容,我们了解了 iOS 应用发布的详细流程,包括 App Store Connect 的操作、Xcode 的设置以及最终的发布步骤。同时,我们也学习了如何提升应用的用户体验,包括可访问性支持和国际化的实现方法。此外,还深入探讨了 Flutter 与原生代码之间的通信方式——平台通道。

在实际开发中,开发者可以根据这些知识,将应用顺利发布到 App Store,为不同地区和不同需求的用户提供优质的体验,并实现 Flutter 代码与原生代码的高效交互,充分发挥 Flutter 框架的优势。

以下是本文关键内容的列表总结:
1. iOS 应用发布
- 准备 Apple Developer 账户
- 检查 Xcode 项目信息和相关文件
- 在 App Store Connect 注册 Bundle ID 和创建应用
- 进行 Xcode 设置
- 构建并发布应用
2. 提升用户体验
- 实现可访问性支持,如对比度、大字体和屏幕阅读器支持
- 完成应用的国际化,包括添加依赖、创建类、生成和使用翻译资源
3. Flutter 与原生代码通信
- 了解平台通道的工作原理
- 回顾方法通道的应用
- 掌握平台通道在不同场景下的应用

通过遵循这些步骤和技术,开发者能够开发出功能强大、用户体验良好且具有广泛适用性的移动应用。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值