谷歌电子表格 APIS,困惑

时间:2021-05-08 22:25:46

标签: swift xcode google-sheets-api

我以前有过这个工作,但现在它似乎已经停止了。我正在尝试运行各种 googlesheets APIS,例如读/写/创建。我已经安装了合适的可可豆荚:

platform :ios, '10.0'

target 'Safety_App-Prototype' do
  
  use_frameworks!

    pod 'GoogleAnalytics'
    pod 'GoogleAPIClientForREST/Sheets'
    pod 'GoogleAPIClientForREST/Drive'
    pod 'GoogleSignIn'
    pod 'SVProgressHUD'
    pod 'Firebase/Core'
    pod 'Firebase/Analytics'
    pod 'Firebase/Auth'
    pod 'Firebase/Firestore'
end

我创建了一个谷歌开发者控制台项目并将所有相关信息包含到我的应用程序中。 (这包括项目下的 URL 类型 -> 信息选项卡以及我的应用程序委托,如下所示:

//
//  AppDelegate.swift
//  Created by Michael Szabo on 2021-01-28.
//

import UIKit
import GoogleSignIn

@main
class AppDelegate: UIResponder, UIApplicationDelegate, GIDSignInDelegate {



    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.
        GIDSignIn.sharedInstance().clientID = "FORMYEYESONLY.apps.googleusercontent.com"
        GIDSignIn.sharedInstance().delegate = self
        return true
    }
    
    func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
   
        
        return GIDSignIn.sharedInstance().handle(url as URL?,
                                                 sourceApplication: options[UIApplication.OpenURLOptionsKey.sourceApplication] as? String,
                                                 annotation: options[UIApplication.OpenURLOptionsKey.annotation])

    
    }

    func sign(_ signIn: GIDSignIn!, didSignInFor user: GIDGoogleUser!, withError error: Error!) {
        if let error = error {
          if (error as NSError).code == GIDSignInErrorCode.hasNoAuthInKeychain.rawValue {
            print("The user has not signed in before or they have since signed out.")
          } else {
            print("\(error.localizedDescription)")
          }
          return
        }
        // Perform any operations on signed in user here.
        let userId = user.userID                  // For client-side use only!
        let idToken = user.authentication.idToken // Safe to send to the server
        let fullName = user.profile.name
        let givenName = user.profile.givenName
        let familyName = user.profile.familyName
        let email = user.profile.email
        // ...
        print(fullName)
    }
    
    func sign(_ signIn: GIDSignIn!, didDisconnectWith user: GIDGoogleUser!, withError error: Error!) {
       // Perform any operations when the user disconnects from app here.
        print("User has disconnected")
    }
    
    // MARK: UISceneSession Lifecycle

    func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
        // Called when a new scene session is being created.
        // Use this method to select a configuration to create the new scene with.
        return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
    }

    func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
        // Called when the user discards a scene session.
        // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
        // Use this method to release any resources that were specific to the discarded scenes, as they will not return.
    }


}

我添加了一个谷歌签名按钮,它允许我登录并请求读取/写入工作表的权限,并在我的脚本中添加了创建/读取/写入工作表的功能,如下所示:


//  Created by Michael Szabo on 2021-02-21.
//


import GoogleAPIClientForREST
import GoogleSignIn
import UIKit

class JHA_pg1: UIViewController, UINavigationControllerDelegate, UIImagePickerControllerDelegate, UITextFieldDelegate, GIDSignInUIDelegate, GIDSignInDelegate {
    

    var rowstart:NSNumber = 0
    var rowend:NSNumber = 0
    var columnstart:NSNumber = 0
    var columnend:NSNumber = 0
    var red:NSNumber = 1
    var blue:NSNumber = 1
    var green:NSNumber = 1

    var range1 = ""
    var text1 = ""
    var text2 = ""
    var text3 = ""
    var bordertype = "SOLID"
    var borderthick:NSNumber = 3
    var inbortype = "NONE"
    var inborthick:NSNumber = 0
        
    var spreadsheetId = ""
    
   
    @IBOutlet weak var BeginAssessment: UIButton! //SubmitButton
 
    let today = Date()
    let formatter1 = DateFormatter()
    let formatter = DateFormatter()
    var date = String()
    var buttontitle = String()
        
    let defaults = UserDefaults.standard
        
        
    private let scopes = [kGTLRAuthScopeSheetsSpreadsheets]
    private let service = GTLRSheetsService()
   

    
//=========================================================================================================
//=========================================================================================================

    
    
