Post not yet marked as solved
I'm building an app to manage and edit some files. To do that, I want to open the files in place dropping them into a view. I cannot find a way to obtain the file URL after the drop operation. If I constrain the file types to .fileURL, the drop frame doesn't activate. If I use .data, I get the file and not the path, which is what I want.
Any way to do this the SwiftUI way?
.onDrop(of: [.fileURL], isTargeted: $dragOver) { providers -> Bool in
providers.first?.loadDataRepresentation(forTypeIdentifier: "public.file-url", completionHandler: { (data, error) in
if let data = data {
print(data.description)
}
})
return true
}
Post not yet marked as solved
I'm using a custom UITextField inside a UIViewRepresentable, to have a Textfield with only a decimalpad and a custom keyboard toolbar. The goal is to add to the toolbar basic things such as inserting a minus, an E, etc... at the current cursor position.
I've noticed that if I change a string @State var, the keyboard behaves as expected, but if the string is inside an array (for example an array of strings), the inputs made from the inputAccessoryView do not save and get erased if you tap on the next textfield UNLESS pressing an actual key of the keyboard afterwards.
I leave here some code as its easy to reproduce:
import SwiftUI
struct ContentView: View {
@State var text = ""
@State var array = ["",""]
var body: some View {
List {
//Here the text saves
DataTextField("This saves", text: $text)
//If its inside an array, after changing the field and if the last key pressed was the button above keyboard, the value erases
DataTextField("Does not save", text: $array[0])
DataTextField("Does not save", text: $array[1])
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
struct DataTextField: UIViewRepresentable {
private var placeholder: String
@Binding var text: String
init(_ placeholder: String, text: Binding<String>) {
self.placeholder = placeholder
self._text = text
}
func makeUIView(context: Context) -> UITextField {
let textfield = UITextField()
textfield.keyboardType = .decimalPad
textfield.delegate = context.coordinator
textfield.placeholder = placeholder
let toolBar = UIToolbar(frame: CGRect(x: 0, y: 0, width: textfield.frame.size.width, height: 44))
let minusButton = UIBarButtonItem(title: "-", style: .plain, target: self, action: #selector(textfield.minusButtonTapped(button:)))
let scientificButton = UIBarButtonItem(title: "E", style: .plain, target: self, action: #selector(textfield.scientificButtonTapped(button:)))
toolBar.items = [minusButton, scientificButton]
toolBar.setItems([minusButton, scientificButton], animated: true)
textfield.inputAccessoryView = toolBar
textfield.borderStyle = .roundedRect
textfield.textAlignment = .right
textfield.adjustsFontSizeToFitWidth = true
return textfield
}
func updateUIView(_ uiView: UITextField, context: Context) {
uiView.text = text
}
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
class Coordinator: NSObject, UITextFieldDelegate {
var parent: DataTextField
init(_ textField: DataTextField) {
self.parent = textField
}
//This function gets called (when changing a value in an array) only when the normal keyboard is pressed. If you type first - or E and then a number, the value is updated correctly. If you type first the number and lastly the E or the -, after changing the textfield the value reverts back to the one that was typed with the keyboard.
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if let currentValue = textField.text as NSString? {
let proposedValue = currentValue.replacingCharacters(in: range, with: string) as String
self.parent.text = proposedValue
}
return true
}
}
}
extension UITextField {
@objc func minusButtonTapped(button: UIBarButtonItem) -> Void {
insertText("-")
}
@objc func scientificButtonTapped(button: UIBarButtonItem) -> Void {
insertText("E")
}
}```