NSURLSession validation - swift

I'm trying o work out the correct (or at least a good) way to handle data request using Swift 2.
What i want to achieve is to:
Check if a data connection is available, if no then alert the user
If connection is available make a request
Check request response, if invalid then alert the user
if valid, check the response code and display one of 2 messages
what i have so far
let requestURL: String = **********************
let url = NSURL(string: requestURL)!
let request = NSMutableURLRequest(URL: url)
let session = NSURLSession.sharedSession()
let postParams: NSDictionary = ["id":newId!]
request.HTTPMethod = "POST"
do {
let jsonData = try NSJSONSerialization.dataWithJSONObject(postParams, options: [])
let jsonString = NSString(data: jsonData, encoding: NSUTF8StringEncoding)! as String
let utf8str = jsonString.dataUsingEncoding(NSUTF8StringEncoding)
let base64Encoded = utf8str?.base64EncodedStringWithOptions(NSDataBase64EncodingOptions(rawValue: 0))
let bodyData = "data="+base64Encoded!
request.HTTPBody = bodyData.dataUsingEncoding(NSUTF8StringEncoding)
} catch {
print("Error serialising JSON")
}
session.dataTaskWithRequest(request) { data, response, error in
// Make sure response is OK
guard let realResponse = response as? NSHTTPURLResponse where realResponse.statusCode == 200 else
{
// Show success message
print("Invalid Response from server")
}
// Read JSON Data
if let postString = NSString(data:data!, encoding: NSUTF8StringEncoding) as? String {
if let responseData = postString.dataUsingEncoding(NSUTF8StringEncoding) {
let json = JSON(data: responseData)
let responseMessage:String = json["response"]["data"].stringValue
if(responseMessage == "success")
{
print("successful post")
}else{
print("error saving post")
}
}
}
}
Currently if i was to run this in airplane mode then nothing happens, but i would like to catch this and tell these they need a data connection

Try sth like this:
func connectedToNetwork() -> Bool {
var zeroAddress = sockaddr_in()
zeroAddress.sin_len = UInt8(sizeofValue(zeroAddress))
zeroAddress.sin_family = sa_family_t(AF_INET)
let defaultRouteReachability = withUnsafePointer(&zeroAddress) {
SCNetworkReachabilityCreateWithAddress(nil, UnsafePointer($0))
}
var flags = SCNetworkReachabilityFlags()
if !SCNetworkReachabilityGetFlags(defaultRouteReachability!, &flags) {
return false
}
let isReachable = (flags.rawValue & UInt32(kSCNetworkFlagsReachable)) != 0
let needsConnection = (flags.rawValue & UInt32(kSCNetworkFlagsConnectionRequired)) != 0
return (isReachable && !needsConnection)
}
if(connectedToNetwork() == true){
//call your function to make the request
} else {
//show alert that they need an internet connection
}

Related

Why is this URLSession.datatask not working in Swift 5 for macos

