|
2 | 2 |
|
3 | 3 | swift-corelibs-foundation contains new features and API in the Swift 5.x family of releases. These release notes complement the [Foundation release notes](https://developer.apple.com/documentation/ios_release_notes/ios_12_release_notes/foundation_release_notes) with information that is specific to swift-corelibs-foundation. Check both documents for a full overview.
|
4 | 4 |
|
| 5 | +## Improvements to NSCoder |
| 6 | + |
| 7 | +In this release, the implementation of `NSCoder` and related classes has been brought closer to the behavior of their Darwin counterparts. There are a number of differences from previous versions of swift-corelibs-foundation that you should keep in mind while writing code that uses `NSKeyedArchiver` and `NSKeyedUnarchiver`: |
| 8 | + |
| 9 | +* In previous versions of swift-corelibs-foundation, the `decodingFailurePolicy` setting was hardcoded to `.setAndReturnError`; however, failure in decoding would crash the process (matching the behavior of the `.raiseException` policy). This has been corrected; you can now set the `decodingFailurePolicy` to either policy. To match Darwin, the default behavior has been changed to `.raiseException`. |
| 10 | + |
| 11 | +* On Darwin, in certain rare cases, invoking `failWithError(_:)` could stop execution of an initializer or `encode(with:)` method and unwind the stack, while still continuing program execution (by translating the exception to a `NSError` to a top-level caller). Swift does not support this. The `NSCoder` API documented to do this (`decodeTopLevelObject…`) is not available on swift-corelibs-foundation, and it has been annotated with diagnostics pointing you to cross-platform replacements. |
| 12 | + |
| 13 | +* The following Foundation classes that conform to `NSCoding` and/or `NSSecureCoding` now correctly implement archiving in a way that is compatible with archives produced by their Darwin counterparts: |
| 14 | + |
| 15 | + - `NSCharacterSet` |
| 16 | + - `NSOrderedSet` |
| 17 | + - `NSSet` |
| 18 | + - `NSIndexSet` |
| 19 | + - `NSTextCheckingResult` (only for results whose type is `.regularExpression`) |
| 20 | + - `ISO8601DateFormatter` |
| 21 | + - `DateIntervalFormatter` |
| 22 | + |
| 23 | +* The following Foundation classes require features not available in swift-corelibs-foundation. Therefore, they do not conform to `NSCoding` and/or `NSSecureCoding` in swift-corelibs-foundation. These classes may have conformed to `NSCoding` or `NSSecureCoding` in prior versions of swift-corelibs-foundation, even though they weren't complete prior to this release. |
| 24 | + |
| 25 | + - `NSSortDescriptor` (requires key-value coding) |
| 26 | + - `NSPredicate` (requires key-value coding) |
| 27 | + - `NSExpression` (requires key-value coding) |
| 28 | + - `NSFileHandle` (requires `NSXPCConnection` and related subclasses, which are not available outside of Darwin) |
| 29 | + |
| 30 | + While the type system may help you find occurrences of usage of these classes in a `NSCoding` context, they can still be, incorrectly, passed to the `decodeObjects(of:…)` method that takes a `[AnyClass]` argument. You will need to audit your code to ensure you are not attempting to decode these objects; if you need to decode an archive that contains these objects from Darwin, you should skip decoding of the associated keys in your swift-corelibs-foundation implementation. |
| 31 | + |
| 32 | +## NSSortDescriptor Changes |
| 33 | + |
| 34 | +swift-corelibs-foundation now contains an implementation of `NSSortDescriptor` that is partially compatible with its Objective-C counterpart. You may need to alter existing code that makes use of the following: |
| 35 | + |
| 36 | +- Initializers that use string keys or key paths (e.g.: `init(key:…)`) are not available in swift-corelibs-foundation. You should migrate to initializers that take a Swift key path instead (`init(keyPath:…)`). |
| 37 | + |
| 38 | +- Initializers that take or invoke an Objective-C selector are not available in swift-corelibs-foundation. If your class implemented a `compare(_:)` method for use with the `init(keyPath:ascending:)` initializer, you should add a `Swift.Comparable` conformance to it, which will be used in swift-corelibs-foundation in place of the method. The conformance can invoke the method, like so: |
| 39 | + |
| 40 | +```swift |
| 41 | +extension MyCustomClass: Comparable { |
| 42 | + public static func <(_ lhs: MyCustomClass, _ rhs: MyCustomClass) { |
| 43 | + return lhs.compare(rhs) == .orderedAscending |
| 44 | + } |
| 45 | +} |
| 46 | +``` |
| 47 | + |
| 48 | +Note that swift-corelibs-foundation's version of `init(keyPath:ascending:)` is annotated with diagnostics that will cause your code to fail to compile if your custom type isn't `Comparable`; code that uses that constructor with Foundation types that implement a `compare(_:)` method, like `NSString`, `NSNumber`, etc., should still compile and work correctly. |
| 49 | + |
| 50 | +If you were using a selector other than `compare(_:)`, you should migrate to passing a closure to `init(keyPath:ascending:comparator:)` instead. That closure can invoke the desired method. For example: |
| 51 | + |
| 52 | +```swift |
| 53 | +let descriptor = NSSortDescriptor(keyPath: \Person.name, ascending: true, comparator: { (lhs, rhs) in |
| 54 | + return (lhs as! NSString).localizedCompare(rhs as! String) |
| 55 | +}) |
| 56 | +``` |
| 57 | + |
| 58 | + - Archived sort descriptors make use of string keys and key paths, and Swift key paths cannot be serialized outside of Darwin. `NSSortDescriptor` does not conform to `NSSecureCoding` in swift-corelibs-foundation as a result. See the section on `NSCoding` for more information on coding differences in this release. |
| 59 | + |
5 | 60 | ## Improved Scanner API
|
6 | 61 |
|
7 | 62 | The `Scanner` class now has additional API that is more idiomatic for use by Swift code, and doesn't require casting or using by-reference arguments. Several of the new methods have the same name as existing ones, except without the `into:` parameter: `scanInt32()`, `scanString(_:)`, `scanUpToCharacters(from:)`, etc. These invocations will return `nil` if scanning fails, where previous methods would return `false`.
|
|
0 commit comments