add Single Value inside an existing Section in UITableView - arrays

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

Related

Weekly activity summary help? SWIFTUI

I'm tryin' to obtain a list of activities ("dd/mm/YY: goal achieved/missed goal") which has to be setted every week. The problem is that I obtain a list of activities with the same date and the same result of the previous one. For example:
28/02/2022: goal achieved
28/02/2022: goal achieved
28/02/2022: goal achieved
and the next day:
01/03/2022: missed goal
01/03/2022: missed goal
01/03/2022: missed goal
01/03/2022: missed goal
I want to obtain, instead, a list like:
28/02/2022: goal achieved
01/03/2022: missed goal
02/03/2022: goal achieved...
These are useful structs:
struct Persistent {
#AppStorage("goalAchieved") static var goalAchieved : Bool = false
#AppStorage("activityList") static var activityList : [String] = []
}
struct obj {
static var currentDate = Date()
static var stringDate = ""
static var activity = Activity(date:Persistent.lastUpdatedDate)
}
This is the ActivityListView:
import SwiftUI
func activitystring(activity:Activity) -> String{
var output = ""
output = "\(activity.date): \(activity.reachedobj(goalAchieved: Persistent.goalAchieved))"
return output
}
struct Activity: Identifiable{
let id = UUID()
let date: String
func reachedobj(goalAchieved: Bool) -> String {
var output = ""
if Persistent.goalAchieved == false { output = "Missed goal" }
if Persistent.goalAchieved == true { output = "Goal Achieved!"}
return output
}
}
struct ActivityRow: View{
var activity: Activity
var body: some View{
Text(activitystring(activity: activity))
Divider()
}
}
struct ActivityListView: View {
var body: some View {
ScrollView{
Text("Week summary").font(.system(size: 15)).foregroundColor(Color.green)
Text("")
ForEach(Persistent.activityList, id: \.self) { activity in
let activity = Activity(date: Persistent.lastUpdatedDate)
ActivityRow(activity: activity)
}
}
}
}
Finally this is the useful code in the ApplicationApp file (main) where I update activity list:
MenuView().onAppear(){
if Persistent.activityList.count>7{
Persistent.activityList.removeAll()
}
obj.currentDate = Date()
let formatter = DateFormatter()
formatter.dateFormat = "dd/MM/YY"
obj.stringDate = formatter.string(from:obj.currentDate)
if Persistent.lastUpdatedDate != obj.stringDate{
Persistent.goalAchieved = false
let activity = Activity(date: Persistent.lastUpdatedDate)
Persistent.activityList.append(activitystring(activity: activity))
Persistent.lastUpdatedDate = obj.stringDate
}
}
What's wrong on this?
You're calling obj.activity in your ForEach and ActivityRow, that's why it repeats that same static property all over the place.
You better just drop your struct obj and try again without it
In your Persistent object you have an array of many activities, called activitylist , but one single boolean that tells if the goal is achieved - goalachieved indeed.
Your view is iterating through the array of Persistent.activitylist, so you will have many lines for one single result - achieved or not achieved. You might actually want to iterate over an array of Persistent objects - meaning that somewhere you should probably store [Persistent] in some variable. In this way, you will see one line only for each result.
If I also may suggest: use the conventions for naming variables, Swift uses "camelCaseConventionForVariables", easier to read than "thewholevariableislowercase"
Edit:
Let me try to change a little bit your code (I would personally change it more radically, but that's not the scope of the answer).
Instead of having only one goalAchieved for all elements on the array activityList, make it a dictionary:
struct Persistent {
// Drop this variable
// #AppStorage("goalAchieved") static var goalAchieved : Bool = false
// Make this a dictionary, the date will be the key and the goalAchieved will be the value
#AppStorage("activityList") static var activityList : [String: Bool] = [:]
}
Add values to the dictionary (#meomeomeo is right, you don't need obj):
MenuView().onAppear() {
if Persistent.activityList.count > 7 {
Persistent.activityList.removeAll()
}
let currentDate = Date()
let formatter = DateFormatter()
formatter.dateFormat = "dd/MM/YY"
let stringDate = formatter.string(from: currentDate)
if Persistent.lastUpdatedDate != stringDate {
let activity = Activity(date: Persistent.lastUpdatedDate)
Persistent.activityList[activitystring(activity: activity))] = false // Will create something like ["01/03/2022": false]
Persistent.lastUpdatedDate = stringDate
}
}
Iterate on the dictionary in your ForEach; for more info: read here.

How to acces array of structures in structure Swift

I have the following stucture:
struct Points : Codable {
var name : String?
var interests : [Interests]
///How do i get string or array of string that is equal to all interests
var allInterestText : String ///???
}
struct Interests : Codable {
var interest : Interest?
}
struct Interest : Codable{
var name : String?
}
I've been trying to achieve that, but all my attempts have failed.
Try this for a single String:
struct Points {
// ...
var allInterestText: String {
interests.compactMap { $0.interest?.name }.joined(separator: " ")
}
}
if you decide you want an Array instead, simple change the type and remove the .joined()

Append array value to struct

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]()