I am trying to make my own DynamicIP updater as a command line tool so I can set it up to run as a launch agent. I thought this would be a pretty simple thing to do, but I am not getting anything when I run this bit of code.
main.swift:
import AppKit
let userName = "yourUserName"
let password = "yourPassword"
let domain = "yourDomainName"
let ftp = "ftp"
let www = "www"
let checkIPURL = URL(string: "https://svc.joker.com/nic/checkip")
let domainUpdateURL = URL(string: "https://svc.joker.com/nic/update?username=\(userName)&password=\(password)&hostname=\(domain)")
let ftpUpdateURL = URL(string: "https://svc.joker.com/nic/update?username=\(userName)&password=\(password)&hostname=\(ftp).\(domain)")
let wwwUpdateURL = URL(string: "https://svc.joker.com/nic/update?username=\(userName)&password=\(password)&hostname=\(www).\(domain)")
var ipAddress = ""
if let url = checkIPURL {
print("1 - \(url)")
var request = URLRequest(url: url)
print("2 - \(request.url!)")
request.httpMethod = "POST"
print("3")
let session = URLSession.shared
print("4")
session.dataTask(with: request) { data, response, error in
print("4.1")
guard error == nil else {
print("Error:", error ?? "")
return
}
print("4.2")
guard (response as? HTTPURLResponse)?
.statusCode == 200 else {
print("down")
return
}
print("4.3")
if let data = data {
if let dataString = String(decoding: data, as: UTF8.self).removeHtmlTags() {
if let startIndex = dataString.lastIndex(of: " ") {
let chars = dataString.distance(from: startIndex, to: dataString.endIndex)-1
ipAddress = String(dataString.suffix(chars))
}
}
print(ipAddress)
} else {
print("No data")
}
print("up - \(response!)")
}.resume()
print("Done.")
}
extension String {
// Credit - Andrew - https://stackoverflow.com/questions/25983558/stripping-out-html-tags-from-a-string
func removeHtmlTags() -> String? {
do {
guard let data = self.data(using: .utf8) else {
return nil
}
let attributed = try NSAttributedString(data: data, options: [.documentType: NSAttributedString.DocumentType.html, .characterEncoding: String.Encoding.utf8.rawValue], documentAttributes: nil)
return attributed.string
} catch {
return nil
}
}
}
Everything outside of the session prints, but nothing inside of it prints (4.x statements).
I deleted the AppSandbox because when I have AppSandbox as a Capability and turn on Outgoing Connections I get a crash with EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0).
But even with AppSandbox deleted it does not work.
The strange thing is this works fine in a playground (with a slight modification turning the String extension into a function within the playground), which really makes this a head scratcher for me.
Here's my playground code:
import AppKit
let userName = "yourUserName"
let password = "yourPassword"
let domain = "yourDomainName"
let ftp = "ftp"
let www = "www"
let checkIPURL = URL(string: "https://svc.joker.com/nic/checkip")
let domainUpdateURL = URL(string: "https://svc.joker.com/nic/update?username=\(userName)&password=\(password)&hostname=\(domain)")
let ftpUpdateURL = URL(string: "https://svc.joker.com/nic/update?username=\(userName)&password=\(password)&hostname=\(ftp).\(domain)")
let wwwUpdateURL = URL(string: "https://svc.joker.com/nic/update?username=\(userName)&password=\(password)&hostname=\(www).\(domain)")
var ipAddress = ""
if let url = checkIPURL {
print("1 - \(url)")
var request = URLRequest(url: url)
print("2 - \(request.url!)")
request.httpMethod = "POST"
print("3")
let session = URLSession.shared
print("4")
session.dataTask(with: request) { data, response, error in
print("4.1")
guard error == nil else {
print("Error:", error ?? "")
return
}
print("4.2")
guard (response as? HTTPURLResponse)?
.statusCode == 200 else {
print("down")
return
}
print("4.3")
if let data = data {
//if let dataString = String(decoding: data, as: UTF8.self).removeHtmlTags() {
if let dataString = removeHtmlTags(data: data) {
if let startIndex = dataString.lastIndex(of: " ") {
let chars = dataString.distance(from: startIndex, to: dataString.endIndex)-1
ipAddress = String(dataString.suffix(chars))
}
}
print(ipAddress)
} else {
print("No data")
}
print("up - \(response!)")
}.resume()
print("Done.")
}
func removeHtmlTags(data: Data) -> String? {
do {
let attributed = try NSAttributedString(data: data, options: [.documentType: NSAttributedString.DocumentType.html, .characterEncoding: String.Encoding.utf8.rawValue], documentAttributes: nil)
return attributed.string
} catch {
return nil
}
}
Is there something else I need to do to get this to work within the command line tool app I am trying to build?

Multiple File Upload in Swift

