I am making an app for my school. The school uses a Google Calendar to schedule all of their events. They would like me to implement the events from their calendar into the app.
I am using the Google Calander API. Since I will only be pulling information from one account there is no need for user authentication.
I have my API key and made sure my events on my google calendar are visible to everybody.
This is the JSON result that I am presented with upon running.
Here is the code in my HomeController
override func viewDidLoad() {
super.viewDidLoad()
//Event call from Google API
let url = NSURL(string: "https://www.googleapis.com/calendar/v3/calendars/<THE EMAIL ACCOUNT>/events?maxResults=15&key=APIKey-<MY API KEY>")
let task = URLSession.shared.dataTask(with: url! as URL) {(data, response, error) in
let dataAsNSString = NSString(data: data!, encoding: String.Encoding.utf8.rawValue)
print(dataAsNSString)
}
task.resume()
}
Your error is due to the either the fields query parameter has an error or is otherwise invalid. If you check the documentation, that was introduced there.
Suggested action: Because this is a permanent error, do not retry.
Read the error message instead and change your request accordingly.
Related
I'm trying to make a simple messaging app using an API. Right now, I have a thread that checks a request each second and see if the number of messages have changed, but this causes so much trouble, the RAM is constantly going up and the API becomes unresponsive because of the large number of requests. At the moment my code looks like this :
var request = URLRequest(url: URL(string: "URL")!)
let session = URLSession.shared
public func thread()
{
DispatchQueue.global(qos: .background).async {
while(true)
{
self.request.httpMethod = "GET"
self.session.dataTask(with: self.request) {data, response, err in
let json = try! JSONSerialization.jsonObject(with: data!, options: []) as? [String: Any]
let data = json?["data"] as? [[String: Any]]
if((data?.count)! > self.nbMessages)
{
self.messages.removeAll()
for message in data! {
let text = message["message_body"] as? String
let creator = message["creator_id"] as? Int
self.messages.append([text!, String(creator!)])
}
DispatchQueue.main.async {
self.nbMessages = (data?.count)!
self.TableView.reloadData()
let scrollPoint = CGPoint(x: 0, y: self.TableView.contentSize.height - self.TableView.frame.size.height)
self.TableView.setContentOffset(scrollPoint, animated: false)
}
}
}.resume()
usleep(2000)
}
}
}
This works fine, I can send messages and see messages sent to me (with a decent delay), but my logic with the request at every 2 second is way off and I acknowledge it. I'm still learning Swift so I'd really appreciate some advises on this matter, thanks!
In comments you provide elaboration, saying that you are implementing a messenger. For that purpose simple HTTP requests are not appropriate approach. Instead, you want to introduce so-called socket connection. I dare quote myself from another relevant thread:
It's called socket-connections, at a glance it looks like a channel, that hosts on a server side, and any clients (devices) can join this channel (two or more, whatever you want). If device send a message to the server, it should broadcast the message toward all other participants (it can broadcast the message even to the sender itself, but with some meta-information so we can distiguish our own messages and ignore them).
Thereby first of all you need server with socket connection established, then you can implement any of already existing solutions (e.g. https://github.com/daltoniam/Starscream for iOS). Also you may want to take a look at AWS https://aws.amazon.com, as it has the socket connection service out of the box for the server side and required SDK for both Android and iOS platforms.
I want to know how you guys handle errors when using a URLRequest in your app. How do you go about notifying your users that an error has occurred? Do you even notify your users at all? Do you try and reload the URLRequest again? Do you tell your users to close the current screen and open it again with an alert box? I have no clue.
Once there's an error, your app stops. So what do you do when this happens and you have a network issue, bad Json data?
What do you do when you get a "Bad Network Connection (The server is down)" or the URLSession comes back with an error and the internet connection is fine?
Please look at the code below and help me figure out what needs to be done when an error occurs.
let url = URL(string:"http://example/jsonFile.php")
var request = URLRequest(url:url!)
request.httpMethod = "POST"
let postingString = "id=\(id)"
request.httpBody = postingString.data(using: String.Encoding.utf8)
let task = URLSession.shared.dataTask(with: request as URLRequest){(data, response, error) -> Void in
if error != nil {
print("error \(error)")
// *****
// What do you do here? Do you tell your users anything?
// *****
return
}
// Check for Error
if let urlContent = data {
do{
let jsonResult = try JSONSerialization.jsonObject(with: urlContent, options: .allowFragments) as! [String: AnyObject]
print("jsonResult \(jsonResult)")
}
catch{
print("JSON serialization failed")
// *****
// What do you do here? Do you tell your users anything?
// *****
}
}
}
task.resume()
It is often a bad idea to hide the errors and do nothing (see Error Hiding Anti-Pattern). Unfortunately, handling errors is not easy and can be tedious some times. Pretty code examples quickly become "uglier" when exceptions and errors have to be handled. It takes time to learn to do it well.
In the case of network connections, you would want to wrap your requests into asynchronous methods that take a completion callback as parameter. This callback will often receive a successful result or an error, sometimes wrapped in an enum to remove ambiguity (see Result as an example).
Once you know a network request has failed, you can present that information to the user in a clean, informational but non-obstructive way. To find out what other applications do in this scenario, turn on Airplane Mode in your phone and poke around.
Here are some examples:
Apple Music
Facebook Messenger
I might be a little slow here, but is is possible to send push notifications with firebase programatically?
Let's say I have an iOS app and a button event. When I press that button I want to send a push notification to certain users via firebase that says 'Hello World!'.
The only way I see now to accomplish that is to use the notification console, but I want to do it programatically. Do I actually have to have my own server to do this?
What do you recommend as the easiest way nowadays to send remote push notifications programatically besides having my own server?
Currently, no. There's no recommended way of doing this through Firebase Cloud Messaging without having your own server to perform the logic. (I wouldn't make calls to the service from the client like Dupinder recommended, as it will leak your server key to the world, which is a Bad Thing Indeed)
That said, it's certainly a feature request the team hears about quite frequently so it's something they're certainly aware about and looking into.
Please make sure do NOT include the server-key into your client. There are ways "for not so great people" to find it and do stuff... The Proper way to achieve that is for your client to instruct your app-server to send the notification.
You have to send a HTTP-Post to the Google-API-Endpoint.
You need the following headers:
Content-Type: application/json
Authorization: key={your_server_key}
You can obtain your server key within in the Firebase-Project.
HTTP-Post-Content: Sample
{
"notification": {
"title": "Notification Title",
"text": "The Text of the notification."
},
"project_id": "<your firebase-project-id",
"to":"the specific client-device-id"
}
Yes, we can send push notification with firebase programatically.I have try this by getting the device token of both the users and hitting one api at the send button .Just have a look..
let url = NSURL(string: "https://fcm.googleapis.com/fcm/send")
let request = NSMutableURLRequest(URL: url!)
request.setValue("your server key ", forHTTPHeaderField:"Authorization") // your legacy server key
request.setValue("ebl0RxL94Ss:APA91bGXn_i6TLcXC1rZZSO1pKXCnqKjg-SxOHsjdahoJ4qIjVxX6dwal3YNeCvpHltEnwHibEuldWzfTiQewgD_J_4HIg31VE_vyvONdHN9v6VQGRcY6PaXY1xZmJ9t_cKfs7sQ9K1q", forHTTPHeaderField:"Authentification") // sender refreshedToken
request.setValue("application/json", forHTTPHeaderField:"Content-Type")
request.HTTPMethod = "POST"
let sessionConfig = NSURLSessionConfiguration.defaultSessionConfiguration()
// dictionary containing sender refreshedToken and other notification detail including text
let json = ["to":"c6HixiMte3A:APA91bFfNvQev2qcZqdsnJ9qoho_GlXRj1PWx6FWleScgExBi95WAkRqmp2jilCbZYoifs9bfHPyGpofjTAM239SYEiAwMRzgAONFv_KH-u49pG9C6f6UEVY4WEctjFzek9WZ7pBv31t",
"priority":"high",
"content_available":true,
"notification":["body":"new messages","title":text,"score":"5x1","time": "15:10"]]
do {
let jsonData = try NSJSONSerialization.dataWithJSONObject(json, options: NSJSONWritingOptions.PrettyPrinted)
request.HTTPBody = jsonData
} catch let error as NSError {
print(error)
}
// insert json data to the request
let urlSession = NSURLSession(configuration: sessionConfig, delegate: self, delegateQueue: NSOperationQueue.mainQueue())
let dataTask = urlSession.dataTaskWithRequest(request) { (data: NSData?, response: NSURLResponse?, error: NSError?) -> Void in
let strData = NSString(data: data!, encoding: NSUTF8StringEncoding)
print("Body: \(strData)")
print(response,data)
print(error)
}
dataTask.resume()
I need to show a web browser in my app. I can't use SFSafariViewController as I need to be able to authenticate with NTLM, so I'm currently using Alamofire to download the data and then displaying it in a UIWebView.
I have got the UIWebView to display the HTML via .loadHTMLString(), however the images, CSS and Javascript files are not loading. I tried setting the baseURL to the website root, however, when I do this nothing at all loads in the UIWebView, leaving it blank with no content or errors in the console.
Alamofire.request(.GET, "https://dev-moss.stpaulscatholiccollege.co.uk/sites/Students/default.aspx").authenticate(usingCredential: credential)
.response { request, response, data, error in
dispatch_async(dispatch_get_main_queue(), { () -> Void in
// check for errors or bad responsecode
if (error == nil) && (response?.statusCode == 200) {
// load the website
let gatewayString = "\(NSString(data: data!, encoding: NSUTF8StringEncoding))"
self.gatewayWebView.loadHTMLString(String(NSString(data: data!, encoding: NSUTF8StringEncoding)!), baseURL: nil)
print(gatewayString)
}
else {
print("There was an error loading the website.")
}
})
}
Even when setting the baseURL to NSURL(string: "https://dev-moss.stpaulscatholiccollege.co.uk/") or NSURL(string: "https://dev-moss.stpaulscatholiccollege.co.uk") the print of gatewayString still spits out the website to the console however.
Your code isn't working because the base URL isn't https://dev-moss.stpaulscatholiccollege.co.uk/, it's https://dev-moss.stpaulscatholiccollege.co.uk/sites/Students/default.aspx. Try that and it should work.
Edit:
It looks like it's not working because https://dev-moss.stpaulscatholiccollege.co.uk/sites/Students/default.aspx uses HTTP Basic Authentication, which you have not provided credentials for (the UIWebView makes a separate requests for resources from your one made via Alamofire, which doesn't include your credentials.) See How to do authentication in UIWebView properly?
I am trying to open from my app Apple Music app using UIApplication.sharedApplication().openURL and search for an artist or having a link opening a related page where the song is.
Is there an api I can use to search on the Apple Music App? Is this possible?
let test = "https://itun.es/gb/RJEL2?i=915794180"
UIApplication.sharedApplication().openURL(NSURL(string:test)!)
If I use that link the app opens up but nothing happens.
If
let test = "https://itun.es/gb/RJEL2?i=915794180"
contains your search information you can get the contents of the url like such
let Session = NSURLSession.SharedSession()
var task = Session.dataTaskWithURL(test, completionHandler: {
(data, response, error) -> Void in
:
})
task.resume()