Hello
When I write decimal numbers in my SwiftUI app, the app doesn't detect the comma ( , )
How do I solve it? (I'm using a DecimalPad)
Thank you
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
Hello
When I dismiss my .sheet it is very slow and sometimes it doesn't work
.sheet(isPresented: $myViewi) {
MyView()
}
@Environment(\.presentationMode) var presentationMode
.navigationBarItems(trailing:
Button(action: {
presentationMode.wrappedValue.dismiss()
}) {
Image(systemName: "xmark").font(.title).foregroundColor(.blue)
}
)
How do I fix it?
Thank You
Hello
How do I make the default placeholder of a CustomTextField (that has a double binding) a string (onAppear)
When I run the app on the TextField I see 0 instead of "Input"
Code:
import SwiftUI
struct BMIView: View {
var currencyFormatter: NumberFormatter {
let formatter = NumberFormatter()
formatter.locale = .current
formatter.numberStyle = .decimal
return formatter
}
@State private var height: Double?
var body: some View {
NavigationView{
Form{
Section(header: Text("Enter your height in cm")){
DecimalTextField("Input", value: $height.bound, formatter: currencyFormatter)
}
}
.navigationBarTitle("BMI")
}
}
}
struct DecimalTextField: UIViewRepresentable {
private var placeholder: String
@Binding var value: Double
private var formatter: NumberFormatter
init(_ placeholder: String,
value: Binding<Double>,
formatter: NumberFormatter ) {
self.placeholder = placeholder
self._value = value
self.formatter = formatter
}
func makeUIView(context: Context) -> UITextField {
let textfield = UITextField()
textfield.keyboardType = .decimalPad
textfield.delegate = context.coordinator
textfield.placeholder = placeholder
textfield.text = formatter.string(for: value) ?? placeholder
textfield.textAlignment = .left
let toolBar = UIToolbar(frame: CGRect(x: 0, y: 0, width: textfield.frame.size.width, height: 44))
let doneButton = UIBarButtonItem(title: "Done", style: .done,
target: self, action: #selector(textfield.doneButtonTapped(button:)))
let space = UIBarButtonItem(barButtonSystemItem: UIBarButtonItem.SystemItem.flexibleSpace,
target: nil,action: nil)
toolBar.setItems([space, doneButton], animated: true)
textfield.inputAccessoryView = toolBar
return textfield
}
func updateUIView(_ uiView: UITextField, context: Context) {
// Do nothing, needed for protocol
}
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
class Coordinator: NSObject, UITextFieldDelegate {
var parent: DecimalTextField
init(_ textField: DecimalTextField) {
self.parent = textField
}
func textField(_ textField: UITextField,
shouldChangeCharactersIn range: NSRange,
replacementString string: String) -> Bool {
// Allow only numbers and decimal characters
let isNumber = CharacterSet.decimalDigits.isSuperset(of: CharacterSet(charactersIn: string))
let withDecimal = (
string == NumberFormatter().decimalSeparator &&
textField.text?.contains(string) == false
)
if isNumber || withDecimal,
let currentValue = textField.text as NSString?
{
// Update Value
let proposedValue = currentValue.replacingCharacters(in: range, with: string) as String
let decimalFormatter = NumberFormatter()
decimalFormatter.locale = Locale.current
decimalFormatter.numberStyle = .decimal
// Try currency formatter then Decimal formatrer
let number = self.parent.formatter.number(from: proposedValue) ?? decimalFormatter.number(from: proposedValue) ?? 0.0
// Set Value
let double = number.doubleValue
self.parent.value = double
}
return isNumber || withDecimal
}
func textFieldDidEndEditing(_ textField: UITextField,
reason: UITextField.DidEndEditingReason) {
// Format value with formatter at End Editing
textField.text = self.parent.formatter.string(for: self.parent.value)
}
}
}
// MARK: extension for done button
extension UITextField{
@objc func doneButtonTapped(button:UIBarButtonItem) -> Void {
self.resignFirstResponder()
}
}
extension Optional where Wrapped == Double {
var _bound: Double? {
get{
return self
}
set{
self = newValue
}
}
var bound: Double {
get{
return _bound ?? 0
}
set {
_bound = newValue
}
}
}
The problem might be at line 243
(I found the struct DecimalTextField on the internet)
Thank you for your time
Hello
Everytime I run a project I get this popup: The document “iosfwd” could not be saved. You don’t have permission.
How do I fix it?
Thank you
Hello
I'm trying to use a formatter on a String but it is giving me this error
Cannot convert value of type 'String' to type 'NSNumber' in coercion, is there a simple and short way to fix it?
Here is the code
import SwiftUI
struct TemperatureView: View {
		
		@State private var inputValue = ""
		
		 let inputUnits = [
				"celsius [°C]",
				"kelvin [K]",
				"fahrenheit [°F]"
		]
		let outputUnits = [
				"celsius [°C]",
				"kelvin [K]",
				"fahrenheit [°F]"
	 ]
		@State private var inputUnitValue = 0
		
		@State private var outputUnitValue = 1
		
		
		var after: String{
				var input: Measurement<UnitTemperature>
				var output: String = ""
				
				switch inputUnits[inputUnitValue] {
				case "celsius [°C]": input = Measurement(value: Double(inputValue) ?? 0, unit: .celsius)
				case "kelvin [K]": input = Measurement(value: Double(inputValue) ?? 0, unit: .kelvin)
				case "fahrenheit [°F]": input = Measurement(value: Double(inputValue) ?? 0, unit: .fahrenheit)
				default: input = Measurement(value: Double(inputValue) ?? 0, unit: UnitTemperature.celsius)
				}
				switch outputUnits[outputUnitValue] {
				case "celsius [°C]": output = outputFormatter.string(from: input.converted(to: .celsius))
				case "kelvin [K]": output = outputFormatter.string(from: input.converted(to: .kelvin))
				case "fahrenheit [°F]": output = outputFormatter.string(from: input.converted(to: .fahrenheit))
				default: output = String(describing: input.converted(to: UnitTemperature.celsius))
						
				}
						
				return output
		}
		
		@Environment(\.presentationMode) var presentationMode
		let outputFormatter: MeasurementFormatter = {
						let nf = NumberFormatter()
						nf.locale = Locale.current
						nf.usesSignificantDigits = true
						let mf = MeasurementFormatter()
						mf.numberFormatter = nf
						mf.unitOptions = .providedUnit
						return mf
				}()
				
		var body: some View {
				NavigationView{
						Form{
								Section(header: Text("Enter your Input value")){
												TextField("Have a goal?", text: $inputValue)
														.keyboardType(.decimalPad)
								}
								
								Section(header: Text("Input")){
										Picker("Input values", selection: $inputUnitValue){
												ForEach(0..<inputUnits.count){ item in
														Text(inputUnits[item])
												}
										}
								}
								
								Section(header: Text("Output")){
										Picker("Output values", selection: $outputUnitValue){
												ForEach(0..<outputUnits.count){ item in
														Text(outputUnits[item])
												}
										}
								}
								
								Section(header: Text("Check your Output value")){
										Text("\(after as NSNumber, formatter: outputFormatter)")
								}
								
						}
						.navigationBarTitle("Temperature")
						.navigationBarItems(trailing:
																		Button(action: {
																				presentationMode.wrappedValue.dismiss()
																		}) {
																				Image(systemName: "xmark").font(.title).foregroundColor(.blue)
																		}
						)
				}
		}
		
}
The error is at line 80/81
Thank you for your time
Hello
I made a custom Picker View but I don't have any idea on how to change the background color to grey when I press on one of the options
Here is the code:
struct PickerView: View {
		
		var arr: [String] = ["Easy", "Medium", "Hard"]
		var h: CGFloat = 50
		var w: CGFloat = 320
		
		@ObservedObject var input: UserInput
		var body: some View{
				HStack(spacing: 40){
						ForEach(0..<arr.count){ i in
								HStack(spacing: 25){
										Text(arr[i])
												.bold()
												.onTapGesture {
														switch i{
														case i: input.indi = i
														default: return
														}
														print(i)
												}
										if(i < arr.count - 1){
										Divider()
												.frame(height: 25)
										}
								}
						}
				}.padding()
				.clipShape(RoundedRectangle(cornerRadius: 16, style: .continuous))
				.overlay(
						RoundedRectangle(cornerRadius: 16)
								.stroke(Color.gray, lineWidth: 3)
				)
		}
}
class UserInput: ObservableObject {
		@Published var indi: Int = 0
}
Thank you for your time
Hello
Is there a way to know if the detected finger or face are wrong?
I am using this function:
func authenticate() {
let context = LAContext()
var error: NSError?
if context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) {
let reason = "We need to unlock your data."
context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: reason) { success, authenticationError in
DispatchQueue.main.async {
if success {
self.isUnlocked = true
} else {
userPressedCancel = false
}
}
}
} else {
}
}
Hello
Is there a way to execute a function (even if the app is closed) at a certain time, for example 12:30 AM?
Hello
I am trying to save some data in the Health App from my app, and it is working, the problem is that when I delete that data (already saved) from my app (using the deleteFromHealthKit function) the data is not deleted from the health app. How can I fix this?
Here is the code:
import SwiftUI
import HealthKit
struct ContentView: View {
init() {
//--------
let healthStore = HKHealthStore()
let allTypes = Set([HKObjectType.quantityType(forIdentifier: .dietaryWater)!])
healthStore.requestAuthorization(toShare: allTypes, read: allTypes) { (success, error) in
if !success {
print("success")
}
}
}
func fetchHealthData(date: Date, ml: Double) -> Void {
let healthStore = HKHealthStore()
let quantityType = HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.dietaryWater)
let waterConsumed = HKQuantitySample.init(type: quantityType!, quantity: .init(unit: HKUnit.literUnit(with: .milli), doubleValue: ml), start: date, end: date)
healthStore.save(waterConsumed) { success, error in
if (error != nil) {
print("Error: \(String(describing: error))")
}
if success {
print("Saved: \(success)")
}
}
}
@State var water: [Water] = []
@State private var value: Double = 0
func deleteFromHealthKit(date: Date, ml: Double) {
let healthStore = HKHealthStore()
let quantityType = HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.dietaryWater)
let waterConsumed = HKQuantitySample.init(type: quantityType!, quantity: .init(unit: HKUnit.literUnit(with: .milli), doubleValue: ml), start: date, end: date)
healthStore.delete(waterConsumed) { success, error in
if (error != nil) {
print("Error: \(String(describing: error))")
}
if success {
print("Saved: \(success)")
}
}
}
var body: some View {
NavigationView{
VStack{
Text("Value: \(value)")
.padding()
HStack{
Text("100 ml")
.onTapGesture {
value = 100
}
Text("200 ml")
.onTapGesture {
value = 200
}
}
Button("Add"){
water.append(Water(value: value, date: Date()))
fetchHealthData(date: Date(), ml: value)
}.disabled(value == 0 ? true : false)
.padding()
List{
ForEach(0..<water.count, id: \.self){ i in
HStack{
Text("\(water[i].value)")
Text("\(water[i].date)")
}
.onTapGesture {
deleteFromHealthKit(date: water[i].date, ml: water[i].value)
water.remove(at: i)
}
}
}
}
}
}
}
struct Water: Identifiable {
var id = UUID()
var value: Double
var date: Date
}
Thank you
Hello
Is there a way to share data stored in CloudKit and CoreData between iOS and watchOS in SwiftUI? I am using the same CoreData file both, and I am using the same PersistenceController file both, and I am using the same CloudKit container for both.
I tried adding the App Groups capability to all the targets, but it is not working.
(I already enabled iCloud capability, Push notification capability and background Modes capability for both iOS and WatchOS)
PersistenceController:
struct PersistenceController {
static let shared = PersistenceController()
static var preview: PersistenceController = {
let result = PersistenceController(inMemory: true)
let viewContext = result.container.viewContext
do {
try viewContext.save()
} catch {
let nsError = error as NSError
fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
}
return result
}()
let container: NSPersistentCloudKitContainer
init(inMemory: Bool = false) {
container = NSPersistentCloudKitContainer(name: "Test7")
if inMemory {
container.persistentStoreDescriptions.first!.url = URL(fileURLWithPath: "/dev/null")
}
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error as NSError? {
fatalError("Unresolved error \(error), \(error.userInfo)")
}
})
container.viewContext.automaticallyMergesChangesFromParent = true
container.viewContext.mergePolicy = NSMergeByPropertyStoreTrumpMergePolicy
}
}
View:
struct ContentView: View {
@FetchRequest(
entity: Item.entity(),
sortDescriptors: []
) var items: FetchedResults<Item>
@Environment(\.managedObjectContext) private var context
var body: some View {
NavigationView{
List {
ForEach(items) { item in
Text("Item at \(item.date!)")
}
.onDelete(perform: deleteItems)
}
.toolbar {
Button {
addItem()
} label: {
Image(systemName: "plus")
}
}
}
}
private func addItem() {
withAnimation {
let newItem = Item(context: context)
newItem.date = Date()
do {
try context.save()
} catch {
let nsError = error as NSError
fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
}
}
}
private func deleteItems(offsets: IndexSet) {
withAnimation {
offsets.map { items[$0] }.forEach(context.delete)
do {
try context.save()
} catch {
let nsError = error as NSError
fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
}
}
}
}
Thank you
Hello
How can I set up local notifications that repeat every X minutes from a certain hour to another hour.
For example, I want to receive a notification every 60 minutes starting from 12:00 AM to 10:00 PM?
func scheduleNotifications() {
let content = UNMutableNotificationContent()
content.title = "App"
content.subtitle = "App"
content.sound = UNNotificationSound.default
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 60, repeats: true)
let request = UNNotificationRequest(identifier: UUID().uuidString, content: content, trigger: trigger)
UNUserNotificationCenter.current().add(request)
}
With this code I can schedule a notification every minute, however, I cannot decide from what time it should start or when it stops.
Any ideas?
Thank you!
Hello
In my previous post I asked:
https://developer.apple.com/forums/thread/689720
(Read my previous post before continuing, please)
My question now is, if I compare Dates between each other will they be formatted or not, and how would I fix this?
Thank You
Hello
In my app I have a list of items in a ForEach and at the end of the ForEach there is a .onDelete. (This is in a View that I called AllHistoryView)
The items are represented by a CoreData NSManagedObject that I called LifetimeInputs with 3 properties:
date: Date, imageTemplate: String, valori: Double
The problem is that, when I add (in a different View) an item with the date of tomorrow and then I add another to item with the date of today and then go to the AllHistoryView where there are all the items and delete slowly the item with date of tomorrow (especially at the end of the swipe action) instead of deleting the item that I swiped it deletes the on before it, how can I solve this problem?
Here is the AllHistoryView code:
import SwiftUI
import CoreData
struct AllHistoryView: View {
@Environment(\.managedObjectContext) var viewContext
@FetchRequest(entity: LifetimeInputs.entity(), sortDescriptors: [NSSortDescriptor(keyPath: \LifetimeInputs.date, ascending: true)], animation: .default) var lifetimeInputsModel: FetchedResults<LifetimeInputs>
@State private var text: String = ""
@State private var ascending: Bool = true
@State var sortDescriptor: NSSortDescriptor = NSSortDescriptor(keyPath: \LifetimeInputs.date, ascending: true)
@Environment(\.dynamicTypeSize) var dynamicTypeSize
var size: CGFloat{
if UIDevice.current.userInterfaceIdiom == .phone {
switch dynamicTypeSize {
case .xSmall: return 11
case .small: return 13
case .medium: return 15
case .large: return 17
case .xLarge: return 19
case .xxLarge: return 21
case .xxxLarge: return 23
default: return 23
}
} else {
switch dynamicTypeSize {
case .xSmall: return 13
case .small: return 15
case .medium: return 17
case .large: return 19
case .xLarge: return 21
case .xxLarge: return 23
case .xxxLarge: return 25
case .accessibility1: return 27
case .accessibility2: return 29
default: return 29
}
}
}
var body: some View {
theView()
}
@ViewBuilder
func theView() -> some View{
NavigationView{
if !lifetimeInputsModel.isEmpty{
List{
SectionList(sortDescripter: sortDescriptor, text: $text)
.environment(\.managedObjectContext, viewContext)
.onChange(of: ascending, perform: { _ in
if ascending {
withAnimation {
sortDescriptor = NSSortDescriptor(keyPath: \LifetimeInputs.date, ascending: true)
}
} else {
withAnimation {
sortDescriptor = NSSortDescriptor(keyPath: \LifetimeInputs.date, ascending: false)
}
}
})
}
.searchable(text: $text, placement: .navigationBarDrawer, prompt: "Quantity or date".localized())
.navigationBarTitle("History", displayMode: .inline)
.toolbar{
ToolbarItem(placement: .automatic) {
Image(systemName: "arrow.up.arrow.down.circle")
.foregroundColor(.primary)
.font(.system(size: size))
.rotation3DEffect(.degrees(ascending ? 0 : 180), axis: (x: 1, y: 0, z: 0))
.opacity(0.5)
.onTapGesture {
ascending.toggle()
}
}
}
} else{
VStack{
Text("No Data".localized())
.font(.largeTitle)
.fontWeight(.semibold)
.foregroundColor(.secondary)
}
.padding(.bottom)
.navigationBarTitle("History", displayMode: .inline)
}
}
}
}
struct SectionList: View {
@Environment(\.managedObjectContext) var viewContext
@FetchRequest var lifetimeInputsModel: FetchedResults<LifetimeInputs>
@Binding var text: String
init(sortDescripter: NSSortDescriptor, text: Binding<String>) {
let request: NSFetchRequest<LifetimeInputs> = LifetimeInputs.fetchRequest()
request.sortDescriptors = [sortDescripter]
_lifetimeInputsModel = FetchRequest<LifetimeInputs>(fetchRequest: request)
self._text = text
}
@FetchRequest(entity: Limit.entity(), sortDescriptors: [NSSortDescriptor(keyPath: \Limit.date, ascending: true)], animation: .default) var limit: FetchedResults<Limit>
@Environment(\.dynamicTypeSize) var dynamicTypeSize
var size: CGFloat{
if UIDevice.current.userInterfaceIdiom == .phone {
switch dynamicTypeSize {
case .xSmall: return 11
case .small: return 13
case .medium: return 15
case .large: return 17
case .xLarge: return 19
case .xxLarge: return 21
case .xxxLarge: return 23
default: return 23
}
} else {
switch dynamicTypeSize {
case .xSmall: return 13
case .small: return 15
case .medium: return 17
case .large: return 19
case .xLarge: return 21
case .xxLarge: return 23
case .xxxLarge: return 25
case .accessibility1: return 27
case .accessibility2: return 29
default: return 29
}
}
}
@StateObject var lifeTimeInputsViewModel = LifeTimeInputsViewModel()
var body: some View {
Section{
ForEach(lifetimeInputsModel.filter { text.isEmpty || "\($0)".contains(text) }){ lifetimeInputs in
HStack{
Text("\(lifetimeInputs.valori, specifier: format(unita: !limit.isEmpty ? limit[0].unita ?? ml : ml)) \(!limit.isEmpty ? limit[0].unita ?? ml: ml)")
.font(.system(size: size))
Spacer()
Text("\(dateFormatter.string(from: lifetimeInputs.date ?? Date()))")
.font(.system(size: size))
}
}
.onDelete(perform: { offsets in
lifeTimeInputsViewModel.deleteItems(offsets: offsets)
})
} header: {
Text("History".localized()).font(.system(size: size - 4))
}
}
}
Thank You very much!
Hello
@FetchRequest(
entity: Book(),
sortDescriptors: []
) var books: FetchedResults<Book>
How can I get notified when books changes?
I was thinking about putting this...
.onReceive(NotificationCenter.default.publisher(for: .NSManagedObjectContextDidSave), perform: { _ in})
... in my main View but this would notify me if anything gets saved and that is not what I want. I want to get notified just if a certain FetchRequest changes (in this case books)?
And in another thread I was told to use...
.onRecevie(books.publisher){ _ in
....
}
...however using this code publishes each member of the sequence as a separate element, I want it to publish just once?
Thank You!
Hello
I created a @propertyWrapper to limit the number a variable can reach. I tried it in a SwiftUI view with a button that increases the value of the variable and it works, the variable stops at the maximum number set in the initializer. However if I try it with a Textflied it doesn't work, if I insert a higher number than the one set nothing happens, it makes me do it. How can I solve this problem, I know the problem has to do with Binding but I don't know exactly what it is, here is the code:
import SwiftUI
struct ContentView: View {
@Maximum(maximum: 12) var quantity: Int
var body: some View {
NavigationView{
Form{
TextField("", value: $quantity, format: .number, prompt: Text("Pizza").foregroundColor(.red))
Button {
quantity += 1
} label: {
Text("\(quantity)")
}
}
}
}
}
@propertyWrapper
struct Maximum<T: Comparable> where T: Numeric {
@State private var number: T = 0
var max: T
var wrappedValue: T {
get { number }
nonmutating set { number = min(newValue, max) }
}
var projectedValue: Binding<T> {
Binding(
get: { wrappedValue },
set: { wrappedValue = $0 }
)
}
init(maximum: T){
max = maximum
}
}
extension Maximum: DynamicProperty {
}
Thank You for your time