Hi guys, I cannot get a custom UIControl to allow me to use command+drag to create a segue in the storyboard. I know they can be done programatically but I need to do them in the storyboard per requirements and was wondering if there's a trick to add this functionality. When I try with a custom UIControl, the connection from my control to the other view controller never "attaches" and no blue square around the other view controller and menu popoup for a segue appears. I've tried adding a gesture recognizer and ensuing sendTo events were active but no dice. I also tried dragging from the heirarchy view but again nothing. It's like the control doesn't even see the second view controller. For troubleshooting I even tried making a completely empty project, empty class that inherits from UIButton (which should already have those things) and it still doesn't work. (And yes, my view is set to the Custom UIButton in the storyboard.)I did notice that with the controls that do work they all have a "Triggered Segues" section in the connections inspector and wonder if that may be the key. I'm on XCode 10.3.
Post
Replies
Boosts
Views
Activity
Hi guys, I have a problem I'm trying to solve and I can't figure out a way to do it. I have a variable in the view model that is being watched and will flash the background of a textfield red if an invalid character is entered. (This is a business requirement for a SwiftUI proof of concept at work so I cannot change this behavior.). Unfortuantely I cannot figure out how to do it.The code below is a simplification of what I need. If you enter a "!" in the text field, the background will render red. The issue here is because it can't change back to white without a state change, the background stays red until a new character is pressed. I'm trying to figure out a workaround to this since it doesn't seem possible to chain animations and the "repeatCount(1, autoreverses: true) doesn't do anything here. Anyone have any suggestions? class Person: ObservableObject {
@Published var name: String = "" { willSet { processValue(value: newValue) }}
@Published var hasError: Bool = false
private func processValue(value: String) {
value.last == "!" ? (hasError = true) : (hasError = false)
}
}
struct ContentView: View {
@ObservedObject var vm = Person()
@State private var change = false
var body: some View {
VStack {
TextField("Name", text: $vm.name)
.background(vm.hasError ? Color.red : Color.white) //I'd rather just flash this red and turn it back to white
.animation(Animation.linear(duration: 0.2).repeatCount(1, autoreverses: true))
}.padding()
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
Hi guys, Yesterday during a work meeting a coworker said to use a struct as a view model instead of a class that derives from observable object so that you can avoid using all the property wrappers. While this approach technically works I don't feel it's the proper way to do things for a few reasons:1. It seems "anit-pattern". Not on part of Apple documetnation I've found uses a struct instead of an observabled object. 2. It seems really memory inefficient. Imagine if the struct held large amounts of data, you'd be recreating it every time the view refreshed. 3. The property wrappers do things under the hood (mainly create subscribers from what I'm seeing in the docs). Can someone with more knowlege of SwiftUI bring some clarity to this for me? Is ObservableObject or just a Struct more efficient?
Hi guys, I'm so stuck on a problem that was super easy in UIKit, but seemingly impossible in SwiftUI. All I need to do is create reusable controls that have logic and view encapsulation, and can validate on every key pressed. These controls do different things like validate text input in a special way, or calculate different things, and in UIKit it was easy, I would just make a class to handle the logic and the view, drop them into my project either programatically or via storyboard, and they'd do their thing. I'd like to do the same in SwiftUI by encapsulating a control so that I can do something like this: @ObservedObject var vm = FormViewModel()
VStack {
ControlType1(minLength: 5, allowsDecimal: false, text: $vm.userID)
ControlType2(maxLength 3, allowsUnicode: true, text: $vm.frpReading)
//Etc
}I have scoured all over the internet for months and cannot find a good way to encapsulate the logic with a view. It seems like no one else has either and there are plenty of people trying to do this same thing. It's very common to do in the enterprise world. I just want to be able to instantiate a control with some settable properties and have it handle my logic. ViewModels looked promising, but if a ViewModel is controlling the logic of one of those ControlType views and massaging the input string, then there is no way to connect the data to the FormViewModel which oversees the logic of the entire form. Combine sounded promising but it's such a nightmare syntax wise and the documentation for it is virtually non-existent. Property Observers don't work the same when it comes to @Published and other property wrappers so they're out the window. You get either nothing, or infinite loops when you try and use them in SwiftUI. My question is, how can I create a reusable component that lets me handle logic every time a key is pressed? This took minutes in UIKit. Is it even possible in SwiftUI yet?
Hi guys,
I'm trying to figure out why I can use some string modifications on a custom property wrapper but not others. My end goal is to try and encapsulate logic on TextFields that I can use across projects and property wrappers seemed like the answer, but I'm getting inconsistent results.
I have the following code:
import SwiftUI
import Combine
struct ContentView: View {
@StateObject var vm = FormDataViewModel()
var body: some View {
Form {
TextField("Name", text: $vm.name)
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
class FormDataViewModel: ObservableObject {
@CustomWrapper var name: String = ""
private var nameObserver: AnyCancellable?
init() {
nameObserver = _name.$value.sink {_ in
self.objectWillChange.send()
}
}
}
@propertyWrapper
public class CustomWrapper {
@Published var value: String
public var wrappedValue: String {
get { value }
set {
value = newValue.filter({$0 != "s"})
print("Value: \(value)")
}
}
public var projectedValue: AnyPublisher<String, Never> {
return $value
.eraseToAnyPublisher()
}
public init(wrappedValue: String) {
value = wrappedValue
}
}
As the code currently sits, if I type into the TextField the lower case 's' actually appears, and only disappears when I type something else, despite the print statement showing the correct value (without the s).
If I change this line:
value = newValue.filter({$0 != "s"})
to this:
value = String(newValue.prefix(5))
Then start typing in the text field, the text field shows far more than 5 characters, it'll show however many characters I type, but value printed out only shows only 5.
If I switch out the code to this:
value = newValue.uppercased()
Everything works as expected. All lowercase text I enter is immediately uppercased. No delays, no phantom entries like with filter, it just works.
Does anyone know why this happens? Is it a bug? Is it my code?
Anyone else running into this?
I didn't have time to try other combinations but in Xcode 12, using SwiftUI and the new application lifecycle build to device takes forever, even on a brand new project just trying to build the default "Hello World" screen.
Apps work fine in the simulator, apps work fine in preview, but building to device via cable or network is incredibly slow and can take anywhere from 45 seconds to a few minutes to go from black screen to app screen. Normally it's instant.
In Xcode source control, in the commits section, there is an avatar placeholder beside the name. Photos of Xcode show this image populated with a picture, but there seems to be no way to actually do this. This is very painful for people who work in an office where two employees share the same name.
Things I've tried that don't work:
-Having a Gravatar (yes email addresses match).
-Ensuring my git config file has an email address.
-Ensuring my email address in GitHub is correct (and my GitHub has a picture).
-Ensuring my contacts app has my name with my email address and picture in it.
How on earth does one populate this placeholder (see image below)?
Hi guys,
In Xcode, when you run an audit in the accessibility inspector, you can see a report of all of the deficiencies your app has. Does anyone know if there's either a way to export this data, or access it somehow where I could write a plugin to get the report?
Hi guys,
I don't know if it's something in my code or a bug but for some reason on my latest project tableView.indexPathForRow(at: to:) is returning an index that is off by one.
I have a stripped down tableview controller with a custom cell and button linked to the "testButton" method. I also tagged the button with the indexPath.row from the cellForRowAt method so I know the cell is in the correct place.
The problem is, in tableView.indexPathForRow, the tag shows up with the expected value, but the indexPath.row from that method is off by one.
class TestListViewController: UITableViewController {
override func viewDidLoad() {
super.viewDidLoad()
configureTableView()
}
}
extension TestListViewController {
private func configureTableView() {
tableView.register(TestCell.self, forCellReuseIdentifier: "TestCell")
}
@objc func testButton(_ sender: UIButton) {
guard let indexPath = tableView.indexPathForRow(at: sender.convert(CGPoint.zero, to: self.tableView)) else {
return
}
print("Tag: \(sender.tag)") //This comes up as expected and the tag matches the row
print("IndexPath: \(indexPath)") //This does not, index row is off by one!
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "TestCell", for: indexPath) as! TestCell
cell.nameLabel.text = "Row \(indexPath.row)"
cell.checkbox.addTarget(self, action: #selector(testButton(_ :)), for: .touchUpInside)
cell.checkbox.tag = indexPath.row
return cell
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 50
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
}
In my actual app there is a checkbox on each cell and if I tap the first cells checkbox obviously the app crashes because the index is out of range, if I tap the second cells checkbox, the first cells checkbox fills in.
I'm at an utter loss, I have used this method many times in production apps just fine so I'm hoping it's just something I'm forgetting to do.
Hi all,
This post is from a blind user on Reddit looking for assistance. He created a ticket in the feedback app but was hoping there was another solution.
He is unable to post to these forums because VoiceOver doesn't allow him to set the tags appropriately. He asked that someone please post it here so he can get help.
Below is his post:
I’ve discovered another issue with VoiceOver in Xcode 16. We can’t add Plist keys to info.plist anymore. We can create a new row, but choosing a suggestion with VoiceOver is impossible.
My current workaround is to add a random key, save the file, and then open it as source code. I can edit the file in the code editor, but I lose great autocompletion and Plist handling. This is slowing me down, and I’m very unhappy with it. I’d appreciate it if you could share this post widely. Hopefully, a solution will be found. Thanks everyone!
(I can't link his original post here as it's not allowed.)
In short, is there any trick to getting Voiceover to work with plist files in Xcode 16?