Write to Google Sheets in Swift - ios

I'm really confused how to write to an excel sheet, that is public. So far I have downloaded Alamofire and GoogleAPIClientForREST cocoapods. So I was wondering, if I want to write to the sheet do I first need to implement a google sign in or can I just send data over using Alamofire. I am super lost so If someone can help me that would be great.
Google sheet: https://docs.google.com/spreadsheets/d/1zJR0uk6Pb6BuxJihFyxwe4ipQdBY4E9FFR74geBj8p0/edit#gid=0
func makeAndSendRequest() {
let baseUrl = "https://sheets.googleapis.com/v4/spreadsheets"
let spreadsheetId = "1zJR0uk6Pb6BuxJihFyxwe4ipQdBY4E9FFR74geBj8p0"
let params = ["valueInputOption": "RAW"]
let range = "Studen!A3:B3"
//need to add params
let url = baseUrl + "/" + spreadsheetId + "/values/" + range + "/valueInputOption=RAW/"
let fullUrl = URL(string: url)!
//my values
let requestParams = [
"values": [
1,
2
]
]
//my auth is after Bearer so "Bearer 901390"
let header = ["Authorization":"Bearer "]
let requestURL = "https://sheets.googleapis.com/v4/spreadsheets/\(spreadsheetId)/values/\(range)?valueInputOption=RAW"
let req = Alamofire.request(requestURL, method: .put, parameters: requestParams, encoding: JSONEncoding.default,headers: header)
req.responseJSON { response in debugPrint(response) }
}

Try to fix this first.
valueInputOption is a query parameter, see: https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets.values/update
You URL should at least be:
let url = baseUrl + "/" + spreadsheetId + "/values/" + range + "?valueInputOption=RAW"
next you need to fix your request body, range is required per document here: https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets.values/update
{
"range": "A3:B3",
"values": [
[
1,
2
]
]
}
This range should be same as your range in your query parameter, say Sheet1!:A3:B3 as in your query parameter.
Note that it starts with the sheet name, it should not be "studen"
I have used the playground tool on the same page and able to call the api to change the data in your spreadsheet.
At the end I am getting 200 response code and following json:
{
"spreadsheetId": "1zJR0uk6Pb6BuxJihFyxwe4ipQdBY4E9FFR74geBj8p0",
"updatedRange": "Sheet1!A3:B3",
"updatedRows": 1,
"updatedColumns": 2,
"updatedCells": 2
}
----- Edit -----
As you asked, the API needs Oauth token, the framework to handle this is actually called G Suite
Please find the guide here:
https://developers.google.com/gsuite/guides/ios

Related

Alamofire post json and response json

i'm try to post a JSON using Swift3 and Alamofire and it work successfully in Postman Postman screen shot
but in code the response is HTML string that means an exception in server
i tried to change encoding from JsonEncoding.default to URLEncoding.default and it works good but after 3 days the same error when i run the app
let url = "http://mattam.net/mobileapp/addOrder"
let par:[String:Any] = ["order_restaurant":8,
"order_type":1,
"order_address":1,
"order_within":"45 mins",
"order_exacttime":"09:00 pm",
"order_total":300,
"order_fees":30,
"order_gtotal":330,
"order_user":38,
"pquantity[10]":3,
"pquantity[9]":1,
"poption[9]":238,
"pextra[10]":"80,81"]
print(par)
Alamofire.request(url, method: .post, parameters: par, encoding: URLEncoding.default).responseJSON{
r in
if r.result.isSuccess{print("------i______i-----")}
print(r)
if let result = r.result.value as? NSDictionary{
print(result)}
}
and in PostMan Bulk edit is
order_restaurant:8
order_type:1
order_address:1
order_within:45 mins
order_exacttime:09:00 pm
order_total:300
order_fees:30
order_gtotal:330
order_user:38
pquantity[10]:3
pquantity[9]:1
poption[9]:238
pextra[10]:80,81
and url is "let url = "http://mattam.net/mobileapp/addOrder""
Your problem is that your using http instead of https in your app.
The screenshot uses https while the url you posted (copied from your code) uses http.
If I understand your question right, you need to send some post details to the server as a Json, so here is some code to do that:
private func alamoFireAjax(url: String, parameters: Parameters, callback: #escaping (DataResponse<Any>) -> Void) {
Alamofire.request(url, method: .post, parameters: parameters, encoding: JSONEncoding.default).responseJSON(completionHandler: callback)
}
I had a similar issue and to solve it I placed the dictionary creation in a method call. You can usually get away with most requests but I found anything larger than 10 rows needed a separate method handler.
fileprivate func generateParams() -> [String: Any] {
var params = [String: Any]()
params["order_restaurant"] = 8
params["order_type"] = 1
params["order_address"] = 1
params["order_within"] = "45 mins"
params["order_exacttime"] = "09:00 pm"
params["order_total"] = 300
params["order_fees"] = 30
params["order_gtotal"] = 330
params["order_user"] = 38
params["pquantity[10]"] = 3
params["pquantity[9]"] = 1
params["poption[9]"] = 238
params["pextra[10]"] = "80,81"
return params
}

