iOS - UI Automation get textfield by accessibility label? - iphone

So in my nib file i enabled accessibility and set the accessibility label of a textfield to "txt"
I am trying to find this textfiled based on accessibility name and change its text.
var target = UIATarget.localTarget();
var application = target.frontMostApp();
var mainWindow = application.mainWindow();
mainWindow.logElementTree();
// This works
var textField = mainWindow.textFields()[0];
//this doesn't work
var textField = mainWindow.textFields()["txt"];
textField.setValue("Hello");
Am I doing anything wrong? How can I find a label based on accessibility label?
EDIT:
I am open to other solutions as well, I am trying to avoid getting the textfield based on the index

I have a similar problem and setting the accessibility label value in the code instead in the nib file solve my problem. For example, I have a UITextField that I need to access in my UIAutomation script, I would have to set the accessibility label value in the viewDidLoad method as shown below.
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
testTxtField.accessibilityLabel = #"myTxtBox";
}
and below is my UIAutomation Script
var target = UIATarget.localTarget();
var application = target.frontMostApp();
var mainWindow = application.mainWindow();
mainWindow.logElementTree();
// This works
//var textField = mainWindow.textFields()[0];
// Now, this work too.
var textField = mainWindow.textFields()["myTxtBox"];
textField.setValue("Hello");
UIALogger.logMessage("Text field:" + textField.label());

Related

UIButton Configuration Line Break Mode Not Working

I know there are a few SO posts about this, but none are working...
I am just trying to get my custom UIButton subclass using the UIButton.Configuration method to force my title label to stay 1 line, without changing the button frame.
I keep getting the right button shown below...
What can I do?? Here is how I am setting up by button..
init(withTitle title: String, ... <more custom params> ...) {
// ...
super.init(frame: .zero)
var config = UIButton.Configuration.filled()
config.title = title
titleLabel?.lineBreakMode = .byTruncatingTail
titleLabel?.numberOfLines = 1
configurationUpdateHandler = { button in
// ... here I handle colorizing elements for different button states /
}
}
I understand I can accomplish the text clipping by using a standard let button = UIButton(type: .custom), and set the titleLabel line properties. This is not a solution - the customization offered with the configuration are not available otherwise.

Thread 1: signal SIGABRT swift

I was trying to center the text in the middle of a view, but instead, received an error. Here's my code as a reference.
let textbox = UITextField()
textbox.text = "Hello"
textbox.sizeToFit()
textbox.centerXAnchor.constraint(equalTo: textboxView.centerXAnchor).isActive = true
textbox.centerYAnchor.constraint(equalTo: textboxView.centerYAnchor).isActive = true
textbox.delegate = self
self.textboxView.addSubview(textbox)
You cannot constraint a view relative to another view unless they are first related.
You need to add the subview first before setting the constraints
let textbox = UITextField()
textbox.text = "Hello"
textbox.translatesAutoresizingMaskIntoConstraints = false
self.textboxView.addSubview(textbox)
textbox.centerXAnchor.constraint(equalTo: textboxView.centerXAnchor).isActive = true
textbox.centerYAnchor.constraint(equalTo: textboxView.centerYAnchor).isActive = true
textbox.delegate = self
You haven’t given lot of detail surrounding the rest of your view controller, so you may have already added it somewhere else.
However, when using autolayout constraints you must turn off auto masking.
textbox.translatesAutoresizingMaskIntoConstraints = false
You should also add the textbox as a subview prior to setting constraints.

swift - How to correctly set up a UITextView

