Apollo iOS 1.2 迁移指南
从 1.0 - 1.1 到 1.2
本指南描述了将您的代码从版本 1.0 或 1.1 迁移到 Apollo iOS 1.2 版本的过程。Apollo iOS。
尽管 1.2 是一个 minor 版本升级,但在这个版本中解决了一个关键问题,升级过程中需要进行小的重大变更是必需的。虽然我们努力使次要版本的升级路径平滑,但如果没有这次迁移,无法合理地解决这个问题。
缓存键配置 API
本版本中配置自定义缓存键的 API 实现了细微的变化。在您生成的SchemaConfiguration.swift
文件中定义的cacheKeyInfo(for:objecthots:)
函数已进行了修改。
在先前版本中,objecthots:
参数是JSONObject
类型,这是一个typealias
,表示Dictionary<String, AnyHashable>
类型。在 1.2 版本中,objecthots:
参数是新建类型ObjectData
。
为保留您的实现,SchemaConfiguration.swift
文件只会在第一次生成代码时生成。这意味着在升级到 Apollo iOS 1.2 时,您需要修改cacheKeyInfo(for:objecthots:)
函数的函数签名。
对于新项目,该函数将在第一次生成代码时正确生成。
理由
因为缓存键解析在原始JSON(来自网络响应)和SelectionSet
模型数据(直接写入缓存时)上同时进行,因此底层object
数据将具有不同的格式。这种不一致性导致了一些用户难以跟踪的bug。ObjectData
包装器struct
用于在cacheKeyInfo(for:object:)
函数的上下文中规范这种数据以保持一致格式。
迁移步骤
对于大多数用户,更改只是将函数签名从
public enum SchemaConfiguration: ApolloAPI.SchemaConfiguration {static func cacheKeyInfo(for type: Object, object: JSONObject) -> CacheKeyInfo? {/// ...}}
修改为
public enum SchemaConfiguration: ApolloAPI.SchemaConfiguration {static func cacheKeyInfo(for type: Object, object: ObjectData) -> CacheKeyInfo? {/// ...}}
对于大多数基本用例,这些用例仅使用object
的subscript
来访问其值,这将是足够的。ObjectData
结构体并没有提供与Dictionary
相同的API,并且存在一些语义上的差异,您可能需要解决。我们建议运行充分的测试以确认您的缓存键解析函数仍然返回预期的值。
如果您的缓存键解析函数在新函数签名下无法编译或无法正确解析缓存键,请继续阅读以获取更多信息。
底层值类型更改
The ObjectData
struct 允许您以保持值类型一致性的方式访问提供的object
中的值。如果您的对cacheKeyInfo(for:object:)
函数的实现将值转换为特定预期类型,则可能需要修改您的代码以确保正确执行类型转换。
- 标量类型
- 原始的标量值(
String, Int, Float, Double
或Bool
)
- 原始的标量值(
- 自定义标量类型
- 自定义标量将被反序列化为从类型
jsonValue
属性返回的原始值。 - 有关更多信息,请参阅自定义标量。
- 自定义标量将被反序列化为从类型
- 对象类型s
- 对于其他嵌套在传入的GraphQL对象,将返回另一个
ObjectData
结构体。 - 在之前的版本中,返回值是另一个
JSONObject
(即。Dictionary
)。
- 对于其他嵌套在传入的GraphQL对象,将返回另一个
- 列表类型
- 对于列表字段,返回值是新定义的
ListData
结构体。 ListData
结构体与ObjectData
结构体功能相同,但是包裹了一个元素数组而不是字典。
- 对于列表字段,返回值是新定义的
ObjectData
API 限制
The ObjectData
结构体公开了一个显著受限的 API。它仅允许对底层数据的键值对进行索引访问。通常,这个 API 应该足以访问解决缓存键所需的值。如果您cacheKeyInfo(for:object:)
函数正在使用任何其他功能来使用Dictionary
,您需要重构您的代码。
为了避免对缓存键解析机制的复杂性要求,仅在需要时根据用户反馈对ObjectData
API进行扩展。如果您的cacheKeyInfo(for:object:)
函数需要在ObjectData
上公开其他功能,请提交一个功能请求.
示例
让我们考虑一个示例cacheKeyInfo(for:object:)
函数,它是从之前版本中需要修改以迁移到1.2版本的。
public enum SchemaConfiguration: ApolloAPI.SchemaConfiguration {static func cacheKeyInfo(for type: Object, object: JSONObject) -> CacheKeyInfo? {switch type {case Objects.User:let userInfo = object[info] as? [String: AnyHashable]let emailList = userInfo["emailAddresses"] as? [String]return try? CacheKeyInfo(jsonValue: emailList[0])case Objects.Post:let timestampCustomScalar = object["timestamp"] as? TimeStamplet timestampRawValue = object["timestamp"] as? Stringlet timestampString = (timestampCustomScalar?.jsonValue as? String)?? timestampRawValuereturn try? CacheKeyInfo(jsonValue: timestampString)case Objects.Product:return try? CacheKeyInfo(id: object["UPC"])default:return nil}}}
要将此函数迁移到1.2版本,我们需要进行一些更改。
- 必须将
object
参数更改为类型ObjectData
- 需要对
User
对象的info
字段进行类型转换,使其成为ObjectData
而不是[String: AnyHashable]
- 对于
User
对象的info.emailAddresses
应期望是ListData
类型而不是[String]
。 - 之前,
Post
对象的自定义标量timestamp的值可能是TimeStamp
自定义标量或其原始jsonValue类型,这取决于数据来源。现在,我们应该一直期待反序列化为jsonValue
– 在这种情况下,一个String
。 Product
对象的自定义字段UPC一直是标量值。这里不需要进行任何更改。
public enum SchemaConfiguration: ApolloAPI.SchemaConfiguration {static func cacheKeyInfo(for type: Object, object: ObjectData) -> CacheKeyInfo? {switch type {case Objects.User:let userInfo = object["info"] as? ObjectDatalet emailList = userInfo["emailAddresses"] as? ListDatareturn try? CacheKeyInfo(jsonValue: emailList[0] as? String)case Objects.Post:let timestamp = object["timestamp"] as? Stringreturn try? CacheKeyInfo(jsonValue: timestamp)case Objects.Product:return try? CacheKeyInfo(jsonValue: object["UPC"])default:return nil}}}
ObjectData
和ListData
索引访问器可以链式使用。这意味着User
对象的缓存密钥解决方法可以更简单地实现为:
case Objects.User:return try? CacheKeyInfo(jsonValue: object["info"]?["emailAddresses"]?[0])
Swift访问修饰符
1.2.0引入了新的代码生成配置参数,允许您指定生成的Swift类型的访问控制。1.2.0
引入了新的代码生成配置参数,允许您指定生成的Swift类型的访问控制。当使用模块类型为embeddedInTarget
或operation输出类型为relative
或absolute
时,您可以选择让生成的Swift类型可以通过public
或internal
访问。
您不需要将这些选项添加到您的代码生成配置中,但未指定选项时使用的默认值与先前的Apollo iOS版本不同。
在1.2.0
之前,所有的Swift类型都使用public
访问权限生成,新的配置选项的默认值是internal
。
这意味着您之前可能使用公有的Swift类型的地方,现在可能会出现编译器错误,因为这些类型不再可访问。要解决这个问题,您需要在代码生成配置中添加配置选项,指定public
访问修饰符。
您可能需要手动修改模式配置和自定义标量文件,因为如果这些文件已经存在,它们将不会被重新生成。手动更新它们的替代方案是删除这些文件,运行代码生成,然后重新添加任何可能在现有的自定义标量文件中使用的自定义逻辑。
示例
模块类型
"output": {"schemaTypes": {"moduleType": {"embeddedInTarget": {"name": "MyApplicationTarget","accessModifier": "public"}},"path": "./generated/schema/"}}
let configuration = ApolloCodegenConfiguration(// Other properties not shownoutput: ApolloCodegenConfiguration.FileOutput(schemaTypes: ApolloCodegenConfiguration.SchemaTypesFileOutput(path: "./generated/schema/",moduleType: .embeddedInTarget(name: "MyApplicationTarget", accessModifier: .public))...))
操作 - 相对
"output": {"operations" : {"relative" : {"subpath": "Generated","accessModifier": "public"}}}
let configuration = ApolloCodegenConfiguration(// Other properties not shownoutput: ApolloCodegenConfiguration.FileOutput(operations: .relative(subpath: "generated",accessModifier: .public)...))
操作 - 绝对
"output": {"operations" : {"absolute" : {"path": "Generated","accessModifier": "public"}}}
let configuration = ApolloCodegenConfiguration(// Other properties not shownoutput: ApolloCodegenConfiguration.FileOutput(operations: .absolute(path: "generated",accessModifier: .public)...))