The '#' char gets converted to %23 causing the GET Request to fail

I am a new Swift developer using Swift 3 developing an iOS app. I need to make a URL Request to get some data from the web. That URL contains a # character.
I use URLComponents with URLQueryItems to build the request URL. During this process the # char gets converted to %23 which I think is valid utf8 encoding. Unfortunately, this causes the GET to fail.
To test I pasted the URL into my browser and changed %23 back to # and it worked just fine.
How can I fix this so it does not change # to URL. I did find a post from a couple years ago but it was using old framework items so it does not apply to me.
Below is the playground I made to illustrate and test this.
// ------------------------------------------------------------------
//: Playground - TestBuildURLWithParameters
//
// I am using this playground to build the proper
// URL for the GET request to get the detailed
// rtesults for a specific athlete where the "Key"
// is their Bib Nbr. If the GET cant find the specific
// Atlete with that URL it redirects you to the list
// of athlete results (which is no go to me in this case)
//
// Currently, there is a big "gotcha". In building the URL
// using component and query items, the foundation classes
// replace the '#' sign in the URL with the %23 which represents
// the pound sign. Unfortunately, the causes the GET to fail
// and redirects to athlete list which is not helpful
// I am still trying to figure out how to FORCE it to keep
// the '#" character in the URL so it will work
//
// ------------------------------------------------------------------
import Foundation
import UIKit
let baseURLString = "http://www.ironman.com/triathlon/events/americas/ironman-70.3/augusta/results.aspx"
let rd = "20150927"
let race = "augusta70.3"
let bibID = "93"
var detail = "1#axzz4FGGcjBOn"
print("Detail w/o unicocde: \(detail)")
detail = "1\u{0023}axzz4FGGcjBOn"
print("Detail with unicocde: \(detail)")
var components = URLComponents(string: baseURLString)!
var queryItems: [URLQueryItem] = [] // All Items after the "?"
let baseParams =
[
"rd": rd,
"race": race,
"bidID": bibID, // Note: HTML mispelled bib with bid so "bidID" is the URL search
"detail": detail
]
for (key, value) in baseParams
{
let item = URLQueryItem(name: key, value: value)
queryItems.append(item)
}
components.queryItems = queryItems // what does this look like
print("components: \(components)") // see it
It is not a good way to include fragment part of URL into query items.
Try this:
import Foundation
let baseURLString = "http://www.ironman.com/triathlon/events/americas/ironman-70.3/augusta/results.aspx"
let rd = "20150927"
let race = "augusta70.3"
let bibID = "93"
var detail = "1"
//# split the last query item and the fragment
let fragment = "axzz4FGGcjBOn"
var components = URLComponents(string: baseURLString)!
var queryItems: [URLQueryItem] = []
let baseParams =
[
"rd": rd,
"race": race,
"bidID": bibID,
"detail": detail
]
for (key, value) in baseParams
{
let item = URLQueryItem(name: key, value: value)
queryItems.append(item)
}
components.queryItems = queryItems
components.fragment = fragment
print("components: \(components)")
If you need you can choose the character that will receive the encoding.
In the charactersIn: you put all characters you want to encode.
Then you use the .inverted so all the others characters will go normal like this:
let customAllowedSet = NSCharacterSet(charactersIn:"=\"%/<>?#\\^`{|}").inverted
let encondedString = originalString.addingPercentEncoding(withAllowedCharacters: customAllowedSet)
print("enconded string: \(encondedString)")
Encode your parameters and then add it to URL, this will encode # before hitting API and you'll get desired result.
To encode parameters, you can use below code.
var parameterString = "your parameter string"
var encodedString = parameterString .addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)
print(encodedString !)
I did get an answer via email from a friend that works for now. Basically, I added the query items manually to the URL using the URL extension below so it didn't monkey with the '#' char:
extension URL {
func appendingNonEscapedQueryItems(_ queryItems: [URLQueryItem]) -> URL {
let url = self
var urlString = url.absoluteString
for queryItem in queryItems {
let queryName = queryItem.name
guard let queryValue = queryItem.value else {
continue
}
let query = queryName + "=" + queryValue
if queryItem == queryItems.first {
urlString = urlString + "?" + query
}
else
{
urlString = urlString + "&" + query
}
}
return URL(string: urlString)!
}
}
...
let requestURL = components.url!.appendingNonEscapedQueryItems(queryItems)
print("URL \(requestURL)")