I am trying to upload multiple file to the server by my iPhone. The problem is that when I try to upload 1.4 mb file it could not upload properly. I checked the uploaded file and the file size is 1 kb. So I made this code based on the postman. As you know the postman can create the code according to which language do you want. Thank you.
function uploadFile(){
var parameters: [[String: Any]] = []
var fileCount: Int = 0
let homeDirectory = ""
var soundPath = "\(homeDirectory)\(CommonUtil.PATH_SOUND)"
soundPath = soundPath.replacingOccurrences(of: "file:///", with: "")
//fiels[0] = ["fileName" : "2021_10_19_09_12_52.wav"]
//fiels[1] = ["fileName" : "2021_10_19_09_12_53.wav"]
//fiels[3] = ["fileName" : "2021_10_19_09_12_54.wav"]
for item in files{
var dict = item as! [String:String]
let strFilePath = "\(soundPath)\(dict["fileName"]!)"
if FileManager.default.fileExists(atPath: strFilePath){
var dict = [String:Any]()
dict.updateValue("strFileName[\(fileCount)]", forKey: "key")
dict.updateValue(strFilePath, forKey: "src")
dict.updateValue("file", forKey: "type")
parameters.append(dict)
fileCount++
}
print(dict["fileName"]!)
}
var dict = [String:Any]()
dict.updateValue("strApiName", forKey: "key")
dict.updateValue("soundFileUpload", forKey: "value")
dict.updateValue("text", forKey: "type")
parameters.append(dict)
uploadFiles(parameters: parameters)
}
func uploadFiles(parameters: [[String: Any]]){
var semaphore = DispatchSemaphore(value: 0)
let boundary = "Boundary - \(UUID().uuidString)"
var body = ""
var error: Error? = nil
for param in parameters {
if param["disabled"] == nil {
let paramName = param["key"]!
body += "--\(boundary)\r\n"
body += "Content-Disposition:form-data; name=\"\(paramName)\""
if param["contentType"] != nil {
body += "\r\nContent-Type: \(param["contentType"] as! String)"
}
let paramType = param["type"] as! String
if paramType == "text" {
let paramValue = param["value"] as! String
body += "\r\n\r\n\(paramValue)\r\n"
} else {
let paramSrc = param["src"] as! String
//let fileData = URL(string: paramSrc)?.dataRepresentation ?? Data()
let fileData = try! NSData(contentsOfFile:paramSrc, options:[]) as Data
let fileContent = String(data: fileData, encoding: .utf8)
body += "; filename=\"\("file:///"+paramSrc)\"\r\n"
+ "Content-Type: \"content-type header\"\r\n\r\n\(fileContent)\r\n"
}
}
}
body += "--\(boundary)--\r\n";
let postData = body.data(using: .utf8)
var request = URLRequest(url: URL(string: "http://api.polytus.com/")!,timeoutInterval: Double.infinity)
request.addValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
request.httpMethod = "POST"
request.httpBody = postData
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data else {
DispatchQueue.main.async {
self.showLoading(show: false)
self.showBluetoothAlert(message: "failed")
}
print(String(describing: error))
semaphore.signal()
return
}
DispatchQueue.main.async {
self.showLoading(show: false)
self.showBluetoothAlert(message: "success")
}
print(String(data: data, encoding: .utf8)!)
semaphore.signal()
}
task.resume()
semaphore.wait()
}
For what I've understand you want to know the file size in the server filesystem. If this is you want you have to use an API that give you back the data, after the file is uploaded and moved from temporary web server space to final location. In brief you need to do 2 request, one for upload and one for getting the file data (space or any other data needed), or develop an API that give you as answer of the correct upload the file size.

Logical fault in repeat-while loop?

