Im not able to find where i have gone wrong.I tried all possible solutions but nothing seems to work.
Can anyone suggest where I have gone wrong?
My code is as below:
var diaryEntryUrl = "http://myUrl?uid=10001&diary_text=\(textPrint)&location=\(loactionAddrEnc)"
// var diaryEntryUrl = diaryEntryUrlEncode.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed) --- tried encoding, but didn't work
let postParameters:[String: Any] = [ "imagesName": self.awsImageArray2, "tagsList": self.tagArray]
Alamofire.request(diaryEntryUrl, method: .post, parameters: postParameters, encoding: JSONEncoding.default, headers: [:]).responseJSON {
response in
if response.result.isSuccess{
print("SuccessFully Added")
}else{
print("Error \(String(describing: response.result.error))")
}
}
I tried encoding the texts also but still error is there.I did it as below:
loactionAddrEnc = loactionAddr.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)
var textPrint = diaryEntryText.text.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)
I am getting the follwing error:
As you can see in the log Optional for location and diary text. So it means you need to unwrap it first.
if let textPrint = textPrint, let loactionAddrEnc = loactionAddrEnc {
var diaryEntryUrl = "http://myUrl?uid=10001&diary_text=\(textPrint)&location=\(loactionAddrEnc)"
// rest of your code
}
This should solve your problem. But there is another way.
You can pass all your query params in postParameters.
var diaryEntryUrl = "http://myUrl"
var postParameters:[String: Any] = [ "imagesName": self.awsImageArray2, "tagsList": self.tagArray]
postParameters["uid"] = "10001"
if let textPrint = textPrint {
postParameters["diary_text"] = textPrint
}
if let loactionAddrEnc = loactionAddrEnc {
postParameters["location"] = loactionAddrEnc
}
Alamofire.request(diaryEntryUrl, method: .post, parameters: postParameters, encoding: JSONEncoding.default, headers: [:]).responseJSON {
response in
if response.result.isSuccess {
print("SuccessFully Added")
}else{
print("Error \(String(describing: response.result.error))")
}
Related
New to swiftui and don't understand why the JSONDecoder() line in the first code throws
[SwiftUI] Publishing changes from background threads is not allowed; make sure to publish values from the main thread (via operators like receive(on:)) on model updates.
This to me is not updating ui so why is this showing?
do {
// pass the request type, bearer token, and email / password ( which are sent as POST body params )
let request = L.getRequest(requestType:"POST", token: token, email: self.username, password: self.psw)
L.fetchData(from: request) { result in
switch result {
case .success(let data):
// covert the binary data to a swift dictionary
do {
let response = try JSONDecoder().decode(WpJson.self, from: data)
for (key, title) in response.allowedReadings {
let vimeoId = Int( key )!
let vimeoUri = self.buildVimeoUri(vimeoId: key)
self.addReadingEntity(vimeoUri: vimeoUri, vimeoId: vimeoId, title: title)
}
self.writeToKeychain(jwt:response.jwt, displayName: response.displayName)
readings = self.fetchReadings()
}
catch {
self.error = error.localizedDescription
}
case .failure(let error):
self.error = error.localizedDescription
}
}
}
I tried wrapping a main queue around the do-catch in the L.fetchData(from: request) { result in but this did not help
DispatchQueue.main.async { [weak self] in
Here is the Login protocol, again without any ui work:
import Foundation
import SwiftUI
struct Login: Endpoint {
var url: URL?
init(url: URL?) {
self.url = url
}
}
protocol Endpoint {
var url: URL? { get set }
init(url: URL?)
}
extension Endpoint {
func getRequestUrl() -> URLRequest {
guard let requestUrl = url else { fatalError() }
// Prepare URL Request Object
return URLRequest(url: requestUrl)
}
func getRequest(requestType:String="POST", token:String, email:String="", password:String="") -> URLRequest {
var request = self.getRequestUrl()
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("Bearer \(token)", forHTTPHeaderField: "Authorization")
if ( "" != email && "" != password && requestType == "POST") {
let parameters:[String:String?] = [
"email": email,
"password": password
]
// Run the request
do {
// pass dictionary to nsdata object and set it as request body
request.httpBody = try JSONSerialization.data(withJSONObject: parameters, options: .prettyPrinted)
} catch let error {
print(error.localizedDescription)
}
}
return request;
}
func fetchData(from request: URLRequest, completion: #escaping (Result<Data, NetworkError>) -> Void) {
URLSession.shared.dataTask(with: request) { data, response, error in
if let data = data {
completion(.success(data))
} else if error != nil {
// any sort of network failure
completion(.failure(.requestFailed))
} else {
// this ought not to be possible, yet here we are
completion(.failure(.unknown))
}
}.resume()
}
}
extension URLSession {
func dataTask(with request: URLRequest, completionHandler: #escaping (Result<(Data, HTTPURLResponse), Error>) -> Void) -> URLSessionDataTask {
return dataTask(with: request, completionHandler: { (data, urlResponse, error) in
if let error = error {
completionHandler(.failure(error))
} else if let data = data, let urlResponse = urlResponse as? HTTPURLResponse {
completionHandler(.success((data, urlResponse)))
}
})
}
}
Do you have any idea on how to fix this?
Wrap it right in place of assignment
catch {
DispatchQueue.main.async {
self.error = error.localizedDescription
}
}
case .failure(let error):
DispatchQueue.main.async {
self.error = error.localizedDescription
}
}
I am using activity indicator from "https://github.com/erangaeb/dev-notes/blob/master/swift/ViewControllerUtils.swift". I tried using it in my view but indicator doesn't seem to stop.I have included it in my view as below:
ActivityIndicatorView().showActivityIndicator(uiView: self.view)
I using the below code to stop:
ActivityIndicatorView().hideActivityIndicator(uiView: self.view)
But I don't know why the indicator is stoping.
More of my code is as below:
Alamofire.request(diaryViewUrl, method: .get, parameters: [:]).responseJSON {
response in
if response.result.isSuccess{
ActivityIndicatorView().showActivityIndicator(uiView: self.view)
let dataFetched : JSON = JSON(response.result.value!)
self.diaryDateTimeText = dataFetched["diary_datetime"].string
self.diaryLocText = dataFetched["diary_loc"].string
self.diaryText = dataFetched["diary_text"].string
self.diaryTags = dataFetched["tags"].arrayObject as? [String]
ActivityIndicatorView().hideActivityIndicator(uiView: self.view)
self.topBar()
self.showViews()
self.scrollView.addSubview(self.containerView)
self.view.addSubview(self.scrollView)
}else{
print("Error \(String(describing: response.result.error))")
}
}
You have to show the activity indicator before making the Alamofire request and when you get the response with success or error status you can hide it, now show and hide are called at the same time.
It works fine for me. Please try it
ActivityIndicatorView().showActivityIndicator(uiView: self.view)
Alamofire.request(diaryViewUrl, method: .get, parameters: [:]).responseJSON {
response in
ActivityIndicatorView().hideActivityIndicator(uiView: self.view)
if response.result.isSuccess{
let dataFetched : JSON = JSON(response.result.value!)
self.diaryDateTimeText = dataFetched["diary_datetime"].string
self.diaryLocText = dataFetched["diary_loc"].string
self.diaryText = dataFetched["diary_text"].string
self.diaryTags = dataFetched["tags"].arrayObject as? [String]
self.topBar()
self.showViews()
self.scrollView.addSubview(self.containerView)
self.view.addSubview(self.scrollView)
}else{
print("Error \(String(describing: response.result.error))")
}
}
This is my code for Jason parsing in Swift:
static func POST(url: String, parameters: NSDictionary, completionBlock: #escaping CompletionBlock){
let todoEndpoint: String = Webservices.Base_Url.appending(url)
guard let url = NSURL(string: todoEndpoint) else {
print("Error: cannot create URL")
return
}
var request = URLRequest(url: url as URL)
//var request = URLRequest(url: NSURL(string: todosEndpoint)! as URL)
let session = URLSession.shared
request.httpMethod = "POST"
var err: NSError?
let jsonData = try? JSONSerialization.data(withJSONObject: parameters)
request.httpBody = jsonData
request.addValue("application/x-www-form-urlencoded;charset=UTF-8 ", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
let task = session.dataTask(with: request, completionHandler: {data, response, error -> Void in
guard error == nil else {
print("error calling POST on /todos/1")
print(error)
return
}
// make sure we got data
guard let dataTemp = data else {
print("Error: did not receive data")
return
}
// parse the result as JSON, since that's what the API provides
do {
guard let todo = try JSONSerialization.jsonObject(with: dataTemp, options: []) as? [String: AnyObject] else {
print("error trying to convert data to JSON")
return
}
// now we have the todo, let's just print it to prove we can access it
print("The todo is: " , todo)
// the todo object is a dictionary
// so we just access the title using the "title" key
// so check for a title and print it if we have one
} catch {
print("error trying to convert data to JSON")
return
}
})
task.resume()
}
I got while jason parsing:
error expression produced error: error: Execution was interrupted,
reason: EXC_BAD_ACCESS (code=1, address=0x0). The process has been
returned to the state before expression evaluation.
What's wrong?
My project had been getting the URL string for the medium sized profile pic using this code:
let downloadMediumPicTask = session.dataTask(with: mediumProfPictureURL) { (data, response, error)
in
// The download has finished.
if let e2 = error {
print("Error downloading profile picture: \(e2)")
} else {
if let res2 = response as? HTTPURLResponse {
print("Downloaded medium profile picture with response code \(res2.statusCode)")
if let imageData2 = data {
mediumProfilePictureUIImageFile = UIImage(data: imageData2)!
print("mediumProfilePictureUIImageFile has now been defined as: \(mediumProfilePictureUIImageFile).")
} else {
print("Couldn't get image: Image is nil")
}
} else {
print("Couldn't get response code for some reason")
}
}
}
downloadMediumPicTask.resume()
It crashes here giving a 403 response code. The URL that is being referenced is an expired signature URL from Facebook. Firebase doesn't adjust to get the new appropriate URL, and it was from Firebase that I had been getting the URL. I can't figure out how to get it directly as tried below:
func getUrlOfMediumProfilePic(){
if (FBSDKAccessToken.current() != nil) {
let graphPathPart2 = "me/picture"
let paramsPart2 = ["type":"medium", "redirect":"false"]
let completionHandlerPart2 = { (connection: FBSDKGraphRequestConnection?, result: Any?, error: Error?) in
if let error = error {
print("Medium picture graph call contained an error: \(error.localizedDescription)")
return
} else {
guard connection != nil else {
print("getURLOfLargeProfilePic() function aborted bc connection failed.")
return
}
let results = result! as! NSDictionary
let dataDict = results["data"] as! NSDictionary
stringOfMediumProfilePicURLaka100x100 = dataDict["url"] as! String
print("medium picture graph call results define stringOfMediumProfilePicURLaka100x100 as: \(stringOfMediumProfilePicURLaka100x100)")
}
}
let graphRequest = FBSDKGraphRequest(graphPath: graphPathPart2, parameters: paramsPart2)!
graphRequest.start(completionHandler: completionHandlerPart2)
}else{
print("User not logged in when getURLOfMediumProfilePic() function was run.")
return
}
}
This code yields an error with code 8.
Have you tried this:
https://graph.facebook.com/{id}/picture?width=100&height=100
I don't know swift, so I can't help about syntax. I think you can make http request to url and get image.
Hope this help :)
How to write the following snippet in swift 3.0 ? The following syntax is in swift 2
Alamofire.download(.POST, invoice.url,parameters:params, destination: { (url, response) -> NSURL in
let pathComponent = response.suggestedFilename
let fileManager = NSFileManager.defaultManager()
let directoryURL = fileManager.URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)[0]
let fileUrl = directoryURL.URLByAppendingPathComponent(pathComponent)
return fileUrl
})
.progress { bytesRead, totalBytesRead, totalBytesExpectedToRead in
print(totalBytesRead)
dispatch_async(dispatch_get_main_queue()) {
let progress = Double(totalBytesRead) / Double(totalBytesExpectedToRead)
completionHandler(progress, nil)
}
}
.responseString { response in
print(response.result.error)
completionHandler(nil, response.result.error)
}
In Swift 3 it is something like this.
let parameters: Parameters = ["foo": "bar"]
let destination: DownloadRequest.DownloadFileDestination = { _, _ in
let pathComponent = "yourfileName"
let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
let fileURL = documentsURL.appendPathComponent(pathComponent)
return (fileURL, [.removePreviousFile, .createIntermediateDirectories])
}
Alamofire.download(urlString, method: .get, parameters: parameters, encoding: JSONEncoding.default, to: destination)
.downloadProgress(queue: DispatchQueue.global(qos: .utility)) { progress in
print("Progress: \(progress.fractionCompleted)")
}
.validate { request, response, temporaryURL, destinationURL in
// Custom evaluation closure now includes file URLs (allows you to parse out error messages if necessary)
return .success
}
.responseJSON { response in
debugPrint(response)
print(response.temporaryURL)
print(response.destinationURL)
}
Check Alamofire Documentation or Alamofire 4.0 Migration Guide for more details.
Use func appendingPathComponent(_ pathComponent: String) -> URL instead of appendPathComponent.
let destination: DownloadRequest.DownloadFileDestination = { _, _ in
let pathComponent = "yourfileName"
let directoryURL: URL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
let folderPath: URL = directoryURL.appendingPathComponent("Downloads", isDirectory: true)
let fileURL: URL = folderPath.appendingPathComponent(pathComponent)
return (fileURL, [.removePreviousFile, .createIntermediateDirectories])
}
and it is also possible to use response.
let destination: DownloadRequest.DownloadFileDestination = { _, response in
let pathComponent = response.suggestedFilename!
let directoryURL: URL = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask)[0]
let folderPath: URL = directoryURL.appendingPathComponent("Downloads", isDirectory: true)
let fileURL: URL = folderPath.appendingPathComponent(pathComponent)
return (fileURL, [.removePreviousFile, .createIntermediateDirectories])
}