SWIFTUI: Trouble using FirebaseFirestoreSwift [duplicate] - google-cloud-firestore

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 months ago.
Improve this question
I am trying to learn requests to an API. I am using News API to test. I have two structs and a WebService function.
I have no idea what could be wrong here, as I am following a tutorial to learn this, and doing exactly what the teacher is showing me to do.
Struct:
import Foundation
struct ArticleList: Decodable {
let status: String
let articles: [Article]
}
struct Article: Decodable { // Decodable because we only read, we do not send anything with this struct
let title: String
let description: String
}
Here is the WebService:
import Foundation
class Webservice {
func getArticles(url: URL, completion: #escaping ([Article]?) -> ()) {
print("URL: \(url)")
URLSession.shared.dataTask(with: url) { data, response, error in
if let error = error {
print(error.localizedDescription)
completion(nil)
} else if let data = data {
let articleList = try? JSONDecoder().decode(ArticleList.self, from: data)
if let articleList = articleList {
completion(articleList.articles)
}
print(articleList?.articles)
}
}.resume()
}
}
The last print in the WebService class is printing nil even though I am using the News API link: https://newsapi.org/v2/top-headlines?country=us&apiKey=XX and yes I am using an apiKey instead of XX and when I visit the link, I get the json so that should not be the problem.
What am I doing wrong here?

Never use
try?
It is ignoring errors, use
do{
//Your code here
}catch{
print(error)
}
CodingKeys(stringValue: "description", intValue: nil)], debugDescription: "Expected String value but found null instead.", underlyingError: nil)) is telling you that it found null therefore...
Change let description: String to let description: String?
To make it optional, the API will not always have a value for the description.
Errors should always be handled gracefully. You should identify a way to throw or return a Result with a failure.
The user should be told if there is an issue.

Related

Decoding JSON with struct returns nil [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 months ago.
Improve this question
I am trying to learn requests to an API. I am using News API to test. I have two structs and a WebService function.
I have no idea what could be wrong here, as I am following a tutorial to learn this, and doing exactly what the teacher is showing me to do.
Struct:
import Foundation
struct ArticleList: Decodable {
let status: String
let articles: [Article]
}
struct Article: Decodable { // Decodable because we only read, we do not send anything with this struct
let title: String
let description: String
}
Here is the WebService:
import Foundation
class Webservice {
func getArticles(url: URL, completion: #escaping ([Article]?) -> ()) {
print("URL: \(url)")
URLSession.shared.dataTask(with: url) { data, response, error in
if let error = error {
print(error.localizedDescription)
completion(nil)
} else if let data = data {
let articleList = try? JSONDecoder().decode(ArticleList.self, from: data)
if let articleList = articleList {
completion(articleList.articles)
}
print(articleList?.articles)
}
}.resume()
}
}
The last print in the WebService class is printing nil even though I am using the News API link: https://newsapi.org/v2/top-headlines?country=us&apiKey=XX and yes I am using an apiKey instead of XX and when I visit the link, I get the json so that should not be the problem.
What am I doing wrong here?
Never use
try?
It is ignoring errors, use
do{
//Your code here
}catch{
print(error)
}
CodingKeys(stringValue: "description", intValue: nil)], debugDescription: "Expected String value but found null instead.", underlyingError: nil)) is telling you that it found null therefore...
Change let description: String to let description: String?
To make it optional, the API will not always have a value for the description.
Errors should always be handled gracefully. You should identify a way to throw or return a Result with a failure.
The user should be told if there is an issue.

Error: "Expected to decode Dictionary<String, Any> but found an array instead." — but I haven't defined a dictionary? [duplicate]

