I have a subclass of NSArray, array of labels:
@interface LabelArray : NSArray
- (UILabel*)objectAtIndex:(NSUInteger)index;
- (UILabel*)objectAtIndexedSubscript:(NSUInteger)index;
@end
@interface ViewController : UIViewController
@property (nonatomic,readonly) LabelArray* labels;
@end
When I try to access it from Swift code with 0 index, everything goes fine:
someObject!.labels[0].textColor = UIColor.redColor()
But when I use an Index variable
var Index: Int = 0
someObject!.labels[Index].textColor = UIColor.redColor()
xcode gives an error: "Could not find member 'textColor'" and forces me to use an ugly code like this:
(someObject!.labels[Index] as! UILabel).textColor = UIColor.redColor()
I'm subclassing the array to be able to modify a group of labels at once, like labels.textColor = UIColor.redColor()
will modify each label in array.
What am I doing wrong, and is there a way to avoid this ugly cast?
Well, I found an answer.
The problem is in Swift strong typing system.
The argument type in overridden
objectAtIndex:
is Unsigned Integer, andIndex
in the caller procedure was declared as Integer. That's why compiler was considering that Swift Array'sobjectAtIndex:
procedure withInt
argument, returning the AnyObject type, was used.Bridged declaration looks like this:
func objectAtIndex(index: Int) -> AnyObject
The solution is to redeclare
objectAtIndexedSubscript:
with(NSInteger)index
instead ofNSUInteger
OR to use
UInt()
conversion:someObject!.labels[UInt(Index)].textColor = ...
We can also overload the
subscript
property (overload the square brackets operator), but we cannot directly extend the LabelArray, becausesubscript
will conflict with obj-cobjectAtIndexedSubscript
method.Instead, we can declare a protocol, extend it with a new method, and then extend the LabelArray with this protocol: