iOS11中的MCSessionDelegate
协议已从
- (void) session:(MCSession *)session
didFinishReceivingResourceWithName:(NSString *)resourceName
fromPeer:(MCPeerID *)peerID
atURL:(NSURL *)localURL
withError:(nullable NSError *)error;
自
- (void) session:(MCSession *)session
didFinishReceivingResourceWithName:(NSString *)resourceName
fromPeer:(MCPeerID *)peerID
atURL:(nullable NSURL *)localURL
withError:(nullable NSError *)error;
这导致在Swift中实现此委托时,使用
func session(_ session: MCSession,
didFinishReceivingResourceWithName resourceName: String,
fromPeer peerID: MCPeerID,
at localURL: URL?,
withError error: Error?) {}
无法在Xcode 8上编译;并且
func session(_ session: MCSession,
didFinishReceivingResourceWithName resourceName: String,
fromPeer peerID: MCPeerID,
at localURL: URL,
withError error: Error?) {}
无法在Xcode 9上编译。
在这两种情况下,Xcode都会显示此错误:
"session(_:didFinishReceivingResourceWithName:fromPeer:at:withError:)"的参数具有与协议"MCSessionDelegate"所要求的不同的可选性
如何使其在两个版本上编译?
我不明白为什么这是一个问题。
如果您使用 Xcode 8 进行构建,则可以使用旧方法签名,构建应用并将其提交到 AppStore。该应用程序将针对 iOS10 SDK 构建,并将在 iOS10 和 iOS11 设备上运行。
当您切换到 Xcode 9 时,您可以切换到新的方法签名,并(当 Xcode 9 超出测试阶段时)提交到 AppStore。该应用程序基于 iOS11 SDK 构建,将在 iOS11 设备上运行。
唯一的困难是您可能想要同时使用 Xcode 8(立即发布应用程序更新)和 Xcode 9(准备在 iOS11 发布后发布应用程序)的短暂时期。你需要在你的 git 存储库中有一个单独的 iOS11 分支 - 但无论如何你都会这样做,对吧?
要通过 XCode 版本的混合和匹配来改进代码,您可以检查 swift 版本,例如
#if swift(>=2.3)
let specifier = url.resourceSpecifier ?? ""
#else
let specifier = url.resourceSpecifier
#endif
但是这里有一个小助手可能很有用..在 http://radex.io/xcode7-xcode8/上找到:
func optionalize<T>(x: T?) -> T? {
return x
}
我知道,这有点奇怪。如果你第一次看到结果,也许会更容易解释:
let URL = optionalize(url) ?? "" // works on both versions!
我们正在利用可选提升来摆脱调用站点上丑陋的条件编译。看,optionalize() 函数的作用是将你传入的任何内容转换为 Optional,除非它已经是 Optional,在这种情况下,它只是按原样返回参数。这样,无论 url 是可选的 (Xcode 8) 还是不是可选的 (Xcode 7),"可选"版本始终相同。
(更详细地解释:在 Swift 中,Foo 可以被认为是 Foo 的一个子类型?,因为您可以将 Foo 的任何值包装在 Optional 中而不会丢失信息。由于编译器知道这一点,它允许你传递一个非可选的参数来代替一个可选的参数——将Foo提升到Foo?