- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试使用 Swift 和 Google Sheets API 创建适用于 iOS 的库存管理应用。在开始之前,我想熟悉 API 并确保一切正常工作。为此,我想创建一个函数 getCell,它返回硬编码行和列处的单元格内容(根据需要以 A1 表示法给出)。由于 Swift 中的 Sheets API 实现似乎需要回调模型(一般来说,我是回调和异步编程的初学者),我还没有弄清楚如何在查询完成后在我的函数中返回单元格的内容.
我已按照 Google ( https://developers.google.com/sheets/quickstart/ios?ver=swift&hl=zh-cn ) 提供的 Sheets API iOS 快速入门在开发者控制台中启用 API 并安装必要的 Cocoapods(我的 Podfile 安装“GoogleAPIClientForREST/Sheets”和“GoogleSignIn”)。在将某些部分转换为较新的 Swift 语法后,我得到了包含的代码,可以正常运行和工作。
当我在 ViewController.swift 文件中编写 getCell 函数时,出现了问题。从下面的代码中可以看出,我假设查询将在 getCellQuery 完成时完成,以便 getCell 将能够访问由回调函数 (displayResultWithTicket) 更新的全局变量。然而,我放入的调试打印语句显示回调函数仅在程序末尾执行,在 getCell 检查全局变量并没有发现任何新内容之后。请注意,电子表格 ID 需要替换为真实 ID 才能运行此代码。
import GoogleAPIClientForREST
import GoogleSignIn
import UIKit
struct MyVariables {
static var currentCell: String? = nil
}
class ViewController: UIViewController, GIDSignInDelegate, GIDSignInUIDelegate {
private let scopes = [kGTLRAuthScopeSheetsSpreadsheets]
private let service = GTLRSheetsService()
@IBOutlet weak var signInButton: GIDSignInButton!
override func viewDidLoad() {
super.viewDidLoad()
GIDSignIn.sharedInstance().delegate = self
GIDSignIn.sharedInstance().uiDelegate = self
GIDSignIn.sharedInstance().scopes = scopes
}
func sign(_ signIn: GIDSignIn!, didSignInFor user: GIDGoogleUser!, withError error: Error!) {
if let error = error {
print("\(error.localizedDescription)")
self.service.authorizer = nil
} else {
self.signInButton.isHidden = true
self.service.authorizer = user.authentication.fetcherAuthorizer()
//main program starts here
print("Cell: " + getCell(a1: "Inventory!A1"))
}
}
func getCell(a1: String) -> String {
print("Started getCell")
getCellQuery(a1: a1)
if MyVariables.currentCell != nil {
print("Finished getCell")
return MyVariables.currentCell!
} else {
print("Error: the global variable is nil and probably hasn't been changed")
print("Finished getCell")
return ""
}
}
func getCellQuery(a1: String) {
print("Started getCellQuery")
let spreadsheetId = "INSERT ID HERE"
// arbitrary row and column in A1 notation
let getRange = a1
let getQuery = GTLRSheetsQuery_SpreadsheetsValuesGet.query(withSpreadsheetId: spreadsheetId, range:getRange)
service.executeQuery(getQuery, delegate: self, didFinish: #selector(displayResultWithTicket(ticket:finishedWithObject:error:)))
print("Finished getCellQuery")
}
@objc func displayResultWithTicket(ticket: GTLRServiceTicket,
finishedWithObject result : GTLRSheets_ValueRange,
error : NSError?) {
print("Started callback")
if let error = error {
print("\(error.localizedDescription)")
return
}
// turn 2d array into string
let rows = result.values!
for row in rows {
for item in row {
// update global variable
MyVariables.currentCell = item as? String
}
}
print("Finished callback")
}
}
登录后,我希望控制台中出现以下内容:
Started getCell
Started getCellQuery
Started callback
Finished callback
Finished getCellQuery
Finished getCell
Cell: <Whatever the cell has>
相反,我得到了这个:
Started getCell
Started getCellQuery
Finished getCellQuery
Error: the cell value is nil and probably hasn't been changed
Finished getCell
Cell:
Started callback
Finished callback
另外,我也尝试过使用 while 循环来等待全局变量更新,但 Swift 似乎始终选择在整个程序结束时调用回调函数,这很烦人。
如果有一种不太笨重的方法来完成这个简单的任务,我们很高兴知道。
最佳答案
您的问题似乎与异步调用模式有关。当您调用 service.executeQuery 时,它将开始异步查询,但由于它正在访问 Web 服务,因此该查询可能需要很长时间才能完成。 executeQuery 函数立即返回,查询本身可能已由其库排队。在下一次机会,请求被发送,当回复返回时,您的 displayResultWithTicket(ticket:finishedWithObject:error:) 回调被调用,但与此同时,您的 getCellQuery 函数的其余部分已完成,就像 getCell 一样。
更好的模式是解雇一些 notification现在您已经有了响应(并传递您在通知中返回的值),然后让该通知的监听器获取响应并对结果执行适当的操作。
或者,sheets API 中可能有一种方法可以传入 closure这很像回调,但它的代码位于传递它的函数中,因此状态管理更容易一些。我不熟悉该 API,因此不确定它是否存在。
这是一篇关于 managing async code 的文章在 Swift 中涵盖了一些选项。它有点旧,但涵盖了基础知识。
关于ios - 如何在执行完成后返回 "GTLRSheetsQuery_SpreadsheetsValuesGet"查询的结果(使用 Sheets API 的 Swift)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57065972/
我有一个“有趣”的问题,即以两种不同的方式运行 wine 会导致: $> wine --version /Applications/Wine.app/Contents/Resources/bin/wi
我制作了这个网络抓取工具来获取网页中的表格。我使用 puppeteer (不知道 crontab 有问题)、Python 进行清理并处理数据库的输出 但令我惊讶的是,当我执行它时 */50 * * *
JavaScript 是否被调用或执行取决于什么?准确地说,我有两个函数,它们都以相同的方式调用: [self.mapView stringByEvaluatingJavaScriptFromStri
我目前正在使用 python 做一个机器学习项目(这里是初学者,从头开始学习一切)。 只是想知道 statsmodels 的 OLS 和 scikit 的 PooledOlS 使用我拥有的相同面板数据
在使用集成对象模型 (IOM) 后,我可以执行 SAS 代码并将 SAS 数据集读入 .Net/C# 数据集 here . 只是好奇,使用 .Net 作为 SAS 服务器的客户端与使用 Enterpr
有一些直接的 jQuery 在单击时隐藏打开的 div 未显示,但仍将高度添加到导航中以使其看起来好像要掉下来了。 这个脚本工作正常: $(document).ready(funct
这个问题已经有答案了: How do I compare strings in Java? (23 个回答) 已关闭 4 年前。 这里是 Java 新手,我正在使用 NetBeans 尝试一些简单的代
如果我将它切换到 Python 2.x,它执行 10。这是为什么? 训练逻辑回归模型 import keras.backend as
我有两个脚本,它们包含在 HTML 正文中。在第一个脚本中,我初始化一个 JS 对象,该对象在第二个脚本标记中引用。 ... obj.a = 1000; obj.
每当我运行该方法时,我都会收到一个带有数字的错误 以下是我的代码。 public String getAccount() { String s = "Listing the accounts";
我已经用 do~while(true) 创建了我的菜单;但是每次用户输入一个数字时,它不会运行程序,而是再次显示菜单!你怎么看? //我的主要方法 public static void main(St
执行命令后,如何让IPython通知我?我可以使用铃声/警报还是通过弹出窗口获取它?我正在OS X 10.8.5的iTerm上运行Anaconda。 最佳答案 使用最新版本的iTerm,您可以在she
您好,我刚刚使用菜单栏为 Swing 编写了代码。但是问题出现在运行中。我输入: javac Menu.java java Menu 它没有给出任何错误,但 GUI 没有显示。这是我的源代码以供引用:
我觉得这里缺少明显的东西,但是我看不到它写在任何地方。 我使用Authenticode证书对可执行文件进行签名,但是当我开始学习有关它的更多信息时,我对原样的值(value)提出了质疑。 签名的exe
我正在设计一个应用程序,它使用 DataTables 中的预定义库来创建数据表。我想对数据表执行删除操作,为此应在按钮单击事件上执行 java 脚本。 $(document).ready(functi
我是 Haskell 新手,如果有人愿意帮助我,我会很高兴!我试图让这个程序与 do while 循环一起工作。 第二个 getLine 命令的结果被放入变量 goGlenn 中,如果 goGlenn
我有一个用 swing 实现迷你游戏的程序,在主类中我有一个循环,用于监听游戏 map 中的 boolean 值。使用 while 实现的循环不会执行一条指令,如果它是唯一的一条指令,我不知道为什么。
我正在尝试开发一个连接到 Oracle 数据库并执行函数的 Java 应用程序。如果我在 Eclipse 中运行该应用程序,它可以工作,但是当我尝试在 Windows 命令提示符中运行 .jar 时,
我正在阅读有关 Java 中的 Future 和 javascript 中的 Promises 的内容。下面是我作为示例编写的代码。我的问题是分配给 future 的任务什么时候开始执行? 当如下行创
我有一个常见的情况,您有两个变量(xSpeed 和 ySpeed),当它们低于 minSpeed 时,我想将它们独立设置为零,并在它们都为零时退出。 最有效的方法是什么?目前我有两种方法(方法2更干净
我是一名优秀的程序员,十分优秀!