I'm trying to import either GoogleAPIClient or GoogleAPIClientForREST

5.6k views Asked by At

I'm trying to follow Google's tutorial on making their QuickStart app to learn how to make API calls with Swift. I followed the tutorial completely and ended up with this code

import GoogleAPIClient
import GTMOAuth2
import UIKit

class ViewController: UIViewController {

    private let kKeychainItemName = "Drive API"
    private let kClientID = "592019061169-nmjle7sfv8i8eahplae3cvto2rsj4gev.apps.googleusercontent.com"

    // If modifying these scopes, delete your previously saved credentials by
    // resetting the iOS simulator or uninstall the app.
    private let scopes = [kGTLAuthScopeDriveMetadataReadonly]

    private let service = GTLServiceDrive()
    let output = UITextView()

    // When the view loads, create necessary subviews
    // and initialize the Drive API service
    override func viewDidLoad() {
        super.viewDidLoad()

        output.frame = view.bounds
        output.editable = false
        output.contentInset = UIEdgeInsets(top: 20, left: 0, bottom: 20, right: 0)
        output.autoresizingMask = [.FlexibleHeight, .FlexibleWidth]

        view.addSubview(output);

        if let auth = GTMOAuth2ViewControllerTouch.authForGoogleFromKeychainForName(
            kKeychainItemName,
            clientID: kClientID,
            clientSecret: nil) {
            service.authorizer = auth
        }

    }

    // When the view appears, ensure that the Drive API service is authorized
    // and perform API calls
    override func viewDidAppear(animated: Bool) {
        if let authorizer = service.authorizer,
            let canAuth = authorizer.canAuthorize, canAuth {
            fetchFiles()
        } else {
            presentViewController(
                createAuthController(),
                animated: true,
                completion: nil
            )
        }
    }

    // Construct a query to get names and IDs of 10 files using the Google Drive API
    func fetchFiles() {
        output.text = "Getting files..."
        let query = GTLQueryDrive.queryForFilesList()
        query.pageSize = 10
        query.fields = "nextPageToken, files(id, name)"
        service.executeQuery(
            query,
            delegate: self,
            didFinishSelector: "displayResultWithTicket:finishedWithObject:error:"
        )
    }

    // Parse results and display
    func displayResultWithTicket(ticket : GTLServiceTicket,
                                 finishedWithObject response : GTLDriveFileList,
                                 error : NSError?) {

        if let error = error {
            showAlert("Error", message: error.localizedDescription)
            return
        }

        var filesString = ""

        if let files = response.files(), !files.isEmpty {
            filesString += "Files:\n"
            for file in files as! [GTLDriveFile] {
                filesString += "\(file.name) (\(file.identifier))\n"
            }
        } else {
            filesString = "No files found."
        }

        output.text = filesString
    }


    // Creates the auth controller for authorizing access to Drive API
    private func createAuthController() -> GTMOAuth2ViewControllerTouch {
        let scopeString = scopes.joinWithSeparator(" ")
        return GTMOAuth2ViewControllerTouch(
            scope: scopeString,
            clientID: kClientID,
            clientSecret: nil,
            keychainItemName: kKeychainItemName,
            delegate: self,
            finishedSelector: "viewController:finishedWithAuth:error:"
        )
    }

    // Handle completion of the authorization process, and update the Drive API
    // with the new credentials.
    func viewController(vc : UIViewController,
                        finishedWithAuth authResult : GTMOAuth2Authentication, error : NSError?) {

        if let error = error {
            service.authorizer = nil
            showAlert("Authentication Error", message: error.localizedDescription)
            return
        }

        service.authorizer = authResult
        dismissViewControllerAnimated(true, completion: nil)
    }

