因为App使用了Eureka,我自定义了一个Row,打算使用[Node]作为其Row的Value类型:
final class TreeTVCell: Cell<[Node]>,CellType{
}
大家知道Row的Value类型必须遵守Equatable协议。
我们先来看一下Node类。该类用Objc语言编写,十分简单:
#import "Node.h"
@implementation Node
- (instancetype)initWithParentId : (int)parentId nodeId : (int)nodeId name : (NSString *)name depth : (int)depth expand : (BOOL)expand{
self = [self init];
if (self) {
self.parentId = parentId;
self.nodeId = nodeId;
self.name = name;
self.depth = depth;
self.expand = expand;
}
return self;
}
@end
问题是当我在Xcode 9.3.1里编译App时一切正常,但是放到Xcode 9.2编译时就会出错,提示:
Type ‘[Node]’ does not conform to protocol ‘Equatable’
我们知道前者Swift的版本是4.1,而后者使用的版本是4.0。所以这就是Swift语言版本的问题了。
Swift 4.1从语言层面上做了升级,其中包括条件一致性的提升,包括 Equatable 和 Hashable 协议的自动实现和条件一致性等。
条件一致性即,泛型类型只有在其类型参数满足特定要求的时候才会遵循某个协议。例如,一个 Array 只有当它的元素也遵循 Equatable协议的时候,才能实现Equatable协议。
这就是为什么Swift 4.1从语言层面上说编译可以通过的原因。
那么如何在Swift 4.0上编译通过呢?我们可以采取变通的方法,用一个Wrap类来包装实际的[Node]对象,这得用到Swift语言的版本选择宏来完成:
#if !swift(>=4.1)
struct EquatableArray<Element:Equatable>:Equatable{
private let _array:[Element]
var array:[Element]{
return _array
}
init(_ array:[Element]){
_array = array
}
static func ==(lhs: EquatableArray<Element>,rhs: EquatableArray<Element>) -> Bool {
return lhs._array == rhs._array
}
}
#endif
然后我们分别以两种情况定义类TreeTVCell:
#if swift(>=4.1)
final class TreeTVCell: Cell<[Node]>,CellType {
//...
}
#else
final class TreeTVCell: Cell<EquatableArray<Node>>,CellType {
//...
}
#endif
最后我们分别在代码流中处理以上两种情况:
#if swift(>=4.1)
row.value = treeData
#else
row.value = EquatableArray(treeData)
#endif
通过使用包装器类,我们得以在不同Swift版本中都可以完成使用Eureka代码App的编译,That’s Good!!! :)