I have a view controller that only has a UITextView in it. I'm having a problem initializing the UITextView with another one that I pass to the view controller.
Here's the code for the view controller:
(The File class has a string variable: name, and UITextView variable: content)
// MARK: Properties
var file: File?
#IBOutlet weak var textViewHome: UITextView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
navigationItem.title = file?.name
self.automaticallyAdjustsScrollViewInsets = false
print(file?.content.text)
print(textViewHome.text)
textViewHome = file?.content
print(textViewHome.text)
}
The output of those print statements are:
Optional("hello")
hello
So the textViewHome variable gets set with the correct string but nothing shows up in text view when the app is run. I've seen a lot of questions similar to this but haven't found one where the UITextView.text variable is correct but nothing actually shows up. Thanks for any advice
The main problem is that your view hierarchy (what's is showing on the screen) had textViewHome because it's a subview of viewController.view. When you changed the pointer of textViewHome, the view hierarchy still had the old one because you changes the viewController's pointer and you didn't touch the hierarchy.
Design Improvement: It's better to let the File own a string and not UITextView.
class File{
var name: String
var content: String
}
In your viewController, you will have
textViewHome.text = file?.content //content is a string

How can I use didSet to change the text of a UITextField (IBOutlet)?

I'd like to set text value of UITextField (IBOutlet) in the DidSet of my model object that I pass.
Here the code:
let manageSettingViewController: ManageSettingViewController = self.storyboard?.instantiateViewControllerWithIdentifier("ManageSettingViewController") as ManageSettingViewController
self.navigationController?.pushViewControllerCustom(manageSettingViewController)
manageSettingViewController.setting = setting
And in the didSet of manageSettingViewController:
var setting: Setting? {
didSet
{
keyTextField.text = setting?.label
valueTextField.text = setting?.value
}
How can I set the text? Because in this case Xcode crash because "keyTextField is nil" :(
You're setting manageSettingViewController.setting right after instantiating manageSettingViewController -- at this point, it hasn't loaded its view from the nib/storyboard yet, so all of its IBOutlet variables (which presumably keyTextField and valueTextField are) are still nil. Those text fields are hooked up as of when ManageSettingViewController's viewDidLoad method is called.
You could change your didSet to check the optional outlets before setting them, or assign through optional chaining:
didSet {
keyTextField?.text = setting?.label
valueTextField?.text = setting?.value
}
This would avoid the crash, but it would also fail to change your text field's content. You'd have to also implement viewDidLoad for ManageSettingViewController to check its setting property and set its text fields accordingly.
Of course, that would duplicate the code from your didSet. That code might still be useful if you want to set setting from elsewhere and have the UI update automatically, but didSet won't help you for updating UI before the UI loads.

MvvmCross: Programmatically adding a view to CollectionView's subview

Depending on user action, I want to dynamically add a view (within MvxViewController) to the subviews collection of a CollectionView. Here's what I'm doing:
Does NOT work: SubviewThree inherits MvxViewController
var mvxViewController = new SubviewThree(); // SubviewThree inherits MvxViewController
var uiView = mvxViewController.View;
uiView.ClipsToBounds = true;
uiView.Hidden = false;
uiView.Frame = new RectangleF(0, 0, 320, 200);
CollectionView.AddSubview(uiView);
CollectionView.BringSubviewToFront(uiView);
Works: SubviewThree inherits UIViewController
var mvxViewController = new SubviewThree(); // SubviewThree inherits UIViewController
var uiView = mvxViewController.View;
uiView.ClipsToBounds = true;
uiView.Hidden = false;
uiView.Frame = new RectangleF(0, 0, 320, 200);
CollectionView.AddSubview(uiView);
CollectionView.BringSubviewToFront(uiView);
Works:
var label = new UILabel(); // All simple controls work just fine
label.Text = "Test Label";
label.ClipsToBounds = true;
label.Hidden = false;
label.Frame = new RectangleF(0, 0, 320, 200);
CollectionView.AddSubview(label);
CollectionView.BringSubviewToFront(label);
What's the best way to achieve this in MvvmCross? Note that I cannot use data binding (and add it via view model's ObservableCollection) here since the view to be added depends on user action - it may not be of same type.
Here's what I'm trying to do:
On right/left button touch, I want to swap views. The views are bound to different view models. The swapped view can either be either of V1 type (having a bar and another UIView) or some other type (just a UIView).
Here's my github link with sample project, just in case if the above image is not clear. You can just run the app and click on Add button. The code for adding view to subview is in BarCell.cs, line 158. There I've commented the above mentioned lines of code.
Github Link
In order for MvvmCross to create a View and to hook it up with it's ViewModel, MvvmCross uses a MvxViewModelRequest object. In iOS this is connected to the View using a Request property.
You can hook this up yourself if you want to - it's just a get/set property that has to be set before ViewDidLoad occurs - see IMvxTouchView.cs
Alternatively:
if you want MvvmCross to create the View (including doing the ViewModel-View lookup) then there are some extension methods in https://github.com/slodge/MvvmCross/blob/v3/Cirrious/Cirrious.MvvmCross.Touch/Views/MvxCanCreateTouchViewExtensionMethods.cs
if you don't need a viewController, then the MvxView class may be sufficient for you - see the N=32 video for an example of its use - http://slodge.blogspot.co.uk/2013/06/n32-truth-about-viewmodels-starring.html