Chlebta
Chlebta

Reputation: 3110

Subclass GMSAutocompleteViewController to use it with Eureka

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

Answers (2)

Fun Programmer
Fun Programmer

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

AndrewR
AndrewR

Reputation: 10889

You likely need to call super.init() in AddressFinderViewController's init function to make sure that GMSAutocompleteViewController is initialized properly.

Upvotes: 1

Related Questions