    override func viewDidLoad() {
        super.viewDidLoad()

        
        
//=========================================================================================================
// Configure Google Sign-in.

        GIDSignIn.sharedInstance().delegate = self
        GIDSignIn.sharedInstance().uiDelegate = self
        GIDSignIn.sharedInstance().scopes = scopes
        GIDSignIn.sharedInstance().signInSilently()

        
    }
    
    
//=========================================================================================================
//=========================================================================================================
    //Submit Function

    @IBAction func BeginAssessment(_ sender: Any) {
   
        
        if(GIDSignIn.sharedInstance()?.currentUser != nil)
        {
        print("loggedIn")
        }
        else
        {
        print("not loggedIn")
        }
        

        
        spreadsheetId = "SOME ID"
        rowstart = 0
        rowend = 5
        columnstart = 0
        columnend = 7
  
        unmergecell()
        
  

        CreateSpreadSheet()
        
        print(spreadsheetId)
        
     
 
    }
        

    //========================================================================================================
    //Write To Sheet Function
        
        func write() {
            let range = range1
            let updateValues = [[text1,text2,text3]]
            let valueRange = GTLRSheets_ValueRange() // GTLRSheets_ValueRange holds the updated values and other params
            valueRange.majorDimension = "ROWS" // Indicates horizontal row insert
            valueRange.range = range
            valueRange.values = updateValues
            let query = GTLRSheetsQuery_SpreadsheetsValuesAppend.query(withObject: valueRange, spreadsheetId: spreadsheetId, range: range)
            query.valueInputOption = "USER_ENTERED"
            
            service.executeQuery(query) { ticket, object, error in}
        }
      
   
    //========================================================================================================
    //Unmerge Cell Function

            func unmergecell() {
                
                let request = GTLRSheets_Request.init()

                let test = GTLRSheets_GridRange.init()
                    
                test.startRowIndex = rowstart
                test.endRowIndex = rowend
                test.startColumnIndex = columnstart
                test.endColumnIndex = columnend

                request.unmergeCells = GTLRSheets_UnmergeCellsRequest.init()
                request.unmergeCells?.range = test

                

                let batchUpdate = GTLRSheets_BatchUpdateSpreadsheetRequest.init()
                
                batchUpdate.requests = [request]
               
            
                let createQuery = GTLRSheetsQuery_SpreadsheetsBatchUpdate.query(withObject: batchUpdate, spreadsheetId: spreadsheetId)
              
                
            service.executeQuery(createQuery) { (ticket, result, NSError) in
                   
                   }
                  }
        

                       }
        
    //========================================================================================================
    //Create Spreadsheet Function

        
        func CreateSpreadSheet()
        {
            
            print("==============================================")
            print("Createsheet Function")
            
            let newSheet = GTLRSheets_Spreadsheet.init()
            let properties = GTLRSheets_SpreadsheetProperties.init()

            properties.title = "Daily JHA Form - "+date
            newSheet.properties = properties
            
            let query = GTLRSheetsQuery_SpreadsheetsCreate.query(withObject:newSheet)
            query.fields = "spreadsheetId"

            query.completionBlock = { (ticket, result, NSError) in

                if let error = NSError {
                    print("error!!!!!!!!!!!!!!!!!!!!!!!!!!")
                    print(error)
                }
                else {
                    let response = result as! GTLRSheets_Spreadsheet
                    let identifier = response.spreadsheetId
                    self.spreadsheetId = identifier!
                    GlobalVariable1.sheetID = self.spreadsheetId
                    print(self.spreadsheetId)
                }
            }
            service.executeQuery(query, completionHandler: nil)
        
        }


 
  //=========================================================================================================
    
    func sign(_ signIn: GIDSignIn!, didSignInFor user: GIDGoogleUser!, withError error: Error!) {
        if let error = error {
          if (error as NSError).code == GIDSignInErrorCode.hasNoAuthInKeychain.rawValue {
            print("The user has not signed in before or they have since signed out.")
          } else {
            print("\(error.localizedDescription)")
          }
          return
        }
        // Perform any operations on signed in user here.
        let userId = user.userID                  // For client-side use only!
        let idToken = user.authentication.idToken // Safe to send to the server
        let fullName = user.profile.name
        let givenName = user.profile.givenName
        let familyName = user.profile.familyName
        let email = user.profile.email
        // ...
        print(fullName)
    }
    
    
    //=========================================================================================================
    // Display (in the UITextView) the names and majors of students in a sample
    // spreadsheet:
    //https://docs.google.com/spreadsheets/d/e/2PACX-1vTxKKu-0BwyOPq9HTYH237jGlMrf3q8kLwe5R2eH2dbkGqNbk3D7L9_MKxpO4b3g9cy09w2davohJzq/pubhtml
            
            func listMajors() {

        let range = "A1:Q"
        let query = GTLRSheetsQuery_SpreadsheetsValuesGet
                    .query(withSpreadsheetId: spreadsheetId, range:range)
                service.executeQuery(query) { (ticket, result, error) in
        if let error = error {
        self.showAlert(title: "Error", message: error.localizedDescription)
        return
                    }
        guard let result = result as? GTLRSheets_ValueRange else {
        return
                    }
        let rows = result.values!
        if rows.isEmpty {
    //    self.output.text = "No data found."
        return
                    }
    //    self.output.text = "Number of rows in sheet: \(rows.count)"
                }
            }
            

    // Process the response and display output
        func displayResultWithTicket(ticket: GTLRServiceTicket,
    finishedWithObject result : GTLRSheets_ValueRange,
    error : NSError?) {
    if let error = error {
    showAlert(title: "Error", message: error.localizedDescription)
    return
            }
    var majorsString = ""
    let rows = result.values!
    if rows.isEmpty {
    //           output.text = "No data found."
    return
            }
            majorsString += "Name, Major:\n"
    for row in rows {
    let name = row[0]
    let major = row[4]
                majorsString += "\(name), \(major)\n"
            }
    //        output.text = majorsString
        }
        
        
        
    // Helper for showing an alert
        func showAlert(title : String, message: String) {
    let alert = UIAlertController(
    title: title,
    message: message,
    preferredStyle: UIAlertController.Style.alert
            )
    let ok = UIAlertAction(
    title: "OK",
    style: UIAlertAction.Style.default,
    handler: nil
            )
            alert.addAction(ok)
    present(alert, animated: true, completion: nil)
        }


}


