Home > Software engineering >  Update Text Field only when Variable updates from the cloud in IOS app
Update Text Field only when Variable updates from the cloud in IOS app

Time:03-20

I am using Firebase to append a String of data for an Array. I would then like to display this data on the screen. The view on the screen is a List and each Post is looking at a different part of the Array (example; postName[0] vs. postName[1].

My problem is that as soon as the screen loads, the data has not completely loaded from the cloud yet and therefore the Array is empty. This causes the app to crash saying that "Index out of range" since there is nothing in an array that a Text box is trying to read from.

The Array receives data from Firebase and if the data arrives fast enough no issue occurs, however, sometimes the data does not come fast enough and crashes saying index not in range.

Is there anything I can set up to not load the Text field until the data has finished loading?

Code provided:

List(fetchPostModel.postsNearby, id: \.self) { post in
        
    ZStack {
            
            if !fetchPostModel.postName.isEmpty { Text(fetchPostModel.postName[Int(post) ?? 0])
                    .font(.title)
                    .bold()
                    .padding()
            } else { Text("Loading...").font(.title).bold().padding() }
            
    }
    .onAppear {
        fetchFromCloud(postNumber: fetchFromCloud.postNumber[Int(post) ?? 0])
    }

    }

CodePudding user response:

To prevent the "Index out of range" you can unwrap the property first to avoid the Int(post) ?? 0

 if !fetchPostModel.postName.isEmpty { 
     
     if let postIndex = post {
           Text(fetchPostModel.postName[Int(postIndex)])
                .font(.title)
                .bold()
                .padding()
     }
     
        } else { Text("Loading...").font(.title).bold().padding() }

CodePudding user response:

you can create one extension for that

extension Collection where Indices.Iterator.Element == Index {
    public subscript(safe index: Index) -> Iterator.Element? {
        return (startIndex <= index && index < endIndex) ? self[index] : nil
    }
}

Now it can be applied universally across different collections

Example:

[1, 2, 3][safe: 4] // Array - prints 'nil'

(0..<3)[safe: 4] // Range - prints 'nil'

In your problem, you can use like that

List(fetchPostModel.postsNearby, id: \.self) { post in
    ZStack {
        if let currentPostName = fetchPostModel.postName[safe: post] {
            Text(currentPostName)
                    .font(.title)
                    .bold()
                    .padding()
        } else {
             Text("Loading...").font(.title).bold().padding() 
        }  
    }
    .onAppear {
        fetchFromCloud(postNumber: fetchFromCloud.postNumber[Int(post) ?? 0])
    }
}
  • Related