I’ve just come across some code in Three20 that looks like this:
SEL sel = @selector(textField:didAddCellAtIndex:);
if ([self.delegate respondsToSelector:sel]) {
[self.delegate performSelector:sel withObject:self withObject:(id)_cellViews.count-1];
}
On LLVM 2.0, this causes the compilation error:
error: arithmetic on pointer to interface ‘id’, which is not a constant size in non-fragile ABI
I know why that error is occurring and I know how to fix it. I just need to invoke the method directly, like so:
SEL sel = @selector(textField:didAddCellAtIndex:);
if ([self.delegate respondsToSelector:sel]) {
[self.delegate textField:self didAddCellAtIndex:(_cellViews.count - 1)];
}
My question is, if you know both the selector and its arguments at compile time, why would you need to use performSelector:withObject:withObject: at runtime? I don’t see why the code was written this way in the first place. If the selector and arguments were dynamically passed into the method, I may understand, but they’re not, the selector and its arguments are hard coded, (even if the index does change during run time, its method of obtaining the index is hard coded.)
If someone could explain to me a good reason why this would be necessary, I’d be grateful. Otherwise, I’ll be over here changing all this code.
After a little more digging, it looks like the
TTPickerTextFieldclass that this code is found in is an indirect subclass of aUITextField.As such, it is piggy-backing on
UITextFields delegate property, which doesn’t conform to theTTPickerTextFieldDelegateprotocol where the methodtextField:didAddCellAtIndex:is declared.I have come to the conclusion that this code is just laziness. No reason why the
UITextFields delegate property had to be piggy-backed, making this confusing, error prone code necessary.My own approach would have been to leave
UITextFields delegate property alone, and add my own property in my specific subclass that handled the specific delegate methods.Just to clarify – the ‘solution’ I mentioned in the question fixes the compiler error, but generates a warning that the method can’t be found and will be assumed to return id. This is what the original code was ‘solving’ but that only worked in GCC. No longer with LLVM 2.0.
Last edit, I promise:
My final solution to combat this laziness and get rid of the warning and error is an ugly hack:
Cast
UITextFields delegate to anidthat conforms toTTPickerTextFieldDelegateand then invoke the method directly.Please don’t be lazy 🙁