Modify an array element after finding it in swift does not work

I wrote a model like this as an exercise :
struct Store {
var name : String
var bills : Array<Bill>
var category : Category?
}
struct Bill {
var date : String
var amount : Float
}
struct Category {
var name : String
var tags : Array<String>
}
and when I'm searching if a store already exist to add a bill to it instead of creating a new store, my code doesn't work. It acts like if the result of the search is a copy of the Array element . I would like to have a reference.
var stores : Array <Store> = Array()
for billStatment in billStatements! {
let billParts = billStatment.split(separator: ",")
if billParts.count > 0 {
let bill : Bill = Bill(date:String(billParts[0]), amount: Float(billParts[2])!)
var store : Store = Store(name:String(billParts[1]), bills: [bill], category: nil)
if var alreadyAddedStore = stores.first(where: {$0.name == String(billParts[1])}) {
alreadyAddedStore.bills.append(bill)
print("yeah found it \(alreadyAddedStore)") // the debugger breaks here so I know the "first" method is working. If I print alreadyAddedStore here I have one more element, that's fine.
} else {
stores.append(store)
}
}
}
print("\(stores.count)") // If I break here for a given store that should contains multiple elements, I will see only the first one added in the else statement.
Can anyone tell me what I am doing wrong?
As already noted, you're confusing value (struct) semantics with reference (class) semantics.
One simple fix would be the change stores to a dictionary with the name as your key:
var stores : Dictionary<String, Store> = [:]
and use it like this:
if(stores[store.name] == nil) {
stores[store.name] = store
}
else {
stores[storeName].bills.append(bill)
}

How to use UISearchBarController with array subsection

I am using the following array structure to create a tableView with sections
struct words {
var sectionName : String!
var coptic : [String]!
var english : [String]!
}
var array = [words]()
var filtered = [words]()
array = [words(sectionName: "", coptic: [""], English: [""])]
I want to utilize a searchcontroller using similar code to this
func updateSearchResults(for searchController: UISearchController) {
// If we haven't typed anything into the search bar then do not filter the results
if searchController.searchBar.text! == "" {
filtered = array
} else {
// Filter the results
filtered = array.filter { $0.coptic.lowercased().contains(searchController.searchBar.text!.lowercased()) }
}
Unfortunately, because coptic is a [String], and not simply a String, the code doesn't work. Is there a way to modify this to be able to filter a search for the coptic subsection?
you can do like this.
func updateSearchResults(for searchController: UISearchController) {
// If we haven't typed anything into the search bar then do not filter the results
if searchController.searchBar.text! == ""
{
filtered = array
}
else
{
filtered.removeAll()
array.forEach({ (word:words) in
var tempWord:words = words.init(sectionName: word.sectionName, coptic: [""], english: [""])
let copticArray = word.coptic.filter({ (subItem:String) -> Bool in
let a = subItem.lowercased().contains(searchController.searchBar.text!.lowercased())
return a;
})
tempWord.coptic = copticArray
filtered.append(tempWord)
})
}
}
Input array = array = [words(sectionName: "abc", coptic: ["apple","ball","cat","dog"], english: [""])]
Search For "app"
OUTPUT words(sectionName: abc, coptic: ["apple"], english: [""])]

Resources