In my SwiftUI app, I have a data from an array.
While scrolling through the list, the cells are being recycled, which is great.
However, I'm puzzled because it seems that the data isn't being refetched as I scroll, which is contrary to what I expected.
I want to understand why the data isn't being refetched for recycled cells and if this is expected behavior.
class HistoryViewModel: ObservableObject {
@Published var filteredContacts: [HistoryData] = []
func updateFilteredContacts() {
filteredContacts = HistoryCallDataService().savedEntities
if self.searchText.isEmpty {
self.filteredContacts = filteredContacts
} else {
self.filteredContacts = filteredContacts.filter { contact in
contact.firstName?.localizedCaseInsensitiveContains(self.searchText) ?? false ||
contact.lastName?.localizedCaseInsensitiveContains(self.searchText) ?? false ||
contact.telephone?.localizedCaseInsensitiveContains(self.searchText) ?? false
}
}
}
The List:
List{
ForEach(vm.filteredContacts.reversed()) { item in
HStack{
VStack(alignment: .leading){
Text("\(item.firstName ?? "N/A") \(item.lastName ?? "N/A" )")
.fontWeight(.semibold)
Text("\(item.telephone ?? "N/A")")
.fontWeight(.medium)
.padding(.top,1)
}
Spacer()
VStack(alignment: .trailing){
Text("\(item.time ?? "N/A")")
.fontWeight(.medium)
Text("\(item.callHidden ? "Hidden" : "Normally ")")
.foregroundColor(item.callHidden ? Color.theme.red : Color.theme.black)
.fontWeight(.bold)
.padding(.top,1)
}
}
}
}
i attach image:
https://im.ezgif.com/tmp/ezgif-1-db6ebe2a2e.gif
[https://im.ezgif.com/tmp/ezgif-1-db6ebe2a2e.gif)
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
I'm facing an issue in my iOS app's architecture involving CoreData, the HistoryCallDataService class, and the HistoryViewModel. I'm hoping someone can help shed light on the problem I'm encountering.
Problem Description:
I'm working with CoreData and have an array that I'm managing through the HistoryCallDataService class.
class HistoryCallDataService {
private let container: NSPersistentContainer
private let containerName = "CallHistoryData"
private let entityName = "HistoryData"
@Published var savedEntities: [HistoryData] = []
I'm observing changes in the savedEntities property of the HistoryCallDataService class using the historyDataService.$savedEntities publisher. When the app starts, the array is updated correctly. However, if I add new content, the savedEntities array updates, but the historyArray in the HistoryViewModel does not reflect these changes.
import Foundation
import Combine
class HistoryViewModel: ObservableObject {
@Published var searchText:String = ""
@Published var historyArray: [HistoryData] = []
private let historyDataService = HistoryCallDataService()
private var cancellables = Set<AnyCancellable>()
var selectedContact: HistoryData? = nil
@Published var filteredContacts: [HistoryData] = []
init(){
addSubscribers()
}
func addSubscribers(){
historyDataService.$savedEntities
.debounce(for: 1.0, scheduler: RunLoop.main)
.sink { [weak self] (returnData) in
guard let self = self else { return }
self.historyArray = returnData
self.updateFilteredContacts()
}
.store(in: &cancellables)
}
func updateFilteredContacts() {
if searchText.isEmpty {
filteredContacts = historyArray
} else {
filteredContacts = historyArray.filter { contact in
contact.firstName?.localizedCaseInsensitiveContains(searchText) ?? false ||
contact.lastName?.localizedCaseInsensitiveContains(searchText) ?? false ||
contact.telephone?.localizedCaseInsensitiveContains(searchText) ?? false
}
}
}
The view:
private var contactList: some View{
List{
ForEach(vm.filteredContacts) { item in
HStack{
VStack(alignment: .leading){
Text("\(item.firstName ?? "N/A") \(item.lastName ?? "N/A" )")
.fontWeight(.semibold)
Text("\(item.telephone ?? "N/A")")
.fontWeight(.medium)
.padding(.top,1)
}
Spacer()
VStack(alignment: .trailing){
Text("\(item.time ?? "N/A")")
.fontWeight(.medium)
Text("\(item.callHidden ? "Hidden" : "Normally ")")
.foregroundColor(item.callHidden ? Color.theme.red : Color.theme.black)
.fontWeight(.bold)
.padding(.top,1)
}
}
.onTapGesture {
vm.selectedContact = item
showingCallAlert.toggle()
}
.listRowBackground(vm.selectedContact?.telephone == item.telephone && showingCallAlert ? Color.theme.gray : nil)
}
.onDelete(perform: { indexSet in
for index in indexSet {
let contactToDelete = vm.filteredContacts[index]
vm.delete(entity: contactToDelete)
}
})
}
.onChange(of:
vm.searchText) { _ in
vm.updateFilteredContacts()
}
.onChange(of: scenePhase) { newPhase in
if newPhase == .active {
print("Active")
vm.updateFilteredContacts()
}
}
.lineLimit(1)
.listStyle(.plain)
}
If anyone has encountered a similar situation or has insights into what might be causing this behavior, I would greatly appreciate your guidance. Thank you in advance for your help!
I want to use Admob in my application - an ad when opening the application only!
After many searches, some of which I did not find an answer but i found:
As of December 8, 2020, Apple has made it mandatory for developers to release what data is being collected and what it's being used for. If developers don't comply, they won't be able to publish new apps or release updates for current apps.
My questions is:
According to Apple policies, can Admob be used in the application?
and to upload the application, what data does Admob collect and what i need to mark in app store connect?
Topic:
App Store Distribution & Marketing
SubTopic:
App Store Connect
Tags:
App Store
App Store Connect
Privacy
AdSupport
I have a problem with the search, it doesn't search for each letter individually,
these only if it is word is together, for example:
I search Kate it will find but if I type Kae (that still has the letters in it), he won't find it, why?
filteredData = contacts.filter {name in
return name.firstName.lowercased().contains(searchText.lowercased()) || name.lastName.lowercased().contains(searchText.lowercased()) || name.telephone.removeCharacters(from: CharacterSet.decimalDigits.inverted).lowercased().contains(searchText.lowercased())
}
i attach screenshot
it want to save QRCode to galley and i get the image but why it not save??
func saveImageQRCode(from string: String) {
filter.message = Data(string.utf8)
if let outputImage = filter.outputImage {
if context.createCGImage(outputImage, from: outputImage.extent) != nil {
// let ge = UIImage(cgImage: cgimg)
let transform = CGAffineTransform(scaleX: 10, y: 10)
let scaledCIImage = outputImage.transformed(by: transform)
let uiimage = UIImage(ciImage: scaledCIImage)
let imageData = uiimage.pngData()!
let docDir = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
let dataNow = "\(Date.now).png"
let imageURL = docDir.appendingPathComponent(dataNow)
try! imageData.write(to: imageURL)
_ = UIImage(contentsOfFile: imageURL.path)!
UIImageWriteToSavedPhotosAlbum(uiimage, nil, nil, nil)
}
}
}
i do this code:
struct TextView: View {
@ObservedObject var service = Service()
@State private var text: String = ""
@FocusState var isInputActive: Bool
var body: some View {
ZStack{
Color(red: 242 / 255, green: 242 / 255, blue: 247 / 255)
.edgesIgnoringSafeArea(.top)
VStack {
Text("QRCode Text")
.multilineTextAlignment(.center)
.font(.system(size: 30, weight: .heavy, design: .default))
.padding(.top, 16.0)
TextField("Enter Text", text: $text)
.textFieldStyle(RoundedBorderTextFieldStyle())
.border(Color.white)
.fixedSize(horizontal: false, vertical: true)
.multilineTextAlignment(.center)
.padding()
.frame(width: 350, height: 80)
.background(Rectangle().fill(Color.white).shadow(radius: 20))
.cornerRadius(30)
.frame(height: 100)
.focused($isInputActive)
.toolbar {
ToolbarItemGroup(placement: .keyboard) {
Spacer()
Button("Done") {
isInputActive = false
}
}
}
Image(uiImage: service.generateQRCode(from: "\(text)"))
.interpolation(.none)
.resizable()
.padding(2.0)
.scaledToFill()
.frame(width: 250, height: 250)
.fixedSize(horizontal: false, vertical: true)
.multilineTextAlignment(.center)
.frame(width: 350, height: 350)
.background(Rectangle().fill(Color.white).shadow(radius: 20))
.cornerRadius(30)
Button("Save QRCode") {
print("save")
}
.padding(.vertical, 10.0)
.padding(.horizontal, 100.0)
.background(Color.blue)
.cornerRadius(20)
.foregroundColor(Color.white)
.frame(height: 100)
Spacer()
}
}
}
}
and when i click on textfield and keyboard up, it up all view, why?
i have coredata and i want to add bool Optional but i get error:
import CoreData
@objc(HistoryData)
class HistoryData: NSManagedObject {
@NSManaged var firstName: String
@NSManaged var lastName: String
@NSManaged var telephone: String
@NSManaged var time: String
@NSManaged var callHidden: Bool? // Here the error
}
Error:
Property cannot be marked @NSManaged because its type cannot be represented in Objective-C
in xcdatamodeld it selected Optional but it not do it..
why?
How i can open Location services direct to my app?
I want it to go to the screen where the user chooses allow location or not can be enabled in the app..
UIApplication.shared.open(URL(string: "App-prefs:LOCATION_SERVICES")!)
this code open for me only the location services but how i can open location setting to my app?
I have the code:
if let url = URL(string:"tel://\(String(describing: Util.checkForNullString(contactNo)))"), UIApplication.shared.canOpenURL(url){
if #available(iOS 10, *) {
UIApplication.shared.open(url)
} else {
UIApplication.shared.openURL(url)
}
}
how I can detected if user calling or dismiss?
how i make a List like at swiftui at storyboard?
the UITableView not the same..
look image:
https://i.ibb.co/Qn69TRR/Untitled.png
how i can do List like a swiftui in storyboard?
i maked core data and i fetch all data to List.
all working (add ,delete) but! if the app inactive (to background) and i open again to delete a row it crashes with error:
"Thread 1: "An NSManagedObjectContext cannot delete objects in other contexts."
struct HistoryView: View {
@State private var history: [HistoryList] = [HistoryList]()
let coreDM: CoreDataManager
var dateFormatter: DateFormatter {
let formatter = DateFormatter()
formatter.dateFormat = "MM-dd-yyyy HH:mm"
return formatter
}
private func populateHistory(){
history = coreDM.getAllHistory()
}
var body: some View {
NavigationView{
VStack {
if !history.isEmpty {
List {
ForEach(history, id: \.self) { historyList in
HStack {
Text(dateFormatter.string(from: historyList.dateFlash ?? Date(timeIntervalSinceReferenceDate: 0)))
Text("\(historyList.timerFlash)s")
.multilineTextAlignment(.trailing)
.frame(maxWidth: .infinity, alignment: .trailing)
}
}.onDelete(perform: { indexset in
indexset.forEach { index in
let history = history[index]
coreDM.deleteHistory(history: history)
populateHistory()
}
})
}.refreshable {
populateHistory()
print("## Refresh History List")
}
} else {
Text("History Flashlight is Empty")
}
}
.onAppear {
populateHistory()
print("OnAppear")
}
}.navigationTitle("History Flashlight")
.navigationBarTitleDisplayMode(.inline)
}
}
struct HistoryView_Previews: PreviewProvider {
static var previews: some View {
HistoryView(coreDM: CoreDataManager())
}
}
why?
why the setTorchModeOn not working? it not change the level torch
guard let device = AVCaptureDevice.default(for: .video) else { return }
if device.hasTorch {
do {
try device.lockForConfiguration()
try device.setTorchModeOn(level: 0.1)
if on == true {
device.torchMode = .on
} else {
device.torchMode = .off
}
device.unlockForConfiguration()
} catch {
print("Torch could not be used")
}
} else {
print("Torch is not available")
}
}
i have NavigationView in my code
i do this for button it Navigation
Button{
print("")
}label: {
Image(systemName: "list.dash")
.foregroundColor(.gray)
}
}
how i can navigate to another view when user click the button??
i created a list with colors and i want when the user click red so all the screen was background red, if user click green so full background is green...
i don't know why but the var not change..
var body: some View {
NavigationView {
List {
Section {
ScreenColorButtons(text: "Red", color: .red)
ScreenColorButtons(text: "Green", color: .green)
ScreenColorButtons(text: "Blue", color: .blue)
}
}
}
}
}
struct ScreenColorButtons: View {
@State static var screenSelected: Color = Color.red
var text: String
var color: Color
var body: some View{
Button(action: {
ScreenColorButtons.screenSelected = color
print(ScreenColorButtons.screenSelected)
}, label: {
NavigationLink(text){}
})
}
}
the ScreenColorView:
struct ScreenColorView: View {
@Environment(\.presentationMode) var presentationMode
var body: some View {
Color.ScreenColorButtons.screenSelected
}
}
why the var not change and error to background??? thank for answer
why when i Swipe the table view the swipe not disappear?
see screenshot
It just gets stuck like that and won't come back, why?
func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
let item = realArray[indexPath.row]
let callAction = UIContextualAction(style: .normal, title: "Call Private", handler: { (action, view, success) in
self.service.dialNumber(number: item.telephone, prefixNumber: true)
self.service.setupCallerId(firstName: item.firstName, lastName: item.lastName, telephone: item.telephone)
})
callAction.backgroundColor = .systemGreen
let configuration = UISwipeActionsConfiguration(actions: [callAction])
return configuration
}