I've searched through the forums and wasn't able to find anything similar to this question. It's my first time posting so please let me know if I need to add anymore information and I'll try my best!
I'm exploring Xcode and building an app for iOS 7 on an iPhone. I'm using a hypothetical purpose for the app just to see if I can learn how to build the thing (it's a booking system for taxis). It's a tabbed application (I have three tabs at the bottom corresponding to three different screens of the app, one is rates which displays a scrollable image of rates, one is a booking system that sends an email with information taken from text fields, and one is a settings page)
My questions is as follows:
On the booking page, I'd like to have a switch that either enables or disables user entry into additional text fields (it's actually for the option to book a 'return' journey, so the user can add in extra information for the return booking).
I have my page set up with the first text fields in place, but I can't for the life of me figure out or find anywhere about how to make this switch enable entry into the additional text fields. Ideally I'd like them to be greyed out and disabled if the switch is off, and enabled if the switch is on.
Any help on the matter would be much appreciated!
Thanks.
edit:I'm also doing this with storyboard, wasn't sure if this made a difference!
You can use UISwitch and UITextField for this. UITextField has a property called enabled that controls whether the user can interact with it.
First you need to create an IBOutlet for your UITextField in storyboard by control-dragging it to respective #interface definition in your header file. Then you need to create an IBAction for your UISwitch, again by control-dragging it to #interface (choosing 'Action' for 'Connection' and 'changed' for 'Event').
Finally implement the newly generated method like this:
#implementation ViewController
-(void)mySwitchChanged:(id)sender
{
UISwitch *mySwitch=(UISwitch *)sender;
myTextField.enabled=[mySwitch isOn];
}
.
.
Related
I am using iOS UITest for a Swift application. I use something like,
func testAllScreenNavigation() {
let app = XCUIApplication()
app.tabBars.buttons["Home"].tap()
app.navigationBars["Home"].buttons["More"].tap()
app.sheets.buttons["Cancel"].tap()
}
etc. to navigate some of the specific, tabs, buttons, etc. and switch to respective screens. But i want to navigate each and every screens of my Application (It can be BFS style navigation or DFS style navigation, no matter). Is there any way iOS provides so i can get all navigable elements and then explore deeper and deeper automatically for my App?
I also need to keep trace of which xcuoelement in a screen is already processed and which are not yet processed.
The only way I can think of is using Xcode UI test recorder feature.
While you are recording, navigate through all of your screens via the device/simulator and then the XCUIApplication() variable would be recorded with the appropriate references.
If the button/nav bar/any element has text on it, it will show up in the recorded code or else it will be referenced numerically.
Hope that helps.
Kind regards,
Mukund
I like your idea for getting all views and check whether the layouting and localization for example is fine.
I think you need to specify your criteria for "screens" and how they are accessed.
Basically, one could thing of the following structure
- UITabBarController
-- UISplitViewController
--- UINavigationController
---- UIViewController
----- UIBarButtonItems
----- UIView
----- UIButton
----- UISwitch
----- UITableViewCell
You could now go top down from the UITabBarController to the next controlling instance (might also skip one, e.g. SplitViewControllers on iPhones).
You can use the general property:
XCUIApplication().tabBars
Nevertheless that transition is the problem: How would you get from one ViewController to another and are they all position in the ViewController's View or do you have to loop the subviews of a view.
UIButton -> Touch Up Inside
UISwitch -> Value Changed
UITableViewCell -> DidSelectRowAtIndexPath
UIView -> UILongPressGestureRecognizer
This is how I would basically set it up:
For each UIViewController instance, get the related View (and perform the following call recursively).
Check all the subviews of a view.
For UIViews, go even further and check their subviews
For UIButtons, perform TouchUpInside
and so on.
Make sure to have a condition to stop going deeper, as UITableViews got a lot of subviews or your UIWebViews would of course be set up in a different way.
This way you should be able to navigate through a lot Views in your app hierarchy, but you will need some extensions for UIBarButtonItems, custom Gesture Recognizers and of course also for your "special" controls that might listen to value changes and perform a layout-change.
Accessing specific elements
In addition to the above approach where you simply get an array of elements of a specific type, you can access specific elements (e.g. those where you know they are of a very specific type with certain ValueChangeListeners or something)
To access a specific object in particular, like the TabBar example from above, you can use the accessibilityLabel like so. At first you need to declare the accessibilityLabel in your code or in the .xib-file/.storyboard:
// just to illustrate, so you get an idea:
self.tabBarController.isAccessibilityElement = true
self.tabBarController.accessibilityLabel = "tabBar"
And then do:
let tabBar = XCUIApplication().tabBars["tabBar"]
Here is Apple's documentation for setting these accessibilityLabels:
https://developer.apple.com/library/content/documentation/UserExperience/Conceptual/iPhoneAccessibility/Making_Application_Accessible/Making_Application_Accessible.html
A great way to get the related identifier of an element would be to use the Accessibility Inspector from Apple:
https://developer.apple.com/library/content/technotes/TestingAccessibilityOfiOSApps/TestAccessibilityiniOSSimulatorwithAccessibilityInspector/TestAccessibilityiniOSSimulatorwithAccessibilityInspector.html
Accessing elements in general
To access elements in general, you need to make use of the XCUIElementType of these objects, here you will access the objects based on their classes.
E.g. you could call:
"tabBars", "navBars", "tables", "buttons", and so on from the elements in general.
Still you would be facing the issue with "special controls". As the Apple documentation lacks (imho) some detail about properties and attributes, I do recommend the docs here: https://blog.metova.com/guide-xcode-ui-test/ It provides a great overview of what is accessible and may help you getting some better understanding.
An overview of the available XCUIElementTypes can be found here. Basically, the elementType property is an enumerated value that represents the type of an element. XCUIElementType is a very large enumeration and some of its members do not apply to iOS applications (they apply to MacOS X apps). Some of the more commonly used values are:
Alert
Button
NavigationBar
TabBar
ToolBar
ActivityIndicator
SegmentedControl
Picker
Image
StaticText
TextField
DatePicker
TextView
WebView
https://developer.apple.com/reference/xctest/xcuielementtype?language=objc
I am newbie in iOS with swift. What I need to do right now is that I have a textfield for user to enter his/er username. And once he clicks the other textfields, say password section, the application will automatically check whether this name exists or not and display a "V" or "X" image in a imageView. But I don't know how to do that or what method or action I should deal with. In Android, I could detect the focus of that textfield.Once the textfield loses the focus and if the text isn't empty, I can retrieve the text and request to my server to verify whether it exists or not. In iOS, I'm totally confused how to detect this, and is this related with first responder? Thx for advice in advance!
Use UITextFieldDelegates.
class XXX : YOURCONTROLLER, UITextFieldDelegate {
override func viewDidLoad() {
super.viewDidLoad()
self.PASSCODE.delegate = self
}
func textFieldDidEndEditing(textField: UITextField) {
if textField == PASSCODE {
//update stuffs
}
}
}
On iOS, you generally create the interface in Interface Builder (a graphical tool you can use to place UI elements on screen and define many of their properties), and then you link them to your code using what's called IBOutlets/IBActions.
The code your link those elements to is often the view controller ; the view controller is the object that is responsible for managing a view and the events it receives.
To make an IBOutlet, go to your interface builder file (1), select the view controller you are interested by (2, for you it will be the one it which your form is present) open the assistant editor (3), the assistant editor should show to code corresponding to your view controller. Then control drag to the inside of your view controller class definition (4).
Once you do that there will be a little "popup" asking you wether you want an outlet or an action (5), if you just want a reference to the given UI object, then select an outlet.
If the object does an action (for example a button) and you want a method to be called when this action occurs, then you would choose action.
From there this should be pretty straightforward, what I would do would be to make an outlet to the textfield containing the password, and an action for the "Send/Connect" button, whether the method linked to this event would be called, I would check if the password is right or wrong.
EDIT : Maybe I added to much details and you already know a lot about what I told you, but when beginning, those things aren't always that much easy.
I'm working on a sharing extension in iOS with Swift. In the share app, I would like to add a custom field, where the user can add text to it. I tried finding references to see how it could be done but I can't find any.
Can someone help me out please?
You can't magically make a text field appear in the SLComposeServiceViewController interface. So you have two choices:
Use SLComposeServiceViewController, and add a configuration item (SLComposeSheetConfigurationItem) which you've set up so that it pushes some new interface containing a text field.
The pushed interface is up to you, even though the SLComposeServiceViewController interface is not.
Don't use SLComposeServiceViewController in the first place. Now the whole interface is up to you. Just use a normal view controller and it will be presented for you, and you can design the view in the storyboard just like always.
I am working on an application which allows users to work with a couple of workmodes. Main view of the app contains information common to all workmodes. I want to create a "subview" with ability to change its ViewController. This subview will be used to display information connected with specified workmode. It is important that app goes to MainViewController from WorkmodesViewController in which user chooses workmode to work with.
My question is:
Which tehnique should I use to acheave changeable WorkmodeViewController inside MainViewVontroller
I have found example git project with functionality I need:
https://github.com/mluton/EmbeddedSwapping
I've got a view controller xib file with several views in it. I'm building a wizard-type interface. I'm just doing a simple fade between the views, and I'm already using a navigation controller for the main interface. I'd prefer not to use one for this wizard. Anyway, in the views, each panel has at least a button, some sort of input field (usually a UITextField) and some helper text hard coded in a UILabel.
The problem is that not all the UITextField objects are calling the textFieldDidChange method in the delegate (File's Owner - .m file associated with the xib), but all the UITextField objects ARE calling the textFieldDidBeginEditing method.
Makes no sense to me. I feel like I must be missing something simple in how I set up the screens, but I'll be darned if I can figure it out. Each of the screens all look identical in the property sheets (on the right hand side of Xcode), and everything is wired up correctly in the File's Owner property sheet, both in IBOutlet and IBActions.
Here are some shots of what's going on...
Ideas? Thanks.
Here are links to the screen caps of the vital parts.
(being a new member is making it hard to add all the info I need with screen caps!)
As far as I now, there is no delegate method with the header textFieldDidChange. You have created a method of your own, which is depending on a NSNotification. Make sure all the UITextFields are send the right notification.
There is no such method on a UITextFieldDelegate
You may have confused textViewDidChange, which is a delegate method for a UITextView, but itis passed the UITextView that generated the event, not an NSNotification.
Seems like you want textField:shouldChangeCharactersInRange:replacementString: instead.
This is resolved. I'm a knucklehead. :-)
I was attaching my own notifier/observer and hadn't done so for the last few UITextField objects. Sorry to bother y'all.