I had added a formatter for decimal, but I deleted this and also change the formatter on the textfield. I got always this errormessage and after a while it will hide.
I have this formatter:
let formatter: NumberFormatter = {
let formatter = NumberFormatter()
formatter.numberStyle = .decimal
return formatter
}()
And this is the code where the error would apear:
VStack {
HStack {
Text("Raddurchmesser")
TextField("Durchmesser", value: $durchmesser, formatter: formatter)
.textFieldStyle(DecimalTextFieldStyle(icon: Image(systemName: "pencil"), framesize: 110))
}
}
.onTapGesture {
hideKeyboard()
I restarted Xcode, also restarted the computer. I make "Clean Build Folder"
The build would be successfully. But where I have a chance to find out, why this line come up.
The decimalFormatter is also in no line of Code.
In Xcode go to the top menu and select: Product -> Clear All issues.
This is sometimes needed when Xcode can't "forget" things like this.
Related
I'm curious, is a mix of Label and Text Views supported as the contents of a Picker? I'm seeing some visual glitches around the icon that suggests it is not.
In the example below, the picker initially appears correctly.
Selecting "First Item" works as expected.
But reverting to the original state, by selecting "None", results in a label that still retains a phantom icon from the previous selection.
Can anyone suggest a good workaround, if this is a bug? I tried using a label with an empty string for the systemImage (Label("None", systemImage: "").tag(0)). I also tried using a Label instead of the text, but without icon (Label("None", systemImage: "house").labelStyle(.titleOnly).tag(0)). In both cases the phantom icon was still there.
Here is the full code to illustrate the problem:
struct LabelAndTextInPicker: View {
#State private var selection = 0
var body: some View {
Form {
Picker("Choice", selection: $selection) {
Text("None").tag(0)
Label("First Item", systemImage: "1.circle").tag(1)
Label("Second Item", systemImage: "2.circle").tag(2)
}
.pickerStyle(.menu)
}
}
}
It does look like a bug. As a workaround try this, works for me:
Label {
Text("None")
} icon: {
Image(uiImage: UIImage())
}.tag(0)
Why is my SwiftUI Swipe Action behaving like this?
I don't now how to add a GIF in stack overflow so here is a imagur link https://imgur.com/a/9MqjIgX.
If you don't want to click on external links here is a image from the GIF:
My View:
struct MyView: View {
#State var shops = [Shop.empty(), Shop.empty(), Shop.empty(), Shop.empty(), Shop.empty()]
var body: some View {
NavigationView {
List($shops) { $shop in
Text(shop.name)
.swipeActions {
Button {
shop.toggleFavourite()
} label: {
Image(systemName: "star")
}
}
}
}
}
}
the shop struct:
struct Shop: Hashable, Identifiable {
var id: UUID
var favourite: Bool
init(id: UUID){
self.id = id
self.favourite = UserDefaults.standard.bool(forKey: id.uuidString)
}
mutating func toggleFavourite() {
favourite.toggle()
UserDefaults.standard.set(favourite, forKey: id.uuidString)
}
static func empty() -> Shop{
Shop(id: UUID())
}
}
But I can't sadly I can't give you a working example, because I tried to run this code in a fresh app and it worked, without the Bug. On the same device. And I don't understand why, because I also put this view in the root of my old project, just for testing, and the bug stayed there.
I was able to figure out, that if I commented out this line:
UserDefaults.standard.set(favourite, forKey: id.uuidString)
my code would work. But unfortunately I can't just leave out this line of code.
I tried several things, including wrapping this line into DispatchQueue.main.async {} and DispatchQueue.main.sync {}, same with the DispatchQueue.global(). I also added delays. Short delays wouldn't work at all (under .5 seconds) and longer delays would just delay the view bug.
Of course I also tried wrapping this line into a separate function, and so on.
There are two mayor points, why I'am so confused:
Why is the line, that sets this to the Userdefaults even influencing the view? I mean I checked with a print statement, that the initializer, which is the only section in my code that checks this Userdefaultvalue, only gets called when the view gets initialized.
Why does the code work in a different project?
I know since I can't provide a working example of my bug it's hard for you to figure out whats wrong. If you have any ideas, I would be very happy!
I'm looking to show an Alert without needing to press a button, i.e. programmatically. In Swift 5 / SwiftUI in 2022.
Searching has shown me this
let alert = UIAlertController(title: "alert", message: "message", preferredStyle: UIAlertController.Style.alert)
self.present(alert, animated: true, completion: nil)
When trying the above code it has issue with the nil in the completion block, but when changing it to curlys it says the view file doesn't have present. Looks to not be for SwiftUI.
How can I show an Alert in Swift 5/SwiftUI without needing a button press?
Following this Link I was able to get the following code working
struct ContentView: View {
// pass this var as binding to other views
#State var showAlert = false
func notificationReminder() -> Alert {
Alert(
title: Text("Notifications Required"),
message: Text("Please authorize notifications by going to Settings > Notifications > Remindr"),
dismissButton: .default(Text("Okay")))
}
var body: some View {
VStack {
Text("this is my main view")
}
.alert(isPresented: self.$showAlert,
content: { self.notificationReminder() })
}
}
using code I then flipped showAlert
Using this code which compiles and seems to run ok as I can tap the add button and create new items) I get an error showing in Xcode. How do I get rid of the annoying error?
I have tried deleting the build folder, restarting Xcode to no avail.
import SwiftUI
import CoreData
struct ContentView: View {
#Environment(\.managedObjectContext) private var viewContext
#FetchRequest(
sortDescriptors: [],
animation: .default)
private var items: FetchedResults<Medicine> // Cannot find type ‘Medicine’ in scope
var body: some View {
VStack {
List {
ForEach(items) { item in
Text("Start at \(item.start!, formatter: itemFormatter)")
}
.onDelete(perform: deleteItems)
}
HStack {
EditButton()
Spacer()
Button(action: addItem, label: {
Text("Add")
})
}
}
}
As was pointed out, this is a pre-compiler issue which you will notice in your editor.
After you make sure that the .xcdatamodeld file is saved and that its Codegen property is set to Class Definition, you should be able to just build (Product -> Build or ⌘-B).
Another caveat: look at any possible additional error messages. In my case, I had inadvertently added an attribute to an entity (I guess a slip of mouse) which had no type (such as String, Int16, etc.). This error prevented the data model file from being processed and produced the "cannot find in scope" error. Fixing the data model also fixed the downstream error.
I have a SwiftUI view that has a Form that contains a DatePicker:
struct GettingUpTimeSettingView: View {
#State private var viewModel = GettingUpTimeSettingViewModel()
var body: some View {
VStack {
Form {
Spacer()
Text(viewModel.questionString)
.accessibility(identifier: "Question")
Spacer()
DatePicker("Alarm Time",
selection: $viewModel.gettingUpTime,
displayedComponents: .hourAndMinute)
.accessibility(identifier: "Time")
.animation(.easeInOut)
Spacer()
Text(viewModel.explanationString)
.accessibility(identifier: "Explanation")
}
}
}
}
And an XCTestCase class for UI Testing:
class SleepyGPIntroUITests: XCTestCase {
private var app: XCUIApplication!
override func setUp() {
continueAfterFailure = false
app = XCUIApplication()
app.launch()
greeting = app.staticTexts["Greeting"]
}
override func tearDown() {
app = nil
}
func test_InitialScreen_ChangesTo_GettingUpScreen_Automatically() {
//Given
let questionText = "What time do you want to get up?"
let explanationText = "This should be the same time every day, including at weekends and on days off. Our best chance of great sleep comes when we have a regular routine."
let timeText = "7:00am"
let question = app.staticTexts["Question"]
let explanation = app.staticTexts["Explanation"]
let time = app.staticTexts["Time"]
//When
_ = time.waitForExistence(timeout: 2)
//Then
XCTAssertFalse(greeting.exists)
XCTAssertEqual(question.label, questionText, "Should show question at top of view")
XCTAssertEqual(explanation.label, explanationText, "Should show explanation in view")
XCTAssertEqual(time.label, timeText, "Should show the correct default time")
}
When I run the test, it fails and gives me this message:
Failed to get matching snapshot: No matches found for Elements matching predicate '"Time" IN identifiers' from input {(
StaticText, identifier: 'Question', label: 'What time do you want to get up?',
StaticText, identifier: 'Explanation', label: 'This should be the same time every day, including at weekends and on days off. Our best chance of great sleep comes when we have a regular routine.'
)}
I'm not sure whether this is down to the DatePicker() being contained in a Form, or whether it's because I'm not using the correct XCUIElementQuery to find it?
When I move the DatePicker outside the Form, I can find it, but only by using its label, and not its accessibility identifier.
The accessibility identifiers are working fine for the Text objects.
I can also find it using
app.datePickers.firstMatch
when it's outside the form, but not when it's contained within it.
I've found this answer that describes some odd behaviour when SwiftUI objects are contained in forms, but still haven't managed to solve my problem.
Many thanks.
tl:dr Can't get XCUIElementQuery to return DatePicker element when UITesting if the DatePicker is contained in a SwiftUI Form.
I've found the answer, for anyone that's interested.
First of all, a piece of basic advice, if you're struggling to find out how to access an element when UI testing in XCode, just use the record function and access the element manually.
That's what I did, and it showed me that before a DatePicker() is tapped on in SwiftUI, it actually shows as a button, so to access it in the example above I used this code:
let alarmTimeButton = app.tables.buttons["Time"]