我想创建一个应用程序,其中某些类型的数据将同步到应用程序特定文件夹中的谷歌驱动器,并且可以访问它来检索数据并填充到应用程序。如果用户手机以某种方式丢失并且用户使用另一部手机并且当用户登录同一个谷歌帐户时则应该获取该数据。
我的问题是我不知道执行此操作的步骤,我能够通过谷歌驱动器创建应用程序文件夹,这通过驱动器向最终用户显示
现在,当我尝试向其中插入数据时出现范围错误。 我使用的代码是:
import Foundation
import GoogleAPIClientForREST
enum GDriveError: Error {
case NoDataAtPath
}
class ATGoogleDrive {
private let service: GTLRDriveService
init(_ service: GTLRDriveService) {
self.service = service
}
public func listFilesInFolder(_ folder: String, onCompleted: @escaping (GTLRDrive_FileList?, Error?) -> ()) {
search(folder) { (folderID, error) in
guard let ID = folderID else {
onCompleted(nil, error)
return
}
self.listFiles(ID, onCompleted: onCompleted)
}
}
private func listFiles(_ folderID: String, onCompleted: @escaping (GTLRDrive_FileList?, Error?) -> ()) {
let query = GTLRDriveQuery_FilesList.query()
query.pageSize = 100
query.q = "'\(folderID)' in parents"
service.executeQuery(query) { (ticket, result, error) in
onCompleted(result as? GTLRDrive_FileList, error)
}
}
public func uploadFile(_ folderName: String, data: Data, MIMEType: String, onCompleted: ((String?, Error?) -> ())?) {
search("config.json") { (folderID, error) in
if let ID = folderID {
self.upload(ID, data: data, MIMEType: MIMEType, onCompleted: onCompleted)
} else {
self.createFolder(folderName, onCompleted: { (folderID, error) in
self.upload("", data: data, MIMEType: MIMEType, onCompleted: onCompleted)
})
}
}
}
private func upload(_ parentID: String, data: Data, MIMEType: String, onCompleted: ((String?, Error?) -> ())?) {
let metadata: GTLRDrive_File = GTLRDrive_File()
metadata.name = "config.json"
metadata.parents = ["appDataFolder"]
let uploadParameters: GTLRUploadParameters = GTLRUploadParameters(data: data, mimeType: "application/json")
uploadParameters.shouldUploadWithSingleRequest = true;
let query: GTLRDriveQuery_FilesCreate = GTLRDriveQuery_FilesCreate.query(withObject: metadata, uploadParameters: uploadParameters)//[GTLRDriveQuery_FilesCreate queryWithObject:metadata
query.fields = "id"
self.service.executeQuery(query) { (ticket, fileN, error) in
print(ticket)
print(fileN)
print(error)
if let f = fileN as? GTLRDrive_File {
if (error == nil) {
print("File ID %@", f.identifier);
} else {
print("An error occurred: %@", error);
}
}
}
}
public func listFromAppFolder(_ parentID: String, data: Data, MIMEType: String, onCompleted: ((String?, Error?) -> ())?) {
let file = GTLRDrive_File()
file.name = "\(Date().timeIntervalSince1970)"
file.parents = ["appfolder"]
let uploadParams = GTLRUploadParameters.init(data: data, mimeType: MIMEType)
uploadParams.shouldUploadWithSingleRequest = true
let query = GTLRDriveQuery_FilesCreate.query(withObject: file, uploadParameters: uploadParams)
query.fields = "id"
self.service.executeQuery(query, completionHandler: { (ticket, file, error) in
print(ticket)
print(file)
print(error)
onCompleted?((file as? GTLRDrive_File)?.identifier, error)
})
}
public func download(_ fileID: String, onCompleted: @escaping (Data?, Error?) -> ()) {
let query = GTLRDriveQuery_FilesGet.queryForMedia(withFileId: fileID)
service.executeQuery(query) { (ticket, file, error) in
onCompleted((file as? GTLRDataObject)?.data, error)
}
}
public func search(_ fileName: String, onCompleted: @escaping (String?, Error?) -> ()) {
let query = GTLRDriveQuery_FilesList.query()
query.pageSize = 1
query.q = "name contains '\(fileName)'"
service.executeQuery(query) { (ticket, results, error) in
onCompleted((results as? GTLRDrive_FileList)?.files?.first?.identifier, error)
}
}
public func createFolder(_ name: String, onCompleted: @escaping (String?, Error?) -> ()) {
let file: GTLRDrive_File = GTLRDrive_File()
file.name = "config.json"
file.parents = ["appfolder"]
let query = GTLRDriveQuery_FilesCreate.query(withObject: file, uploadParameters: nil)
query.fields = "id"
service.executeQuery(query) { (ticket, folder, error) in
onCompleted((folder as? GTLRDrive_File)?.identifier, error)
}
}
public func delete(_ fileID: String, onCompleted: ((Error?) -> ())?) {
let query = GTLRDriveQuery_FilesDelete.query(withFileId: fileID)
service.executeQuery(query) { (ticket, nilFile, error) in
onCompleted?(error)
}
}
}
并且用于登录和使用下面的类
import UIKit
import GoogleSignIn
import GoogleAPIClientForREST
class ViewController: UIViewController {
@IBOutlet weak var resultsLabel: UILabel!
fileprivate let service = GTLRDriveService()
private var drive: ATGoogleDrive?
override func viewDidLoad() {
super.viewDidLoad()
setupGoogleSignIn()
drive = ATGoogleDrive(service)
view.addSubview(GIDSignInButton())
}
private func setupGoogleSignIn() {
GIDSignIn.sharedInstance().delegate = self
GIDSignIn.sharedInstance().uiDelegate = self
GIDSignIn.sharedInstance().scopes = [kGTLRAuthScopeDriveFile]
GIDSignIn.sharedInstance().signInSilently()
}
@IBAction func uploadAction(_ sender: Any) {
if let documentsDir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).last {
let dataImg: Data = UIImageJPEGRepresentation(UIImage(named: "logo.png")!, 1.0)!
drive?.uploadFile("config.json", data: dataImg, MIMEType: "image/png") { (fileID, error) in
print("Upload file ID: \(fileID); Error: \(error?.localizedDescription)")
}
}
}
@IBAction func listAction(_ sender: Any) {
drive?.listFilesInFolder("config.json") { (files, error) in
guard let fileList = files else {
print("Error listing files: \(error?.localizedDescription)")
return
}
self.resultsLabel.text = fileList.files?.description
print(fileList)
for nFile in fileList.files! {
if nFile.mimeType == "image/jpeg" {
self.drive?.download(nFile.identifier!, onCompleted: { (data, error) in
print(data)
print(error)
})
}
}
}
}
}
// MARK: - GIDSignInDelegate
extension ViewController: GIDSignInDelegate {
func sign(_ signIn: GIDSignIn!, didSignInFor user: GIDGoogleUser!, withError error: Error!) {
if let _ = error {
service.authorizer = nil
} else {
service.authorizer = user.authentication.fetcherAuthorizer()
service.shouldFetchNextPages = true
}
}
}
// MARK: - GIDSignInUIDelegate
extension ViewController: GIDSignInUIDelegate {}
每当我尝试上传任何文件时都会出现错误:
Error Domain=com.google.GTLRErrorObjectDomain Code=403 "The granted scopes do not allow use of the Application Data folder." UserInfo={GTLRStructuredError=GTLRErrorObject 0x281515d10: {message:"The granted scopes do not allow use of the Application Data folder." errors:[1] code:403}, NSLocalizedDescription=The granted scopes do not allow use of the Application Data folder.}
最佳答案
您需要为 google drive 配置设置范围,
GIDSignIn.sharedInstance().scopes = [kGTLRAuthScopeDriveAppData]
引用 Drive scope
关于swift - 如何访问特定于应用程序的文件夹并将其用于备份或某些特定于应用程序的数据?在 swift ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56867026/
我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div
总的来说,我对ruby还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用
类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc
我需要在客户计算机上运行Ruby应用程序。通常需要几天才能完成(复制大备份文件)。问题是如果启用sleep,它会中断应用程序。否则,计算机将持续运行数周,直到我下次访问为止。有什么方法可以防止执行期间休眠并让Windows在执行后休眠吗?欢迎任何疯狂的想法;-) 最佳答案 Here建议使用SetThreadExecutionStateWinAPI函数,使应用程序能够通知系统它正在使用中,从而防止系统在应用程序运行时进入休眠状态或关闭显示。像这样的东西:require'Win32API'ES_AWAYMODE_REQUIRED=0x0
关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。
给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru
我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t
对于具有离线功能的智能手机应用程序,我正在为Xml文件创建单向文本同步。我希望我的服务器将增量/差异(例如GNU差异补丁)发送到目标设备。这是计划:Time=0Server:hasversion_1ofXmlfile(~800kiB)Client:hasversion_1ofXmlfile(~800kiB)Time=1Server:hasversion_1andversion_2ofXmlfile(each~800kiB)computesdeltaoftheseversions(=patch)(~10kiB)sendspatchtoClient(~10kiBtransferred)Cl
我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚
Rackup通过Rack的默认处理程序成功运行任何Rack应用程序。例如:classRackAppdefcall(environment)['200',{'Content-Type'=>'text/html'},["Helloworld"]]endendrunRackApp.new但是当最后一行更改为使用Rack的内置CGI处理程序时,rackup给出“NoMethodErrorat/undefinedmethod`call'fornil:NilClass”:Rack::Handler::CGI.runRackApp.newRack的其他内置处理程序也提出了同样的反对意见。例如Rack