This question already has answers here:
Decoding Error -- Expected to decode Dictionary<String, Any> but found an array instead
(2 answers)
Closed 1 year ago.
I'm working on a creative project, and I'm trying to decode content from an API database using Swift's JSONDecoder() function. I've built my structs, a getData() function, and I've set up a do-try-catch for the JSONDecoder() function. I'm having difficulty understanding what I'm doing to get the error I'm getting.
Here are my structs:
struct Response: Codable {
let foundRecipes: [Recipe]
let foundIngredients: [Ingredient]
}
struct Recipe: Codable {
let id: Int
let title: String
let image: String
let imageType: String
let usedIngredientCount: Int
let missedIngredientCount: Int
let missedIngredients: [Ingredient]
let usedIngredients: [Ingredient]
let unusedIngredients: [Ingredient]
let likes: Int
}
struct Ingredient: Codable {
let id: Int
let amount: Int
let unit: String
let unitLong: String
let unitShort: String
let aisle: String
let name: String
let original: String
let originalString: String
let origianalName: String
let metaInformation: [String]
let meta: [String]
let image: String
}
Here's my getData() function:
func getData(from url: String) {
URLSession.shared.dataTask(with: URL(string: url)!, completionHandler: { data, response, error in
guard let data = data, error == nil else {
print("something went wrong.")
return
}
var result: Response?
do {
result = try JSONDecoder().decode(Response.self, from: data)
}
catch {
print("")
print(String(describing: error)) // Right here is where the error hits.
}
guard let json = result else {
return
}
print(json.foundRecipes)
}).resume()
}
Here's a link to the API's documentation. The URL I'm calling in getData() links to the same structure of search as shown in their example: https://spoonacular.com/food-api/docs#Search-Recipes-by-Ingredients — and here's a screenshot of the url results for the exact search I'm working on: https://imgur.com/a/K3Rn9SZ
And finally, here's the full error that I'm catching:
typeMismatch(Swift.Dictionary<Swift.String, Any>, Swift.DecodingError.Context(codingPath: [], debugDescription: "Expected to decode Dictionary<String, Any> but found an array instead.", underlyingError: nil))
My understanding of this error is that it's saying I told the JSONDecoder() to look for a Dictionary of <String, Any>, but it's at the link and only seeing an array. I'm confused, because I don't know where it thinks I'm providing a dictionary. Where am I screwing up? Not looking for specific code changes, just some guidance on what I'm missing.
Thanks in advance :)
As you can see in your image of the API data and in the API documentation you linked to, the API is returning an array (in the documentation, for example, you can see that it is surrounded by [...]). In fact, it looks like the API returns an array of Recipe.
So, you can change your decoding call to this:
var result: [Recipe]?
do {
result = try JSONDecoder().decode([Recipe].self, from: data)
print(result)
} catch {
print(error)
}
Perhaps your idea for Response came from somewhere else, but the keys foundRecipes or foundIngredients don't show up in this particular API call.
Also, thanks to #workingdog's for a useful comment about changing amount to a Double instead of an Int in your model.

The data couldn’t be read because it isn’t in the correct format. When using a API in Swift [duplicate]

This question already has answers here:
"The data couldn’t be read because it is missing" error when decoding JSON in Swift
(6 answers)
Swift - The data couldn’t be read because it isn’t in the correct format
(3 answers)
Closed 1 year ago.
I'm following a tutorial at the moment and trying to apply it to something that I can use and understand better then just a general random API and I ran into this issue when trying to Post data. "This data couldn't be read because it isn't in the correct format"
Using Xcode and Swift.
This is the API I'm trying to grab from is https://github.com/ToontownRewritten/api-doc/blob/master/invasions.md http://toontownrewritten.com/api/invasions
I put it formatted under the code snippet
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
fetchPostData { (posts) in
for post in posts {
print(post.type)
}
}
}
func fetchPostData(completionHandler: #escaping ([Post]) -> Void){
let url = URL(string: "https://www.toontownrewritten.com/api/invasions")!
let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
guard let data = data else { return }
do {
let postsData = try JSONDecoder().decode([Post].self, from: data)
completionHandler(postsData)
} catch {
let error = error
print(error.localizedDescription)
}
}.resume()
}
}
Here is the class that I have for posting the data
import Foundation
struct Post: Codable {
var invasions: String!
var type: String!
var asOf: Int!
var progress: Int!
}
This is the API I'm trying to grab from formatted. http://toontownrewritten.com/api/invasions
{
"lastUpdated":1624089300,
"invasions":{
"Thwackville":{
"asOf":1624089291,
"type":"Big Wig",
"progress":"477/8000"
},
"Splashport":{
"asOf":1624089283,
"type":"Short Change",
"progress":"631/3214"
},
"Kaboom Cliffs":{
"asOf":1624089282,
"type":"Legal Eagle",
"progress":"609/4000"
},
"Fizzlefield":{
"asOf":1624089299,
"type":"Bean Counter",
"progress":"6141/8000"
},
"Boingbury":{
"asOf":1624089283,
"type":"Money Bags",
"progress":"2246/3211"
}
},
"error":null
}

Getting error when trying to use Result type with delegate

