In my first attempt I tried the following code: (which would work great in Java)
// Pass the callback to the new delegate, as well as the list of arrays. var delegate=PickerProvider(selectedCall:returnValue ,arrays:numDice,dieTypes,modRolls,modifiers); // Set the picker view to use the subclass as both a delgate and dataSource. pickerView.dataSource=delegate; pickerView.delegate=delegate;
When I did this, I would end up with a very obscure error:
014-06-15 21:16:11.737 SimpleDieRoller[11717:13412066] -[CALayerArray numberOfComponentsInPickerView:]: unrecognized selector sent to instance 0x10bf05330 2014-06-15 21:16:11.742 SimpleDieRoller[11717:13412066] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[CALayerArray numberOfComponentsInPickerView:]: unrecognized selector sent to instance 0x10bf05330' *** First throw call stack: ( 0 CoreFoundation 0x000000010046ee35 __exceptionPreprocess + 165 1 libobjc.A.dylib 0x0000000101f1a9a0 objc_exception_throw + 45 2 CoreFoundation 0x00000001004751cd -[NSObject(NSObject) doesNotRecognizeSelector:] + 205 3 CoreFoundation 0x00000001003cf89c ___forwarding___ + 988 4 CoreFoundation 0x00000001003cf438 _CF_forwarding_prep_0 + 120 5 UIKit 0x0000000100cd8398 -[UIPickerView _updateSelectedRows] + 69 6 UIKit 0x0000000100cd84ce -[UIPickerView didMoveToWindow] + 78 7 UIKit 0x0000000100d57052 -[UIView(Internal) _didMoveFromWindow:toWindow:] + 1496 8 UIKit 0x0000000100d56d41 -[UIView(Internal) _didMoveFromWindow:toWindow:] + 711 9 UIKit 0x0000000100d4f8e5 __45-[UIView(Hierarchy) _postMovedFromSuperview:]_block_invoke + 128 10 UIKit 0x0000000100d4f856 -[UIView(Hierarchy) _postMovedFromSuperview:] + 437 11 UIKit 0x0000000100d5968e -[UIView(Internal) _addSubview:positioned:relativeTo:] + 1610 12 UIKit 0x0000000100d29c3f -[UIWindow addRootViewControllerViewIfPossible] + 452 13 UIKit 0x0000000100d29e22 -[UIWindow _setHidden:forced:] + 276 14 UIKit 0x0000000100d369ad -[UIWindow makeKeyAndVisible] + 42 15 UIKit 0x0000000100ce4db9 -[UIApplication _callInitializationDelegatesForMainScene:transitionContext:] + 2753 16 UIKit 0x0000000100ce7529 -[UIApplication _runWithMainScene:transitionContext:completion:] + 1222 17 UIKit 0x0000000100ce6510 -[UIApplication workspaceDidEndTransaction:] + 19 18 CoreFoundation 0x00000001003a5bbc __CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK__ + 12 19 CoreFoundation 0x000000010039b095 __CFRunLoopDoBlocks + 341 20 CoreFoundation 0x000000010039a84c __CFRunLoopRun + 844 21 CoreFoundation 0x000000010039a296 CFRunLoopRunSpecific + 470 22 UIKit 0x0000000100ce5f26 -[UIApplication _run] + 413 23 UIKit 0x0000000100ce9308 UIApplicationMain + 2994 24 SimpleDieRoller 0x0000000100006c3d top_level_code + 77 25 SimpleDieRoller 0x0000000100006c7a main + 42 26 libdyld.dylib 0x0000000102478145 start + 1 ) libc++abi.dylib: terminating with uncaught exception of type NSException
It was not obvious from this what was happening. What was really happening is that the 'var delegate' local variable was being allocated and given a count of 1. It was then assigned to
'delegate' and datasource' of the picker.
However those properties are declared:
var dataSource: UIPickerViewDataSource! // default is nil. weak reference
var delegate: UIPickerViewDelegate! // default is nil. weak reference
The fact that they were weak references, means that when the initializer left scope, the count was decremented, the variable was no longer valid, so the picker called an invalid reference.
This was an easy fix, I just made a member variable that held my picker source, however the error was so obscure it took a while to find it out.