How does one remove the focus border for a TextField in SwiftUI?In Cocoa, setting the border to "None" in interface builder would remove the border.I've tried using .border with a width of zero, but that does not work. The .border adds another border on top of the focus border.Setting the style also does not do the trick.
Post
Replies
Boosts
Views
Activity
I have a simple SwiftUI view with a TextField in a macOS app. I change the font size of the TextField.The TextField keeps its original height (prior to changing the font) until it has text, when it suddeny jumps to the correct size.One work around is to have placeholder text (even an empty string with just a space in it), but then the cursor looks funny as the cursor keeps the original height.The following code shows the problem:struct ContentView: View {
@State var input: String = ""
var body: some View {
TextField("Type Here", text: $input)
.font(Font.custom("Arial", size: 35))
}
}I've tried changing the height (using frame modifier) of my view, but this shows the smaller TextField in the larger view, until the TextField receives input.Is this a bug in TextField, or am I doing something wrong and either way, does anybody have a workaround/fix for it?
Is it possible to store previous state in a swiftUI view, and if so, how?I have a view that can take an optional value as an input. If this value is nil, then I would like the view to change color (to show something is wrong) and show the previous valid value it had.Below is an example showing what I hope to achieve.The IntView takes an optional Int as an input. It will show "Not a int." in red if it is nil, but in that case, I would like to show the previous valid value, but in red.In the example given, I have a simple ContentView with a TextField in which you can type an int value. The conversion of string to Int (on line 4) will return nil if the string typed in the TextField is not a valid integer.I've tried doing it with state in my IntView but I cannot update the state when the body is computed.struct ContentView: View {
@State var intAsString: String = ""
var body: some View {
let intValue = Int(intAsString)
return VStack {
IntView(value: intValue)
TextField("", text: $intAsString)
}
}
}
struct IntView: View {
var value: Int?
var body: some View {
let foreColor: Color
let text: String
if value == nil {
foreColor = Color.red
text = "Not a int."
} else {
foreColor = Color.primary
text = "\(value!)"
}
return Text(text).foregroundColor(foreColor)
}
}
I am trying to wrap a NSTextView in a NSViewRepresentable SwiftUI view.If text is changed, then updateNSView is called, and the view is correctly updated, but how do I do it the other way around?I want text to be updated when the user types in the NSTextView and I cannot figure out how to do this. The TextView needs a delegate to handle text changed, but the NSViewRepresentable view cannot implment this protocol (because it is not a class).I have a simple ContentView below that illustrates my problem. It contains Text, my TextView and a TextField. All three use the same text binding. If you type in the TextField, then Text and my TextView is updated, but when you type in my TextView, it does not update text, and hence nothing happens. How can I let my TextView work like TextField?struct TextView: NSViewRepresentable {
typealias NSViewType = NSTextView
@Binding var text: String
func makeNSView(context: Self.Context) -> Self.NSViewType {
let view = NSTextView()
return view
}
func updateNSView(_ nsView: Self.NSViewType, context: Self.Context) {
nsView.string = text
}
}
struct ContentView: View {
@State var text: String = ""
var body: some View {
VStack {
Text(text)
Divider()
TextField("", text: $text)
TextView(text: $text)
.frame(maxWidth: .infinity, maxHeight: .infinity)
}
}
}
I have a simple SwiftUI View that is used for a macOS form. The user can select a option to show/hide detail in the form. I am trying to show this detail using an animation, similar to switching between options in the settings app. The form should grow/shrink as the detail is show, and the detail view(s) should animate in.The code below illustrates my problem. Toggling the "Show Detail" toggle shows and hides the "Detail" Text but it also causes the. position of "Main Text" and the toggle itself to jump, and then animate back in to position.I could fix the "jump" by making the form a fixed size, but that is what I do not want.How do I fix this jump in the animation?struct ContentView: View {
@State var showDetail: Bool = true
var body: some View {
VStack {
Toggle(isOn: $showDetail.animation(.easeInOut), label: { Text("Show Detail") })
Divider()
Text("Main Text")
.font(.title)
if showDetail {
Text("Detail")
.font(.subheadline)
}
}
}
}
I am trying to create a standard stepper with text field in swiftUI, but it does not seem to exist.I need something that looks like this:Do I have to create my own view, or is something already available?I tried an HStack with Text, TextField and stepper, but this does not align properly when placed in a form, and the stepper and text field cannot have a binding to the same value.Any ideas on how to implement this?
I have some swiftUI code that used to work, but somewhere, in the recent xcode updates it stoped working.The following simple example demonstrates my problem:struct ContentView: View {
@State var inputText: String = "0"
var body: some View {
let value = Int(inputText) ?? 0
return VStack {
TextField("Enter Value", text: $inputText)
HStack {
ForEach(0..<8, content: { index in
Text("\(self.nibbleFor(value, pos: index))")
if index == 3 { } // <-- works when this line is commented out.
})
}
}
}
func nibbleFor(_ value: Int, pos: Int) -> UInt8 {
return UInt8((value >> (4 * (7-pos))) & 0x0F)
}
}If you run this, you get a text field that asks for a number. As you enter the number, the 8 text fields below it shows the nibble (4-bit) values for the value entered.I use a ForEach on line 10 to generate the 8 nibble values. In my project's code, I also use an "if" statement to add other elements based on the nibble being displayed. My problem is, that as soon as I add any kind of "if", as shown in line 12, then it stops updating the Text in line 11.If the "if" statement on line 12 is comented out, then it works.I can add multiple HStacks, and type the code out as a workaround, but that is not very elegant.Any idea why the if on line 12 breaks the updating of the UI?
I've been playing with my own custom view and Animatable to make it animate.I got it going, but do not understand 100% what happens behind the scenes, and this is never good to help understanding something.Take for example the following simple struct:struct MyRect: Shape {
var scale: Double
var animatableData: Double {
get { return scale }
set { scale = newValue }
}
func path(in rect: CGRect) -> Path {
var path = Path()
let w = min(rect.width, rect.height)*CGFloat(scale)
let scaledRect = CGRect(origin: rect.origin, size: CGSize(width: w, height: w))
path.addRect(scaledRect)
return path
}
}animatableData returns a double, and the getter and setter works with scale. It intuitively makes sense that scale is the property being animated but animatableData does not really have anything to do with scale.Take for example this slight modification where scale is changed from a double to an Int, where 0 represents 0% and 100 represents 100%:struct MyRect: Shape {
var scale: Int
private var scaleAsDouble: Double
init(scale: Int) {
self.scale = scale
scaleAsDouble = Double(scale)
}
var animatableData: Double {
get { return scaleAsDouble }
set { scaleAsDouble = newValue }
}
func path(in rect: CGRect) -> Path {
var path = Path()
let w = min(rect.width, rect.height)*CGFloat(scaleAsDouble)/100.0
let scaledRect = CGRect(origin: rect.origin, size: CGSize(width: w, height: w))
path.addRect(scaledRect)
return path
}
}In this case, my Shape as an integer property that cannot be animated, because it cannot have fractional steps. The solution is to store a doulbe that can have a fractional part, and use it as the animatableData.What I do not get, is how does the framework know to use the scale property? What are the steps that the framework uses when scale is changes from one value to another in order to call the setter on animatableData with the correct values?
I am trying to write a simple view that displays text, two lines at a time. It must be possible for the user to move up and down in the stack of text.In order to make it look good, the items scrolled in and out of the stack must transition in and out from the top or bottom based on the direction the user selected. Below is some test code that demonstrates the problem. It works correctly as long as you keep sliding in one direction, but fails the first time you change direction.It almost works except for when you change direction. The problem is that the .transition is applied to the Text in line 18 based on the current slideUp state variable. It therefore has the wrong value when the state (direction of movement) changes.Can anyone see a simple, elegant way of solving this?import SwiftUI
struct ContentView: View {
private struct DisplayItem {
var id: Int
var text: String
}
private let numVisibleItems = 2
@State private var slideUp: Bool = true
@State private var startIndex: Int = 0
var items: [String] = []
var body: some View {
HStack {
VStack {
ForEach(visibleItems(), id: \DisplayItem.id) { item in
Text("\(item.text)").font(.system(size: 60)).animation(.easeInOut)
.transition(.asymmetric(insertion: AnyTransition.opacity.combined(with: .move(edge: !self.slideUp ? .top : .bottom )),
removal: AnyTransition.opacity.combined(with: .move(edge: self.slideUp ? .top : .bottom ))))
}
}
.animation(.easeInOut(duration: 1.0))
.frame(width: 200, height: 200)
VStack {
Button(action: {
self.slideUp = true
self.startIndex = min(self.items.count-1, self.startIndex + 1)
}, label: { Text("Slide Up") })
Button(action: {
self.slideUp = false
self.startIndex = max(0, self.startIndex - 1)
}, label: { Text("Slide Down") })
}
}
}
private func visibleItems() -> [DisplayItem] {
let endIndex = min(startIndex + numVisibleItems - 1, items.count - 1)
var result = [DisplayItem]()
for i in startIndex...endIndex {
result.append(DisplayItem(id: i, text: items[i]))
}
return result
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
let formatter = NumberFormatter()
formatter.numberStyle = .spellOut
let data = (0..<10).map { formatter.string(from: NSNumber(value: $0))! }
return ContentView(items: data)
}
}
My question is slightly broader, but hopefully this simple use case states the point.I ofthen run in to the problem where my source of truth is a custom type (struct, array of bytes, int, etc.) that I want to edit. I would like to write a view that has a binding to this type so that all the editing logic lives inside this view without the views outside having to worry how it is edited.The simplest example of this is a view that takes a binding to an Int where the user edits it with a TextField. Up to now I've only been able to do this with a custom UI- or NSViewRepresentable implementation. I thought I had a solution today, but it too does not work. It is close enough, that I thought maybe someone can see a path going further.Below is my code. It has an IntView that takes a binding to an Int, and uses state for the strValue. When it first apears, it updates the local state. It then has a method that can be called to update the binding value (this because I cannot get updates as the text field is changing).My contentView creates this view and stores updateValue so that it can be called when the button is pressed. The problem is that view is a value (not a reference), so the intView created in body() is not the same one as that in the .async call (I double-checked this with the print that prints the pointer to each). When updateValue() is called, I get an exception, because I am using the wrong view. The reason for using an .async call is so that I do not change state when body is computed.Can this code somehow be made to work, or is there another solution to writing IntView that takes a binding to an Int?My problem is often more complicated for example when I want to bind to a struct. If I write a custom __ViewRepresentable solution, then I lose a lot of the ease-of-use of swift, and goes back to manual layout, etc.struct IntView: View {
@Binding var value: Int
@State private var strValue: String = ""
var body: some View {
return TextField("Type here", text: $strValue)
.onAppear(perform: { self.strValue = "\(self.value)" })
}
func updateValue() {
value = Int(strValue)!
}
}
struct ContentView: View {
@State var intValue: Int = 12
@State var updateValue: (() -> Void)?
var body: some View {
let intView = IntView(value: $intValue)
withUnsafePointer(to: intView) { print("value at first @\($0)") }
DispatchQueue.main.async {
withUnsafePointer(to: intView) { print("value in async @\($0)") }
self.updateValue = intView.updateValue
}
return VStack {
Text("\(intValue)")
intView
Button(action: {
self.updateValue!()
}, label: { Text("Get Value") })
}
.padding()
.frame(maxWidth: .infinity, maxHeight: .infinity)
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
How do I read the product string of a USB device?I've used IOServiceGetMatchingServices to get to the device that I need, but I want to display a user-friendly name.I've used IOService utility app to look at all the keys for the device, but none of the keys have the product name.Searching the web, I found kUSBProductStringIndex, so seems I should use that somehow, but could not find methods or example code of how to use it.I found Common QA and Roadmap for USB Software Development on Mac OS X which seems to link to some useful example programs, but pretty much all the links in the QA are dead.
I would like to keep my layout the same, and only rotate views in-place when the screen orientation changes.Below is a simple example of what I am trying to acieve. It shows to TestViews horizontally when in portrait mode, and vertically when in landscape mode.I've made sure that the views themselve does not get re-created in the hope that it would only animate the difference in layout between portrait and landscape, but it makes the views very small, and then animate them in from the corner of the screen.What I am trying to acieve, is for each view to effectively rotate by 90 degrees when the orientation changes. Is it possible in swiftUI?[In my example below, I've hacked my AppDelegate to be my model to get rotation notifications from a publisher in it. This needs to be added for the example to work.]struct TestView: View {
var text: String
var body: some View {
ZStack {
RoundedRectangle(cornerRadius: 25.0, style: .continuous)
.foregroundColor(Color(red: 0.2, green: 0.2, blue: 0.2))
Text(verbatim: text)
.font(.system(size: 95))
.foregroundColor(.white)
}.aspectRatio(1.0, contentMode: .fit)
}
}
struct ContentView: View {
@EnvironmentObject var model : AppDelegate
private let testViews: [TestView] = (0...1).map { TestView(text: "\($0)") }
var body: some View {
ZStack {
if !model.isPotrait {
HStack {
VStack {
testViews[0]
testViews[1]
}
}
} else {
VStack {
HStack {
testViews[0]
testViews[1]
}
}
}
}.padding()
}
}
I have a program where I need to handle Edit>Copy when the first responder cannot.
I've added the following to my AppDelegate:
@IBAction @objc func copy(_ sender: Any?) {
// My code here...
}
But Edit>Copy is greyed out on the menu unless a TextField has focus and it has text selected.
How do I get my copy function called when the text field has focus but does not have text selected (or any other case where the current view with focus cannot handle copy)?
I am using a Picker in a macOS app but it does not show the initial value nor the selected value after choosing it.
I can reproduce the problem with this simple View:
struct ContentView: View {
@State private var pickedValue: UInt8 = 1
var body: some View {
Picker("Pick Something: ", selection: $pickedValue) {
Text("One").tag(1)
Text("Two").tag(2)
}
.padding()
}
}
The default mode is Menu mode, and I want to it show "One" when first starting, and then whatever the user selects. It does not show anything.
After selecting something, it also does not show the selection but it does get a check-mark at the selected item if I click on it again.
I've tried different picker styles but they all give the same problem.
I would like to implement a global copy command for my app. The code below is an attempt at achieving this but does not work.
struct ContentView: View {
@State private var name = ""
var body: some View {
VStack {
Text("Hallo \(name)")
TextField("Please enter your name", text: $name)
}
.onCopyCommand(perform: {
print("You got to onCopy")
var items = [NSItemProvider]()
let stringData = "Hallo \(name)".data(using: .utf8)!
items.append(NSItemProvider(item: stringData as NSData, typeIdentifier: kUTTypePlainText as String))
return items
})
}
}
When the user selects something in the TextField, then using the copy menu should copy that text to the clipboard but when it has nothing selected, then I want to copy "Hallo" and the name to the clipboard.
As you can see, I tried using the onCopyCommand but Copy is always grayed out.
Any ideas on how I can enable Copy on the menu, and handle it when the TextField does not have anything selected?