Append array value to struct - arrays

I have following struct:
struct PalletScan: Codable {
var deliveryId: String?
var userId: String?
var timestamp: String?
var tempPalletNr: String?
var tempLocation: String?
var tempPalletType: String?
var pallets: [MovementScan]?
//coding keys requried for translation API -> struct -> CoreData and CoreData -> struct -> API
enum CodingKeys: String, CodingKey {
case deliveryId = "TOID"
case userId = "UserId"
case timestamp = "TimeStamp"
}
mutating func appendMovementScan() {
var movementScan = MovementScan()
movementScan.locationId = self.tempLocation
movementScan.palletId = self.tempPalletNr
movementScan.palletType = self.tempPalletType
movementScan.timestamp = String(Date().timeIntervalSince1970)
print(movementScan)
self.pallets?.append(movementScan)
}
}
however self.pallets?.append(movementScan) does not adding anything to the pallets array. What am I missing? It must be trivial but can not find mistake.

Just change var pallets: [MovementScan]?
to
var pallets: [MovementScan] = [MovementScan]()
as #Carcigenicate you call append on nil value

var pallet is not initialized and it is an optional so when you append movementscan using ? , it wont be executed.
To fix this you have to some how initialize pallets array before appending to it .
One way can be simply initialize with empty array :
var pallets = [MovementScan]()

Related

【SwiftUI】How to initialize an empty struct

