SwiftUI - Check if a value is present in an array - arrays

I have an array with several objects each with a name and a password. Elsewhere I have a value and I would like to check if this value is already equal to a name in the array.
In my code, if the value is not equal to a "name" value in the array, I use the add() function.
I have no idea how to do this at all. Do you have any advice or a simple code for me please?
struct Object {
var name : String
var password : String
}
struct ContentView: View {
#State var valeur : String = "x"
#State var array = [Object]()
// Let's say it's filled
var body: some View {
VStack{
Button(action: {
if ... {
self.addRow()
}
}) {
Text("Add")
}
}
}
}

Related

AppStorage - Array - Error: No exact matches in call to initializer

I am developing an App for increasing productivity. My Main Goal in this file is to add Views over a dialog. Another target is to save the data in an Array for using it again with the annotation #AppStorage.
struct Task : Identifiable {
var id = UUID()
var myContent = "Empty"
var myCounter = 0
}
I'm using this struct to save my data which is here mainly the tasks name.
struct TaskView : View {
var task : Task
var body: some View {
HStack {
Spacer()
Text(String(task.myContent) ?? "test")
Spacer()
Text("Sessions today: " + String(task.myCounter))
Spacer()
Image(systemName: "xmark.bin.fill")
}
}
}
For displaying the data I'm using my own struct.
struct ItemList: View {
#AppStorage("myviews") var myviews : [Task]? = nil
#State private var showingAlert = false;
#State private var taskName = "tim";
var body: some View {
VStack{
if(!myviews.isEmpty){
for task in myviews {
TaskView(task: task)
}
}
Spacer()
Button {
showingAlert = true;
} label: {
Image(systemName: "plus")
.padding()
.background(Color.red)
.accentColor(.white)
.cornerRadius(100)
}
.alert(isPresented: $showingAlert) {
Alert(title: Text("Important message"), message: TextField("Task: "; text: $taskName), primaryButton: .destructive(Text("Got it!")){
myviews.append(Task(myContent: String(taskName), myCounter: 0))
})
}
Spacer()
}
}
}
So the main part consists of my #AppStorage Array, a loop to show existing "tasks" and a Dialog to add these tasks to the array.
The Error I am getting is the "No exact matches in call to initializer" directly in the line #AppStorage("myviews") var myviews : [Task]? = nil
I already tried different variations of initializing the array until I read in a forum that leaving the initialization not optional could be a cause to my problems.
Furthermore I checked my "Text" - Fields for the wrong types and casted the Int's (myCounter) to String.
It feels like I read every StackOverflow Article regarding my Error but none could help me.

How to use ForEach on an array of struct in Swift?

I have an array of Struct
struct StartView: View {
struct ExampleStruct {
var name: String
var keywords: String
var destinationID: String
init(name: String, keywords: String, destinationID: String) {
self.name = name
self.keywords = keywords
self.destinationID = destinationID
}
}
// Created 3 examplmes
let AStruct = ExampleStruct(name: "Structure A",keywords: "first: school",destinationID: "SAID")
let BStruct = ExampleStruct(name: "Structure B",keywords: "second: church",destinationID: "SBID")
let CStruct = ExampleStruct(name: "Structure C",keywords: "third: bank",destinationID: "SCID")
}
// Created my array of structures
var StructureArray = (AStruct, BStruct, CStruct)
However, I am now trying to create a NavigationView with a List but I am having issues getting this to work.
var body: some View {
NavigationView{
List {
for index in StructureArray.indices {
VStack {
// Text to put ExampleStruct name
// Text to put ExampleStruct keywords
// Text to put ExampleStruct destinationID
}
.padding()
}
}
.navigationTitle("Structure Search")
}
}
I get a Closure containing control flow statement cannot be used with result builder 'ViewBuilder' based on the for index in StructureArray.indices
I have also tried:
for index in 0..<StructureArray.count {
let currentStruc = StructureArray[index]
HStack {
Text (currentStruc.name)
Text (currentStruc.keywords)
\\ etc
}
But get the same error. I have searched online for the last few hours and am still lost on how to make this work. Am I missing something obvious? Would a ForEach be better?
You can try like below. I have corrected a few of your code. Google the changes to better understand it.
ExampleStruct
struct ExampleStruct: Identifiable {
let id = UUID()
var name: String
var keywords: String
var destinationID: String
}
ContentView
import SwiftUI
struct ContentView: View {
let aStruct = ExampleStruct(name: "Structure A",keywords: "first: school",destinationID: "SAID")
let bStruct = ExampleStruct(name: "Structure B",keywords: "second: church",destinationID: "SBID")
let cStruct = ExampleStruct(name: "Structure C",keywords: "third: bank",destinationID: "SCID")
var structArray: [ExampleStruct] {
return [aStruct, bStruct, cStruct]
}
var body: some View {
List {
ForEach(structArray) { item in
Text(item.name)
}
}
}
}
Playgrounds test

Why am I receiving this error message ("Instance method 'appendInterpolation(_:formatter:)' requires that 'Any' inherit from 'NSObject'")?)

I am trying to create a list in my app which acts as a leaderboard. It should add a new value when a button on the other main view is tapped. However, I keep getting this error and I am not sure why. Here is the code for the view of the list:
'''
struct scoreView: View {
#Binding var scoreTracker: Int
#Binding var gameTracker: Int
#Binding var gameScores: [Any]
#State var counter = 0
var body: some View {
Text("Scores: ")
VStack {
List {
ForEach(1..<gameTracker) {
Text("Game \($0): \(gameScores[gameTracker]) ")
}
}
}
}
}
'''
I created an array on my contentView to append a value to it after a button is clicked a certain number of times. However, when I try interpolating that value in the text of the list, I receive this error. How could this be fixed?
This is kind of type safety warning. String interpolation expects a string convertible object. Any object is swift can be represented as string, but without explicit implementation it'll be information about the class or struct name, address, etc. This is most probably not what you wanna see on your string, that's why this error is there.
You can silence it using String(describing::
struct scoreView: View {
#Binding var scoreTracker: Int
#Binding var gameTracker: Int
#Binding var gameScores: [Any]
#State var counter = 0
var body: some View {
Text("Scores: ")
VStack {
List {
ForEach(1..<gameTracker) {
Text("Game \($0): \(String(describing: gameScores[gameTracker])) ")
}
}
}
}
}

make a button that appends structs to an array in swift

I am trying to make a macOS list/todo app with swift and want to add a button that adds appends a struct to an array, but it shows this error: "Cannot use mutating member on immutable value: 'self' is immutable"
here is my code
import SwiftUI
struct Lists{
var title : String
var id = UUID()
}
struct SidebarView: View {
var list = [Lists(title: "one"),Lists(title: "two"),Lists(title: "three")]
var body: some View {
List{
Button(action:{
let item = Lists(title:"hello")
list.append(item)
}) {
Text("add")
}
ForEach(list, id : \.id ){ item in
NavigationLink(destination:DetailView(word:item.title)){
Text(item.title)
}
}
}
.listStyle(SidebarListStyle())
.frame(maxWidth:200)
}
}
struct SidebarView_Previews: PreviewProvider {
static var previews: some View {
SidebarView()
}
}
the code that says list.append is the error
You need to declare list as #State variable.
#State var list = [Lists(title: "one"),Lists(title: "two"),Lists(title: "three")]
Then append new item to list:
Button(action:{
let item = Lists(title:"hello")
self.list.append(item)
}) {
Text("add")
}

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)
}

Resources