Objective
On NSArray
and NSMutableArray
, add a custom subscript that duplicates the [safe:]
subscript that OTCore already implements on standard Swift collections.
Interface
extension NSArray {
open subscript(safe index: Int) -> Any? { get }
}
extension NSMutableArray {
open subscript(safe index: Int) -> Any? { get set }
}
Implementation
- The implementation checks that the passed
index
is safe (it is not out-of-bounds).
- If the index is valid, then the element at that index is returned.
- If the index is not valid, then
nil
is returned.
Problem
I could not find a way to make the compiler happy when both subscripts use the same label "safe:
". The nature of Objective-C objects is making this elusive to figure out.
The following implementation does function as expected (with unique subscript labels) but the goal is to use the same labels.
extension NSArray {
open subscript(safe index: Int) -> Any? {
(0..<count).contains(index) ? self[index] : nil
}
}
extension NSMutableArray {
open subscript(safeMutable index: Int) -> Any? {
get {
(0..<count).contains(index) ? self[index] : nil
}
set {
guard (0..<count).contains(index) else { return }
self[index] = newValue!
}
}
}
As soon as you make the subscript labels the same, it will not compile.
extension NSArray {
open subscript(safe index: Int) -> Any? { get }
}
extension NSMutableArray {
// Compiler Error: "Overriding non-@objc declarations from extensions is not supported"
open subscript(safe index: Int) -> Any? { get set }
}
However, making both subscripts @objc
and having the NSMutableArray
declared override
will allow the code to compile, but the functions are never actually executed when the subscript is called. Instead, the underlying subscript executes (which of course produces EXC_BAD_INSTRUCTION
when an index
is out-of-bounds since that is default behavior of NSArray
and NSMutableArray
.
extension NSArray {
@objc open subscript(safe index: Int) -> Any? { get }
}
extension NSMutableArray {
@objc open override subscript(safe index: Int) -> Any? { get set }
}
Next Steps
I believe the goal of implementing this with identical subscript labels [safe:]
for both NSArray
and NSMutableArray
is possible, but it will require more research and assistance.