    // Helper for showing an alert
    func showAlert(title : String, message: String) {
        let alert = UIAlertController(
            title: title,
            message: message,
            preferredStyle: UIAlertControllerStyle.Alert
        )
        let ok = UIAlertAction(
            title: "OK",
            style: UIAlertActionStyle.Default,
            handler: nil
        )
        alert.addAction(ok)
        presentViewController(alert, animated: true, completion: nil)
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

}

My problem is that for

import GoogleAPIClient

I get the error "No such module GoogleAPIClient", which seems weird to me since GTMOAuth2 doesn't get an error, even though it's part of the same Pod I think (I'm new to this, so I'm probably butchering the terminology).

From researching the problem, I found that GoogleAPIClientForREST should be substituted for GoogleAPIClient. This document on GitHub says to just use GoogleAPIClientForREST in the code instead of GoogleAPIClient, but I get the same error with that as well.

Then I thought maybe I could re-install the pods with some changes to Google's tutorial. In the tutorial, it says to execute this code in Terminal

$ cat << EOF > Podfile &&
> platform :ios, '7.0'
> use_frameworks!
> target 'QuickstartApp' do
>     pod 'GoogleAPIClient/Drive', '~> 1.0.2'
>     pod 'GTMOAuth2', '~> 1.1.0'
> end
> EOF
> pod install &&
> open QuickstartApp.xcworkspace

So I thought maybe I could replace GoogleAPIClient for GoogleAPIClientForREST in the terminal code, but that landed me with the same error

enter image description here

As you can see in the screenshot, the framework is there on the left-hand side, but I'm still getting the "No such module" error.

Embedded Binaries and Linked Frameworks

enter image description here

Search Paths

enter image description here

enter image description here

I also found some suggestions here that I tried to follow, but I didn't completely understand the explanation. Nevertheless, I tried, and did this (if I did it wrong please tell me): enter image description here

So I'm trying to get either GoogleAPIClient or GoogleAPIClientForREST to work. Thank you for your help

4

There are 4 answers

12
Hod On

Use this for your Podfile:

platform :ios, '7.0'
use_frameworks!
target 'QuickstartApp' do
    pod 'GoogleAPIClientForREST/Drive', '~> 1.1.1'
    pod 'GTMOAuth2', '~> 1.1.0'
end

Change your import to

import GoogleAPIClientForREST

Then follow the instructions here to migrate the project: Migrating from GoogleAPIClient to GoogleAPIClientForREST

This mostly involves changing GTL calls to GTLR calls with some word swapping. For example, GTLServiceDrive becomes GTLRDriveService.

Regarding framework search paths, this image shows the section you might need to change (note it works for me using the default):

enter image description here

Search paths can be per target, too. Here's an image showing the application target and the framework search paths:

enter image description here

1
rahul verma On

Although the solution towards which I am pointing you might be for other library, but it will help you for sure. https://stackoverflow.com/a/25874524/5032645 . Please try and let me know, if I should simplify it more for you.

10
Bob Wakefield On

First, look at the Pods_QuickstartApp.framework in the Frameworks group of your Quickstart project. If it is still red, as it is on your screenshot, then Xcode didn't build it. If Xcode didn't build the framework, Xcode can't import it for you.

Cocoapods builds a workspace including your app project, plus another project that assembles your individual pod frameworks into a larger framework.

It seems cocoapods built your workspace, and you did open the workspace instead of the project. That's good.

Check the contents of the file named "Podfile". It should match:

platform :ios, '7.0'
use_frameworks!
target 'QuickstartApp' do
    pod 'GoogleAPIClient/Drive', '~> 1.0.2'
    pod 'GTMOAuth2', '~> 1.1.0'
end

If it doesn't, fix it, exit Xcode, delete the .xcodeworkspace file, and then run

pod install

from the console. That may fix your dependencies so that Xcode builds the frameworks.

If you do get it to compile, your problems have just begun. Google has deprecated the OAAuth authorization from an embedded user-agent.

OAAuth authorization from embedded user-agent deprecated

0
jaerodyne On

So I followed the Quickstart tutorial exactly as well and was able to get it working. I moved the GoogleAPIClientForRest in Framework Search Paths above GTMOAuth2:

Screenshot

I ran into an error in the code after successfully including the module and had to change this line to get it to build and run: if (result.files!.count to if (result.files!.count > 0).

Of course now, Google has deprecated GTMOAuth2 and replaced it with GTMAppAuth, which renders this app useless.