The MCSessionDelegate
protocol has changed in iOS 11 from
- (void) session:(MCSession *)session
didFinishReceivingResourceWithName:(NSString *)resourceName
fromPeer:(MCPeerID *)peerID
atURL:(NSURL *)localURL
withError:(nullable NSError *)error;
to
- (void) session:(MCSession *)session
didFinishReceivingResourceWithName:(NSString *)resourceName
fromPeer:(MCPeerID *)peerID
atURL:(nullable NSURL *)localURL
withError:(nullable NSError *)error;
This causes that, when implementing this delegate in Swift, using
func session(_ session: MCSession,
didFinishReceivingResourceWithName resourceName: String,
fromPeer peerID: MCPeerID,
at localURL: URL?,
withError error: Error?) {}
won't compile on Xcode 8; and
func session(_ session: MCSession,
didFinishReceivingResourceWithName resourceName: String,
fromPeer peerID: MCPeerID,
at localURL: URL,
withError error: Error?) {}
won't compile on Xcode 9.
In both cases Xcode shows this error:
Parameter of 'session(_:didFinishReceivingResourceWithName:fromPeer:at:withError:)' has different optionality than required by protocol 'MCSessionDelegate'
How to make it compile on both versions?
I don't see why this is a problem.
If you build with Xcode 8, you can use the old method signature, build you app and submit it to the AppStore. The app will be built against the iOS10 SDK, and will run on iOS10 and iOS11 devices.
When you switch to Xcode 9, you can switch to the new method signature, and (when Xcode 9 is out of beta) submit to the AppStore. The app is built against iOS11 SDK and will run on iOS11 devices.
The only difficulty is that brief period when you might want to use both Xcode 8 (to release app updates now) and Xcode 9 (preparing for app releases after iOS11 is released). You'd need to have a separate iOS11 branch in your git repo - but you'll be doing that anyway, right?
To improve code with mix & match of XCode versions , you can put check for swift versions like
#if swift(>=2.3)
let specifier = url.resourceSpecifier ?? ""
#else
let specifier = url.resourceSpecifier
#endif
But here’s a little helper that might be useful ..found on http://radex.io/xcode7-xcode8/:
func optionalize<T>(x: T?) -> T? {
return x
}
I know, it’s a little weird. Perhaps it will be easier to explain if you first see the result:
let URL = optionalize(url) ?? "" // works on both versions!
We’re taking advantage of Optional lifting to get rid of ugly conditional compilation at call site. See, what the optionalize() function does is it turns whatever you pass in into an Optional, unless it’s already an Optional, in which case, it just returns the argument as-is. This way, regardless if the url is optional (Xcode 8) or not (Xcode 7), the “optionalized” version is always the same.
(To explain in more detail: in Swift, Foo can be considered a subtype of Foo?, since you can wrap any value of Foo in an Optional without loss of information. And since the compiler knows about this, it allows you to pass a non-optional in place of an optional argument — lifting Foo into Foo?.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With