how to know which Search Bar is Active? - xcode

now I have 2 search bar at one page
the first problem is How can I make a search button always show although no text at searchbar.text?
the second problem is, I have a Table View that Will show a different list expend which search bar I choose, how can I do it well?
I can set a variable that change everytime the search bar is active. However is there a way to see which search bar is currently the active search bar?

The simplest way to check which view are you working with, is assigning the tag property:
firstSearchBar.tag = 100;
secondSearchBar.tag = 200;
You can easily check it:
if(searhBar.tag == 100) {
// it is first search bar
} else if(searchBar.tag == 200) {
// it is second search bar
}
Now, the second part. If you want to show cancel button, you can do it in this way:
searchBar.showsCancelButton = YES;
If you want to show scope bar:
searchBar.showsScopeBar = YES;
If you want to show search results button:
searchBar.showsSearchResultsButton = YES;
EDIT: If you wish to show Search keyboard button even if there's no text entered, you can do it in this way:
UITextField *searchField = (UItextField *)[[searchBar subviews] objectAtIndex:0];
[searchField.enablesReturnKeyAutomatically = NO;
I recommend you reading UISearchBar's documentation.

Related

Xcode UITest scrolling to the bottom of an UITableView

I am writing an UI test case, in which I need to perform an action, and then on the current page, scroll the only UITableView to the bottom to check if specific text shows up inside the last cell in the UITableView.
Right now the only way I can think of is to scroll it using app.tables.cells.element(boundBy: 0).swipeUp(), but if there are too many cells, it doesn't scroll all the way to the bottom. And the number of cells in the UITableView is not always the same, I cannot swipe up more than once because there might be only one cell in the table.
One way you could go about this is by getting the last cell from the tableView. Then, run a while loop that scrolls and checks to see if the cell isHittable between each scroll. Once it's determined that isHittable == true, the element can then be asserted against.
https://developer.apple.com/documentation/xctest/xcuielement/1500561-ishittable
It would look something like this (Swift answer):
In your XCTestCase file, write a query to identify the table. Then, a subsequent query to identify the last cell.
let tableView = app.descendants(matching: .table).firstMatch
guard let lastCell = tableView.cells.allElementsBoundByIndex.last else { return }
Use a while loop to determine whether or not the cell isHittable/is on screen. Note: isHittable relies on the cell's userInteractionEnabled property being set to true
//Add in a count, so that the loop can escape if it's scrolled too many times
let MAX_SCROLLS = 10
var count = 0
while lastCell.isHittable == false && count < MAX_SCROLLS {
apps.swipeUp()
count += 1
}
Check the cell's text using the label property, and compare it against the expected text.
//If there is only one label within the cell
let textInLastCell = lastCell.descendants(matching: .staticText).firstMatch
XCTAssertTrue(textInLastCell.label == "Expected Text" && textInLastCell.isHittable)
Blaines answer lead me to dig a little bit more into this topic and I found a different solution that worked for me:
func testTheTest() {
let app = XCUIApplication()
app.launch()
// Opens a menu in my app which contains the table view
app.buttons["openMenu"].tap()
// Get a handle for the tableView
let listpagetableviewTable = app.tables["myTableView"]
// Get a handle for the not yet existing cell by its content text
let cell = listpagetableviewTable.staticTexts["This text is from the cell"]
// Swipe down until it is visible
while !cell.exists {
app.swipeUp()
}
// Interact with it when visible
cell.tap()
}
One thing I had to do for this in order to work is set isAccessibilityElement to true and also assign accessibilityLabel as a String to the table view so it can be queried by it within the test code.
This might not be best practice but for what I could see in my test it works very well. I don't know how it would work when the cell has no text, one might be able to reference the cell(which is not really directly referenced here) by an image view or something else. It's obviously missing the counter from Blaines answer but I left it out for simplicity reasons.

How to hide / disable tab bar item in swift

I have a five tab, tab bar controller in my app, and I want to only show the 5th item if a manager is logged into the app (instead of employee).
I currently have this code which disables the 5th item but I can still see it (its just grayed out and is not clickable).
self.tabBarController!.tabBar.items![4].enabled = false
Is there a way to only show the first four items and evenly space them if a non manager is logged in?
Swift 3
if let tabBarController = self.tabBarController {
let indexToRemove = 3
if indexToRemove < tabBarController.viewControllers!.count {
var viewControllers = tabBarController.viewControllers
viewControllers?.remove(at: indexToRemove)
tabBarController.viewControllers = viewControllers
}
}

Why UIBarbuttonItem is not working in Swift while code is written well?

I have written the same behaviour in two ways. The first one, doesn't work:
var barbutton = (left) ? navigationItem.leftBarButtonItem : navigationItem.rightBarButtonItem
barbutton = UIBarButtonItem(customView: button)
opposite to:
if (left) {
navigationItem.leftBarButtonItem = UIBarButtonItem(customView: button)
} else {
navigationItem.rightBarButtonItem = UIBarButtonItem(customView: button)
}
What is the difference?
As #Martin points out, the two code sequences are very different in function.
The first sets barbutton to the contents of either leftBarButtonItem or rightBarButtonItem and then discards that value and sets (the temporary variable) to a newly created button.
The second sets either leftBarButtonItem or rightBarButtonItem, depending on left to a newly created button.
There really isn't much way to shorten your code and still achieve the desired effect (without also obscuring the code).
You could use:
(left ? navigationItem.setLeftBarButtonItem : navigationItem.setRightBarButtonItem)(UIBarButtonItem(customView: button), animated: false)
But that's just weird.

NSTextField with auto-suggestions like Safari's address bar?

What's the easiest way to have an NSTextField with a "recommendation list" dynamically shown below it as the user types? Just like Safari's address bar that has a menu of some sorts (I'm pretty confident Safari's address bar suggestions is menu since it has rounded corners, blue gradient selection, and background blurring).
I've tried using NSTextView's autocompletion facility but found it was inadequate:
It tries to complete words instead of the whole text fields – in other words, selecting an autocomplete suggestion will only replace the current word.
It nudges the autocompletion list forward and align it with the insertion point instead of keeping it align with the text field.
In the sample screenshot above whenever I selected the autocomplete suggestion the text field only replaces K with the suggested item in the list, which results in Abadi Abadi Kurniawan.
These are what I'd like to achieve:
Whenever a suggestion is selected, the entire text field is replaced with the suggestion.
Keep the suggestion list aligned with the text field's left side.
Note: This is not a question about adding progress indicator behind a text field.
The Safari address bar uses a separate window. Apple has example project CustomMenus and it only takes an hour or two to customize it.
Developer session explaining what has to be done Key Event Handling in Cocoa Applications
If you want to be able to select multiple words you need to provide own FieldEditor (credits should go for someone else)
- (id)windowWillReturnFieldEditor:(NSWindow *)sender toObject:(nullable id)client;
{
if ([client isKindOfClass:[NSSearchField class]])
{
if (!_mlFieldEditor)
{
_mlFieldEditor = [[MLFieldEditor alloc] init];
[_mlFieldEditor setFieldEditor:YES];
}
return _mlFieldEditor;
}
return nil;
}
- (void)insertCompletion:(NSString *)word forPartialWordRange:(NSRange)charRange movement:(NSInteger)movement isFinal:(BOOL)flag
{
// suppress completion if user types a space
if (movement == NSRightTextMovement) return;
// show full replacements
if (charRange.location != 0) {
charRange.length += charRange.location;
charRange.location = 0;
}
[super insertCompletion:word forPartialWordRange:charRange movement:movement isFinal:flag];
if (movement == NSReturnTextMovement)
{
[[NSNotificationCenter defaultCenter] postNotificationName:#"MLSearchFieldAutocompleted" object:self userInfo:nil];
}
}
This only addresses half of your answer, but I believe you need to subclass NSTextView and implement the - (NSRange)rangeForUserCompletion method, returning the range of the entire string in the text field. This should make sure that it doesn't just autocomplete the most recently entered word.
If you want a custom menu, you're going to have to do that yourself, probably by implementing the -controlTextDidChange: method and displaying a custom view with a table when appropriate.

NSMenuBar mouse down notification?

i'm trying to find notification/way to check if NSStatusItem from NSStatusBar (System wide bar) was clicked.
Does anybody knows how to achive this ?
Thanks
EDITED 20120111
I meant "any" item from whole status bar.
do something like:
statusItem.target = self;
statusItem.action = #selector(mouseDown:);
statusItem.sendActionOn = NSLeftMouseDownMask; // try without this at first - i can't remember what the default it so you probrably don't need it
then:
- (void)mouseDown:(id)sender {
NSLog(#"click click");
}

Resources