I have a problem with the repeat-while loop.I dont know why it doesnt work at my code.Maybe i have some logical fault.
func getJson(){
repeat{
movieName.isHidden = true
let randomNumber = Int(arc4random_uniform(128188))
let jsonUrlString = "https://api.url/3/movie/" + String(randomNumber) + "?api_key="
//let jsonUrlString = "https://api.url.org/3/movie/564?api_key=key&language=de-DE"
guard let url = URL(string: jsonUrlString) else
{return}
URLSession.shared.dataTask(with: url) { (data, response, err) in
guard let data = data else {return}
let dataString = String(data: data, encoding: .utf8)
print(dataString ?? String())
strTrue = false
Here I'm checking if the api returns some data if not they will give me a status code 34.Im checking for the word "status code".
If the api returns "status_code". I'm checking it with a if and then I turn string-code to true.So the condition of the repeat-while loop is
then string-code is true he will start it again and looking for a new movie id.But I tested it and it doesn't work. Maybe you guys can help me :)
let stringCode = dataString?.contains("status_code")
if stringCode == true {
print("yes fehler 34")
strTrue = stringCode!
print(strTrue)
}
do {
guard let json = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as? [String: Any] else {return}
let movie = Movie(json: json)
print(movie.name)
print(movie.genres)
let imageString = "https://image.url.org/t/p/w500"+(movie.imageUrl)
let url2 = URL(string: imageString)
//self.movieImage.downloadedFrom(url: url2!)
self.movieDescriptionLabel = movie.overview
self.movieNameLabel = movie.name
DispatchQueue.main.async {
self.movieName.isHidden = false
self.movieName.text = self.movieNameLabel
self.movieDescription.text = self.movieDescriptionLabel
self.movieImage.downloadedFrom(url: url2!)
}
} catch let jsonError {
print("Error",jsonError)
self.getJson()
}
}.resume()
}while(strTrue == true)

How To Grab HTML From Page Mac Os Swift 3

I would like to know why this is not working. Could someone share a better way to get information from a website. Here I'm trying to grab a price of and item from HomeDepot Website. Then display it in a label called lblmessage.
let url = URL(string:"http://www.homedepot.com/p/SAKRETE-80-lb-Gray-Concrete-Mix-65200390/100350291?MERCH=REC-_-NavPLPHorizontal1_rr-_-NA-_-100350291-_-N")!
let request = NSMutableURLRequest(url: url)
let task = URLSession.shared.dataTask(with: request as URLRequest) {
data, response, error in
var message = ""
if error != nil {
print(error)
}else {
if let unwrappedData = data {
let dataString = NSString(data: unwrappedData, encoding: String.Encoding.utf8.rawValue)
var stringSeparator = "<span id=\"ajaxPriceAlt\" class=\"pReg\" itemprop=\"price\">"
if let contentArray = dataString?.components(separatedBy: stringSeparator) {
if contentArray.count > 0 {
stringSeparator = "</span>"
let newContentArray = contentArray[1].components(separatedBy: stringSeparator)
if newContentArray.count > 0 {
message = newContentArray[0]
print(newContentArray[0])
self.lblmessage.stringValue = newContentArray[0]
}
}
}
}
}

Login Connection, method Get swift with API

I want to connect in an app in swift 2.1
I have a button logIn and I make a function loginButton.
I want to recover my url: localhost/connexion/login/password
And with that I want to say if the user is in the database it's ok !
But I don't really anderstant swift, I'm a beginner in this language.
So there is my code:
#IBAction func loginButton(sender: AnyObject) {
NSLog("login ok")
let _login = loginText.text
let _password = passwordText.text
if(_login!.isEmpty || _password!.isEmpty){
var alert:UIAlertView = UIAlertView()
alert.title = "Error"
alert.message = "Entrez vos identifiants"
alert.delegate = self
alert.addButtonWithTitle("OK")
alert.show()
} else{
let request = NSMutableURLRequest(URL: NSURL(string: "http://localhost:8888/connexion/"+_login!+"/"+_password!)!)
request.HTTPMethod = "GET"
let postString = "login=\(_login!)&pass=\(_password)"
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithRequest(request)
task.resume();
}
}
I have follow this before How to make an HTTP request in Swift?
but it doesn't work.
I tried a lot of things, but without really understand what happened and I don't find a great tutorial with very good explanation. If someone can explain me how to do it I will be very happy !
I think for sending data to server you should create a "POST" request and use NSURLSession API to send data
#IBAction func loginButton(sender: AnyObject) {
NSLog("login ok")
let _login = loginText.text
let _password = passwordText.text
if(_login.isEmpty || _password.isEmpty){
var alert:UIAlertView = UIAlertView()
alert.title = "Error"
alert.message = "Entrez vos identifiants"
alert.delegate = self
alert.addButtonWithTitle("OK")
alert.show()
} else{
let request = NSMutableURLRequest(URL: NSURL(string: "http://localhost:8888/connexion/login")!)
request.HTTPMethod = "POST"
let params = ["login": _login, "pass": _password]
do {
let data = try NSJSONSerialization.dataWithJSONObject(params, options: .PrettyPrinted)
request.HTTPBody = data
} catch let error as NSError {
print("json error: \(error.localizedDescription)")
}
let loginTask = NSURLSession.sharedSession().dataTaskWithRequest(request, completionHandler: { (data, response, error) in
guard let data = data, let _ = response where error == nil else {
print("error")
return
}
do {
let json = try NSJSONSerialization.JSONObjectWithData(data, options: .AllowFragments)
print(json)
} catch let error as NSError {
print("json error: \(error.localizedDescription)")
}
})
loginTask.resume()
}
}
for using "GET" replace else part with
let url = "http://localhost:8888/connexion/login=\(_login)&pass=\(_password)"
let urlString = url.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLQueryAllowedCharacterSet())!
let request = NSURLRequest(URL: NSURL(string: urlString)!)
let loginTask = NSURLSession.sharedSession().dataTaskWithRequest(request, completionHandler: { (data, response, error) in
guard let data = data, let _ = response where error == nil else {
print("error")
return
}
/*do {
let json = try NSJSONSerialization.JSONObjectWithData(data, options: .AllowFragments)
print(json)
} catch let error as NSError {
print("json error: \(error.localizedDescription)")
}*/
if let httpStatus = response as? NSHTTPURLResponse where httpStatus.statusCode != 200 { // check for http errors
print("statusCode should be 200, but is \(httpStatus.statusCode)")
print("response = \(response)")
}
let responseString = String(data: data!, encoding:NSUTF8StringEncoding)
print("responseString = \(responseString)")
})
loginTask.resume()