I need some kind help in SwiftUI.
I have a model below that takes in JSON data.
When I want to initialize it as an empty array, it should be simple, just stating Answers, but how can I initialize it not as an array but an empty single data set.
struct Answers: Identifiable, Decodable {
let id: Int
let questionsUsersId: Int
let reactions: [Reactions]
enum CodingKeys: String, CodingKey {
case id = "questions_id"
case questionsUsersId = "questions_users_id"
case reactions = "reactions"
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.id = try container.decodeIfPresent(Int.self, forKey: .id) ?? 0
self.questionsUsersId = try container.decodeIfPresent(Int.self, forKey: .questionsUsersId) ?? 0
self.reactions = try container.decodeIfPresent([Reactions].self, forKey: .reactions) ?? [Reactions]()
}
}
I've tried var answer: Answers = Answers( ) but got the errors below:
//Missing argument for parameter 'from' in call
//Insert 'from: <#Decoder#>'
The reason I want to initialize it empty is because I need to hand over the default value of it when the data model is nil. (i.e. what should I write in the xxx?)
#ObservedObject var receiveAnswersViewModel = ReceiveAnswersViewModel()
//abbreviate
NavigationLink(destination: AnswerDetailView(answer: receiveAnswersViewModel.answer ?? xxx), isActive: $shouldNavigate) {
ForEach(myPageViewModel.answers(forFilter: selectedFilter)?.answers ?? [Answers]()) { answer in
AnswerCell(answer: answer)
.gesture(TapGesture()
.onEnded({ _ in
//your action here
self.answersId = answer.answersId
receiveAnswersViewModel.fetchAnswers(answers_id: answersId ?? 0)
}))
}
}
This is what I'm trying to do above: Show several cells using NavigationLink. (Imagine that the cells are tweets.) Press one of the tweets in the list → Call fetchAnswers func in the View Model which takes the pressed tweet id as the argument → Returns the specific tweet detail info→ Put it in the Answer model → Hand it over to the View → Navigate to the Tweet Detail View.
View Model code is below:
class ReceiveAnswersViewModel: ObservableObject {
#Published var answer: Answers?
func fetchAnswers(answers_id: Int){
//abbreviate
self.answer = try JSONDecoder().decode(Answers.self, from: data)
}
Thanks in advance.
A reasonable way is to add a static method to create an empty instance. In this case you have also to add the init method
By the way name the struct in singular form, an instance represents likely one Answer
struct Answer: Identifiable, Decodable {
let id: Int
let questionsUsersId: Int
let reactions: [Reactions]
static let example = Answer(id: 0, questionsUsersId: 0, reactions: [])
init(id: Int, questionsUsersId: Int, reactions: [Reactions]) {
self.id = id
self.questionsUsersId = questionsUsersId
self.reactions = reactions
}
...
Then you can declare
var answer = Answer.example

How to get firstindex of array in struct Swift

Hi I have a struct like this
struct OrderCaches: Codable {
var food, drink: [Food]?
}
struct Food: Codable{
var id: Int?
var name: String?
var quantity: Double?
var notes: String?
}
I want to get first index where id = productList[indexPath.row].id
I tried with:
let index = OrderCaches.firstIndex(where: {$0.food.id == productList[indexPath.row].id})
but not work I get this error "Value of type '[Food]?' has no member 'id'".
How can I get the first Index?
Thanks
The function firstIndex is not a static member, but an instance member, hence you have to create an instance of OrderCache to get the index, like below:
let orderCaches = OrderCaches(food: [], drink: [])
let index = orderCaches.food?.firstIndex(where: { $0.id == productList[indexPath.row].id })

Array from a jsonDecoder object

This might be a very easy question (sorry!).
I would like to links a mySQL database to a Quiz App in Swift 4.
Therefore I connected to a service.php and got the information with decodable.
How can I access this information to show in a label? Do I have to make a new Array and append the objects?
import UIKit
struct Question: Codable {
let id: String?
let frage: String?
let antwort1: String?
let antwort2: String?
let antwort3: String?
let antwort4: String?
let correct: String?
let notiz: String?
let lernsektorID: String?
let lerneinheitID: String?
let lernbereichID: String?
let schwierigkeitID: String?
let redakteur: String?
let createdAt: String?
enum CodingKeys: String, CodingKey {
case id = "ID"
case frage = "Frage"
case antwort1 = "Antwort1"
case antwort2 = "Antwort2"
case antwort3 = "Antwort3"
case antwort4 = "Antwort4"
case correct = "Correct"
case notiz = "Notiz"
case lernsektorID = "LernsektorID"
case lerneinheitID = "LerneinheitID"
case lernbereichID = "LernbereichID"
case schwierigkeitID = "SchwierigkeitID"
case redakteur = "Redakteur"
case createdAt = "created_at"
}
}
var fragen = [Question]()
let url = "https://redaktion.pflegonaut.de/service.php"
let urlObj = URL(string: url)
URLSession.shared.dataTask(with: urlObj!) { (data, response, error) in
do {
self.fragen = try JSONDecoder().decode([Question].self, from: data!)
// can I use .append() here?
// maybe in a for loop?
} catch {
print(error)
}
}.resume()
So I can use the elements like:
//
// let randomizedQuestion = fragen.frage.randomElement()
//
// questionOutlet.text = randomizedQuestion
Thanks!
// NECESSARY?
var QuestionBankJson: [QuestionJson] {
var questionListJson = [QuestionJson]()
}
No, just declare one array and name the struct simply Question
var questions = [Question]()
and assign
do {
self.questions = try JSONDecoder().decode([Question].self, from: data!)
print(self.questions[1].Frage!)
} catch {
print(error) // never print something meaningless like "we got an error"
}
Notes:
Please conform to the naming convention that variable names start with a lowercase letter.
If you are responsible for the JSON declare also the keys lowercased otherwise use CodingKeys.
Declare the struct members as much non-optional as possible.
Never print a meaningless literal string when catching Codable errors. Print always the error instance.
Use a better date string format than this arbitrary German format. UNIX time stamp, SQL date string or ISO8601 are sortable and can be even decoded to Date.

remove variables through an array

I'm trying to delete values of a lot of variables inside an array:
var fbUserID = String()
var fbUserName = String()
var meNickname = String()
var userIDOneSignal = String()
var deleteStrings = [fbUserID, fbUserName, meNickname, userIDOneSignal]
Is it possible to do something in line of this:
for i in deleteStrings {
i.removeAll()//remove all as in remove the values of each variable
}
I've also tried using deleteStrings[i].removeAll()
Due to value semantics you cannot mutate variables (as a pointer) from an array.
Rather than an array use a struct
struct User {
var fbUserID = "12"
var fbUserName = "Foo"
var meNickname = "Baz"
var userIDOneSignal = "123"
mutating func clear()
{
fbUserID = ""
fbUserName = ""
meNickname = ""
userIDOneSignal = ""
}
}
var user = User()
print(user.fbUserID) // "12"
user.clear()
user.fbUserID = ""
print(user.fbUserID) // ""
Simply delete the array elements
deleteStrings.removeAll()
If your class inherits from NSObject, you can use key value coding to access the fields by name:
class User: NSObject {
var fbUserID = String()
var fbUserName = String()
var meNickname = String()
var userIDOneSignal = String()
var deleteStrings = ["fbUserID", "fbUserName", "meNickname", "userIDOneSignal"]
func clearAll() {
deleteStrings.forEach { setValue("", forKey: $0) }
}
}
let user = User()
user.fbUserID = "12345"
user.fbUserName = "Joseph Doe"
user.meNickname = "Joe"
print(user.meNickname) // "Joe"
user.clearAll()
print(user.meNickname) // ""
If you want to delete/remove variable value then use optional otherwise your variable value only gets removed or become non-existence when it goes out of scope.
For Example:
var a: Int? = 5 // it have default value 5
a = nil // Now a have nil which is kind of telling that it contains nothing which is what you want to achieve
Now coming to your question.
Is it possible to do something in line of this:
for i in deleteStrings {
i.removeAll()
}
You are iterating over an array of strings and then for each string, you are trying to remove all the characters. First of all you will get error
error: cannot use mutating member on immutable value: 'i' is a 'let' constant
Even though you will correct is using var it will not achieve what you are trying to do i.e. I want to delete the variables value because still your fbUserID ... all other variables will have copies of the data you initialised with.
Now how to do it?
You can use optional to achieve it.
var fbUserID: String? = String()
var fbUserName: String? = String()
var meNickname: String? = String()
var userIDOneSignal: String? = String()
// To delete you will need to assign them nil
fbUserId = nil
Again, you can't do them over loop because var are of values type and when you add it to the list their copies get added.

add Single Value inside an existing Section in UITableView

i have a tableview with sections for adding section i created an struct :
struct datesStruct {
var sectionYear : String!
var sectionMonth : [String]!
}
var datesStructArray = [datesStruct]()
now i want to add a single value inside my exiting sections after checking if the section is satisfying my condition, any idea how am gonna do that ???
e.g. :
if myTableViewSection1 == 2016{
//add value into this section
}
searched a lot about this but didn't get anything yet , if anybody knows then please do help me thanks
First, put this function outside of your class (before "class" or after the last "}":
func == (leftItem: DatesStruct, rightItem: DatesStruct) -> Bool{
return leftItem.sectionYear == rightItem.sectionYear
}
Then Use this:
struct DatesStruct: Equatable{
var sectionYear : String!
var sectionMonth : [String]!
}
var datesStructArray = [DatesStruct]()
func addMonthToYear(year: String, month: String){
if let foundItem: DatesStruct = datesStructArray.filter({$0.sectionYear == year}).first {
datesStructArray[datesStructArray.indexOf(foundItem)!].sectionMonth.append(month)
}
}
Simply pass the year you're looking for and the month you want to add to addMonthToYear
Declare an initializer
struct datesStruct {
var sectionYear : String!
var sectionMonth : [String]!
init(sectionYear: String!, sectionMonth: [String]!) {
self.sectionYear = sectionYear
self.sectionMonth = sectionMonth
}
}
var datesStructArray = [datesStruct(sectionYear: "year", sectionMonth: ["month1", "month2"])]
Then check whether the sectionMonth contains desired string

Resources