Im tring to make a network call and instead of using callback I try to use delegate instead.using Result type where .Sucsess is T: Decodable and .failure is Error. passing my model in the .Sucsess is working but when trying to pass an error I get a compile error "Generic parameter 'T' could not be inferred" what am I missing ?
protocol NetworkServiceDelegate: class {
func decodableResponce<T: Decodable>(_ result: Result<T, NetworkError>)
}
let dataTask:URLSessionTask = session.dataTask(with: url) { (dataOrNil, responceOrNil, errOrNil) in
if let error = errOrNil {
switch error {
case URLError.networkConnectionLost,URLError.notConnectedToInternet:
print("no network connection")
self.delegate?.decodableResponce(Result.failure(.networkConnectionLost))
case URLError.cannotFindHost, URLError.notConnectedToInternet:
print("cant find the host, could be to busy, try again in a little while")
case URLError.cancelled:
// if cancelled with the cancelled method the complition is still called
print("dont bother the user, we're doing what they want")
default:
print("error = \(error.localizedDescription)")
}
return
}
guard let httpResponce:HTTPURLResponse = responceOrNil as? HTTPURLResponse
else{
print("not an http responce")
return
}
guard let dataResponse = dataOrNil,
errOrNil == nil else {
print(errOrNil?.localizedDescription ?? "Response Error")
return }
do{
//here dataResponse received from a network request
let decoder = JSONDecoder()
let modelArray = try decoder.decode([Movie].self, from:
dataResponse) //Decode JSON Response Data
DispatchQueue.main.async {
self.delegate?.decodableResponce(Result.success(modelArray))
}
} catch let parsingError {
print("Error", parsingError)
}
print("http status = \(httpResponce.statusCode)")
print("completed")
}
this line generates the error, it dosnt metter if I pass my enum that cumfirms to Error or trying to pass the error from the dataTask
self.delegate?.decodableResponce(Result.failure(.networkConnectionLost))
Well, you have two problems, having to do with the question "what type is this?" Swift is very strict about types, so you need to get clear about that.
.networkConnectionLost is not an Error. It is an error code. You need to pass an Error object to a Result when you want to package up the error. For example, URLError(URLError.networkConnectionLost) is an Error.
The phrase Result<T, NetworkError> makes no sense. Result is already a generic. Your job is to resolve the generic that it already is. You do that by specifying the type.
So for example, you might declare:
func decodableResponce(_ result: Result<Decodable, Error>)
It is then possible to say (as tests):
decodableResponce(.failure(URLError(URLError.networkConnectionLost)))
or (assuming Movie is Decodable):
decodableResponce(.success([Movie()]))
That proves we have our types right, and you can proceed to build up your actual code around that example code.

Why i can't get the value of NSArray? It's always return nil value.Swift 4.3 [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
I want to get the value of NSArray, but it always gives me nil value, Anyone knows how to solve it?
it is created by swift 4.2
KCNetWorkTool.tool.getRecordListWith(UserID: userID, Date: dateLabel.text!) { (result) in
SVProgressHUD.dismiss()
if let dict = result.data as NSDictionary? {
// the value of this below line, i cann't get . array always return nil
if let array = (dict["list"] as? NSMutableArray) {
let countArray = array.count
for index in 0..<countArray {
if let dictNew = array[index] as? NSDictionary {
let row = EnvelopeModel(dictionary: dictNew)
self.recordModel.append(row)
}
}
}
}
self.recordTable.reloadData()
}
}
Most of your code is unnecessary. Mostly, you don't need to be casting to Objective-C types for arrays and dictionaries. So you need something like this:
KCNetWorkTool.tool.getRecordListWith(UserID: userID, Date: dateLabel.text!) { (result) in
SVProgressHUD.dismiss()
if let envelopes = result.data["list"] as? [[String: Any?]] {
self.recordModel.append(envelopes.forEach { EnvelopeModel(dictionary: $0) })
}
self.recordTable.reloadData()
}
Haven't checked that in a compiler, but something like that.
Well actually you need to understand the basic structure of json copy and past your json string to a json formatter online tool and,
check from root key to end key. Try to unwrap the value from result. debug properly.
On second chance you are converting direct Data to [String : Any]. What Api calling tool you are using Alamofire or other library.
you can use JsonDecoder class to convert Data to your model class which is nativ tool in iOS.
Make your json to a structs and with root struct you can parse Data to whole model structured data.
struct Root<T> : Codable
{
var yourRootKey: T?
}
struct Price : Codable
{
var yoursubKey: Double?
}
Pass in decoder like Root<Price>.self
do{
let response = try JsonDecoder().decode(Root<Price>.self, for : result.data)
}catch let error{
print(error.localizedDescription)
}