struct GlobalVariable1
{
    static var sheetID = ""
}


extension UIViewController {
    func hideKeyboardWhenTappedAround() {
        let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(UIViewController.dismissKeyboard))
        tap.cancelsTouchesInView = false
        view.addGestureRecognizer(tap)
    }

    @objc func dismissKeyboard() {
        view.endEditing(true)
    }

}


但是我收到以下错误:

<块引用>

可选(错误域=com.google.GTLRErrorObjectDomain 代码=401“请求缺少必需的身份验证凭据。需要 OAuth 2 访问令牌、登录 cookie 或其他有效的身份验证凭据。请参阅 https://developers.google.com/identity/sign-in/web/devconsole-project." UserInfo={GTLRStructuredError=GTLRErrorObject 0x600001182310:{错误:[1] 消息:“请求缺少必需的身份验证凭据。需要 OAuth 2 访问令牌、登录 cookie 或其他有效的身份验证凭据。请参阅 https://developers.google.com/identity/sign-in/web/devconsole-project." 代码:401 状态:“UNAUTHENTICATED”},NSLocalizedDescription=请求缺少必需的身份验证凭据。需要 OAuth 2 访问令牌、登录 cookie 或其他有效的身份验证凭据。请参阅 https://developers.google.com/identity/sign-in/web/devconsole-project.})"

我做错了什么?

2 个答案:

答案 0 :(得分:2)

看看您的代码产生的错误,以及您尝试要求的范围,它们似乎还不够。确实,您只设置了:

private let scopes = [kGTLRAuthScopeSheetsSpreadsheets]

根据此 google official doc about scopes,您可以找到有关所有范围的更多详细信息。 在代码的中间部分,您可以阅读个人资料信息,并且可以通过添加有关 google sign in 的范围来阅读这些信息:

  • 个人资料
  • 电子邮件

答案 1 :(得分:1)

似乎我在调用的函数中遗漏了一条指令。我还必须为较新的 pod 文件“pod 'GoogleSignIn', '~> 5.0.2'”更新一些代码。可以在此处找到有关此迁移的说明:

https://developers.google.com/identity/sign-in/ios/quick-migration-guide

我需要添加到我的函数中的代码部分是一个简单的行,可以在这里看到:

service.authorizer = GIDSignIn.sharedInstance().currentUser.authentication.fetcherAuthorizer()

我希望这能帮助其他人(传递出去。)

谢谢。