How to send litter '&' as url parameter - swift

I have a code to update name of department in the database .. I use this encoding code :
let myurlstring="http:example/updateDepartment.php?deptName="+"\(deptName)"+"&id="+"\(deptID)"
let escapedString = myurlstring.addingPercentEncoding(withAllowedCharacters:NSCharacterSet.urlQueryAllowed)
let myUrl = URL(string:escapedString!)!
It works very well , but when deptName string contains this litter & it's not working.
example1 : send request with deptName = "CIT and Network" it will work .
example2 : send request with deptName = "CIT & Network" will be in the database as only "CIT" any litter after & will be skipped.
any help ?
Use URLComponents + URLQueryItem instead. It can be used to encode the query part from structured input:
var comp = URLComponents(string: "http://example.com")!
comp.path = "/some path to/update.php"
comp.queryItems = [
URLQueryItem(name: "deptName", value: "CIT & Network"),
URLQueryItem(name: "id", value: "123456"),
]
let url = comp.url!
print(url)
// http://example.com/some%20path%20to/update.php?deptName=CIT%20%26%20Network&id=123456

Google Sheets iOS - Map documentation to SDK

It is extremely difficult to map the Google Sheets V4 documentation to the SDK methods. For example:
To append a row to a Spreadsheet, the documentation states that there is a Request Resource, e.g.
"appendCells": {
object(AppendCellsRequest)
},
where AppendCellsRequest is
{
"sheetId": number,
"rows": [
{
object(RowData)
}
],
"fields": string,
}
However if I use the SDK as follows:
let range = "Sheet1"
let url = String(format:"%#/%#/values/%#", baseUrl, spreadsheetId, range)
let params = ["valueInputOption":"RAW"]
let fullUrl = GTLUtilities.URLWithString(url, queryParameters: params)
let body = GTLObject()
body.JSON = [ "appendCells" : [
"sheetId" : 0,
"rows" : [[value, value, value, value]],
"fields" : "*"
]]
driveService.fetchObjectByUpdatingObject(body, forURL: fullUrl, completionHandler: {
(ticket:GTLServiceTicket!, object:AnyObject!, error:NSError!) in
})
This fails with an error:
"Invalid JSON payload received. Unknown name "append_cells" at 'data': Cannot find field."
You seem to be calling the wrong URL. Your URL is constructed as:
let url = String(format:"%#/%#/values/%#", baseUrl, spreadsheetId, range)
That will result in:
http://sheets.googleapis.com/spreadsheets/{spreadsheet_id}/values/{range}
... but you are trying to use the AppendCellsRequest object, which isn't supported by the values collection. Each Request object in your link is describing an object that belongs in the request body of a batchUpdate call. For more information, see the Updating Spreadsheets guide.

Simple Post Request with Alamofire

It's my first post here, I'm trying to do this with Alamofire:
Swift code:
let name = "Taza"
let description = "50cl"
let parameters = ["name": name, "description": description]
Alamofire.request(.POST, "http://xxxxx.es/JSONpresenter.php?op=5", parameters: parameters, encoding: .JSON);
PHP code:
$op=$_GET['op'];
else if($op == 5)
{
// Get user id
$name = isset($_POST['name']) ? mysql_real_escape_string($_POST['name']) : “”;
$description = isset($_POST['description']) ? mysql_real_escape_string($_POST['description']) : “”;
add($name,$description);
}
But only get a register with "" in all cells. What am I doing wrong?
You need to use the URLEncoding instead of JSONEncoding for this particular case

Resources