Reputation: 3110
I'm trying to subclass GMSAutocompleteViewController
form GooglePlaces
SDK like this :
class AddressFinderViewController: GMSAutocompleteViewController, TypedRowControllerType {
public var row: RowOf<String>!
public var completionCallback : ((UIViewController) -> ())?
convenience public init(_ callback: (UIViewController) -> ()){
self.init(nibName: nil, bundle: nil)
completionCallback = callback
}
override func viewDidLoad() {
super.viewDidLoad()
}
}
Then I use this to call it :
AddressFinderViewController(){ _ in }
}, completionCallback: { vc in
vc.navigationController?.popViewControllerAnimated(true)
}
But I get this error :
2016-09-07 17:21:19.445 PriumCity[77058:3790134] *** Terminating app
due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[__NSArrayM insertObject:atIndex:]: object cannot be nil'
*** First throw call stack:
(
0 CoreFoundation 0x000000010e129d85 __exceptionPreprocess + 165
1 libobjc.A.dylib 0x000000010ede3deb objc_exception_throw + 48
2 CoreFoundation 0x000000010dfeacc5 -[__NSArrayM insertObject:atIndex:] + 901
3 UIKit 0x000000010c863cec -[UIViewController _addChildViewController:performHierarchyCheck:notifyWillMove:] + 541
4 UIKit 0x000000010c885087 -[UIViewController(UIContainerViewControllerProtectedMethods) addChildViewController:] + 83
5 PriumCity 0x000000010ac0bc9c -[GMSAutocompleteViewController viewWillAppear:] + 301
6 UIKit 0x000000010c8652bd -[UIViewController _setViewAppearState:isAnimating:] + 710
7 UIKit 0x000000010c865958 -[UIViewController __viewWillAppear:] + 149
8 UIKit 0x000000010c895750 -[UINavigationController _startCustomTransition:] + 1203
9 UIKit 0x000000010c8a5b9b -[UINavigationController _startDeferredTransitionIfNeeded:] + 712
10 UIKit 0x000000010c8a6d0b -[UINavigationController __viewWillLayoutSubviews] + 57
11 UIKit 0x000000010ca55503 -[UILayoutContainerView layoutSubviews] + 248
12 UIKit 0x000000010c77f980 -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 703
13 QuartzCore 0x000000010c474c00 -[CALayer layoutSublayers] + 146
14 QuartzCore 0x000000010c46908e _ZN2CA5Layer16layout_if_neededEPNS_11TransactionE + 366
15 QuartzCore 0x000000010c468f0c _ZN2CA5Layer28layout_and_display_if_neededEPNS_11TransactionE + 24
16 QuartzCore 0x000000010c45d3c9 _ZN2CA7Context18commit_transactionEPNS_11TransactionE + 277
17 QuartzCore 0x000000010c48b086 _ZN2CA11Transaction6commitEv + 486
18 UIKit 0x000000010c6f119b _afterCACommitHandler + 174
19 CoreFoundation 0x000000010e04ec37 __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 23
20 CoreFoundation 0x000000010e04eba7 __CFRunLoopDoObservers + 391
21 CoreFoundation 0x000000010e0447fb __CFRunLoopRun + 1147
22 CoreFoundation 0x000000010e0440f8 CFRunLoopRunSpecific + 488
23 GraphicsServices 0x00000001139c0ad2 GSEventRunModal + 161
24 UIKit 0x000000010c6c4f09 UIApplicationMain + 171
25 PriumCity 0x000000010aa99482 main + 114
26 libdyld.dylib 0x000000010f8b292d start + 1
27 ??? 0x0000000000000001 0x0 + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb)
Upvotes: 1
Views: 317
Reputation: 1082
It appears that for some reason, you can't create a custom init for Google's GMSAutocompleteViewController. If you try to create a custom init, then it may present your subclasses view controller, but it will just be a black view controller.
Here is what I did:
My GMSAutocompleteViewController subclass:
import UIKit
import GooglePlaces
class AddressSearchViewController: GMSAutocompleteViewController {
var state: RiderFormRow.Kind = .pickUp
override func viewDidLoad() {
super.viewDidLoad()
setSearchBounds()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private func setSearchBounds() {
//Bloomington, IN coordinates
let northEastCorner = CLLocationCoordinate2D(latitude: 39.20512, longitude: -86.435595)
let southwestCorner = CLLocationCoordinate2D(latitude: 39.09969, longitude: -86.641937)
autocompleteBounds = GMSCoordinateBounds(coordinate: northEastCorner, coordinate: southwestCorner)
autocompleteBoundsMode = .restrict
}
}
Then, this is how I present my subclassed view controller:
let autocompleteController = AddressSearchViewController()
autocompleteController.state = row.type
autocompleteController.delegate = self
present(autocompleteController, animated: true, completion: nil)
So, if you need to pass in any special variables into this subclassed variable, you have to do it after init. It's not a perfect solution because it would be nice to be able to have a custom init, but unfortunately the GMSAutocompeleteViewController needs to call the init(nibName, bundle) in order to work properly. This is probably because Google's framework is using a storyboard for the GMSAutocompeleteViewController. You can not even place logic in the init function of the subclass. It has to go in ViewDidLoad or else the logic gets overrided later in the view controller's life cycle. Anyway, this is the best workaround I could find that worked for me. Part of me wonders if Google actually doesn't want you to mess with the Address controller because it seems like they would have thought about this.
Upvotes: 0
Reputation: 10889
You likely need to call super.init()
in AddressFinderViewController
's init function to make sure that GMSAutocompleteViewController
is initialized properly.
Upvotes: 1