Printing random string from an array on textview - ios

I can't seem to get my array printed onto my textview. I have an array and have set my textview (texthold) to the randomIndex of the array.. Anything you guys see I'm doing wrong?
This is my button that when clicked is supposed to get a random string from the devices array and print it into the textview field. I am getting no errors just nothing displays onto the textview when the button is clicked
#IBAction func Generate(_ sender: Any) {
let devices = ["Apple Watch", "iPhone", "iPad", "Mac", "Apple TV"]
// Generate a random index
let randomIndex = Int(arc4random_uniform(UInt32(devices.count)))
// Get a random item
let randomItem = devices[randomIndex]
texthold.text = devices[randomIndex]
}

This code works in my program. Check your layout using "Debug view hierarchy tool", maybe it will help.
And:
texthold.text = randomItem
Name methods with lowercase (Generate -> generate)
Check if your button touch calls this method
Check if your UI items have connected outlets.
There may be problem with changing text from background thread, but if you really have this method connected from storyboard/xib as method for outlet's action - this situation impossible.
And check that your code is being called on .touchUpInside action of your button (second screenshot in storyboard)!

Related

How do you access a textfield which does not have a label or static text in XCTest?

so I've recently started testing an iOS app with xctest. I'm on a time model view where I would like to change the number in a cell. The number in this cell is the number of days after which the selected time model repeats itself. But I'm unable to access this textfield and change the number as it does not have a label / name / static text. When I record a tap on this field, Xcode gives me a strange element hierarchy which I've defined as the parameter 'onDay' below
func testRepetitionTypeMonthsOnDay() throws {
let app = XCUIApplication()
let tablesQuery = app.tables
let cellsQuery = tablesQuery.cells
XCTAssertTrue(app.navigationBars["Zeitmodelle"].waitForExistence(timeout: standardTimeout)) //wait for the time model view to open
app.staticTexts["Wiederholend"].firstMatch.tap() //tapping on a cell
XCTAssertTrue(app.navigationBars["Wiederholend"].waitForExistence(timeout: standardTimeout)) // wait for the cell to open
let repetitionType = app.tables.cells["Am, Am Tag, Expand"] //cell 1 from screenshot
let onDay = tablesQuery.children(matching: .cell).element(boundBy: 7).children(matching: .other).element(boundBy: 1).children(matching: .other).element.children(matching: .textField).element //cell 2
let endDate = app.tables.cells["Endet, Endet nicht, Expand"] // cell 3 from screenshot
onDay.tap()
onDay.clearAndEnterText("5")
}
However, Xcode cannot find the parameter onDay that itself has generated in the previous step, tap on it and enter a new text. I've attached a screenshot of the app with this cell here. The cells above and below the marked cell can be identified easily and the assertions for their existence work. The marked cell, however, is a different matter as it does not have a label / static text. Do you have an idea how I can get around this? Thanks a lot!
So I've finally found a way to access this element. Instead of going into the cell view I've accessed the textfields array from tables view.
func testRepetitionTypeMonthsOnDay() throws {
let app = XCUIApplication()
let tablesQuery = app.tables
XCTAssertTrue(app.navigationBars["Zeitmodelle"].waitForExistence(timeout: standardTimeout)) //wait for the time model view to open
app.staticTexts["Wiederholend"].firstMatch.tap() //tapping on a cell
XCTAssertTrue(app.navigationBars["Wiederholend"].waitForExistence(timeout: standardTimeout)) // wait for the cell to open
let onDay = tablesQuery.textFields.element(boundBy: 3)
onDay.tap()
onDay.clearAndEnterText("5")
}
Because the app had a mixture of picker wheels and textfields in the same view, it was a bit problematic for Xcode to find the element I wanted from a general element index. But the use of the textfields array filtered the index list down to only textfields. Xcode was then able to identify the element without any conflict and perform the test. I hope this helps anyone having the same problem.

Adding a cell to another TableView. (selecting an item from a tableview, showing it in another tableview)

I'm building an app which which has built in with 2 different tabs. First tab is is "Home" which basically has a tableview with cells that configured from an api.(The api gets me country names for now)
Those cells also have a "Star" button which prints the data of the specific cell for now.
Second tab is "Saved" tab(SavedViewController), where I want to show the "starred" countries, using a tableview.
You can see the image below in order to get an idea for the app.
App simulation Image
The star button has a function in my CountriesTableViewCell. I'm using a saveButtonDelegate in order to let the SavedViewController know about an item is going to be saved. The code in CountriesTableViewCell for star button is as below.
#objc func buttonTapped() {
//If Button is selected fill the image. Else unfill it.
if !isSaveButtonSelected {
saveButton.setImage(UIImage(systemName: "star.fill"), for: .normal)
isSaveButtonSelected = true
saveButtonDelegate?.saveButtonClicked(with: countryData) //Checking if save button is clicked
}
}
countryData is the data that I get from the api, and this is the data I want to pass to SavedViewController.
struct CountryData: Codable {
let name : String
}
So on the SavedViewController, I'm handling the data using the SaveButtonProtocol conformance as below:
extension SavedViewController: SaveButtonProtocol {
func saveButtonClicked(with data: CountryData) {
countryDataArray.append(data)
print("saveButtonClicked")
print("countryData in savevc is \(countryDataArray)")
DispatchQueue.main.async {
self.countriesTableView.reloadData()
}
}
}
Whenever I click the star button on the first tab, this function is getting called on SavedViewController. So whenever I click to button, those print statements above work fine.
The problem is, whenever the star button is clicked, it should append the data of the current clicked cell to countryDataArray in SavedViewController. But the array is not populating as it should.
Let's say I pressed the first cell's star button, my print("countryData in savevc is (countryDataArray)") statement prints : ["Vatican City"], then I press the second cell's star button it only prints ["Ethiopia"] while it should print ["Vatican City", "Ethiopia"]
Why this issue is happening? My best guess is I'm delegating SavedViewController from the cell class so it behaves differently for every other cell. If that is the problem what should I do to solve it?
Many Thanks.
You should store your data in a shared (static array) object so you only have one source and add the saved indicator in your country struct so you do not rely on what is displayed in one view controller.

How do I verify and assert if an animation is playing after clicking a button in XCUITest?

I can't seem to find any information when it comes to animation testing on XCUITest.
The scenario that I am testing is that:
When a button is pressed
Then animation will be displayed on the icon
How do I do this?
I recommend setting a meaningful accessibilityValue on the button when it it's animating, which will let voice over users that something is happening too -- then you can check the value property of the corresponding XCUIElement in your test.
// product code
#IBAction func buttonPressed(_: UIButton) {
self.button.accessibilityIdentifier = "MyButton"
self.button.accessibilityValue = "is animating"
// start animating your button
}
// Test code
let button = self.app.buttons["MyButton"]
button.tap()
XCTAssertEqual(button.value as! String, "is animating")

A UIButton is pressed in 1 VC and I need it to save the buttons title to a label in a different view controller not directly segued to each other

In the initial set up of my app I need the user to chose a genre type. i have it set up such that the user selects from a list of UIButtons which are all different genre types. I need this genre selection to save to the users profile. The next view controller is the same set up as the genreVC but asking for instrument instead of genre. The next segue from here is to view controller 3 the usersVC profile and it should have saved which two buttons were selected on the previous two VC's by updating a label. I have tagged each button with a number and have tried next to everything.
How do I save which button has been pressed on a different view controller to the users profile and update the label on the users profile to the name of the button pressed?
I am using each button individually and have them tagged as such as seen here:
#IBAction func popGenreButton(sender: UIButton) {
if(sender.tag == 6){
print("Pop genre selected")
}
}
#IBAction func altGenreButton(sender: UIButton) {
if(sender.tag == 7){
print("Alternative genre selected")
}
}
#IBAction func electronicGenreButton(sender: UIButton) {
if(sender.tag == 8){
print("Electronic genre selected")
}
}
I also tried adding each button into genreSelection as shown below that didn't work so I stuck with the individual buttons above.
#IBAction func genreSelectionButton(sender: UIButton) {
print(sender.titleLabel!.text!)
genreResult.text = genreString + " genre has been saved to your profile"
}
I also created a nib with myModalDelegate and protocol and nope.
I thought maybe I could create a genre array and when a certain button is selected it calls a certain item from the array and updates that item to the label but I was unsure how to go about this too.
I am using Xcode 7 and Swift 2.0 and Parse as my cloud server.
As you can see I have a lot to learn yet with Swift. I have been searching how to do this for the past week and can't figure it out. I am a 'lot' out of my depth but want to figure it out, if anyone can help that would be great!
A simple solution would be something like creating a global store for those values
i.e.
struct Choices {
static var genre: String?
static var instruments: String?
}
then you could in your different view controllers write and read from it by simply
Choices.instrument = "trumpet"
or
label.text = Choices.genre
A prettier solution would be to create a similar class as the previous struct but not have the variables static. You could then pass it along and fill up with the values from each VC and use the values in the last VC where you are setting the label text

how to find a string property that corresponds to a gesture.view in Swift?

I have a json file containing an array of dictionaries:
"question":"Question text",
"answers":["Yes", "No"],
"answerTracker":["1a", "1b"]
I have created a Question Class & an Answer Button View Class to display the questions & answers in the view.
In the view controller I have so far displayed the questions, created the answer buttons, and finally, added a tapGestureRecogniser to each button.
func answerTapped(gesture:UITapGestureRecognizer) {
// Get access to the button that was tapped
let selectionButtonThatWasTapped:SelectionButtonView? = gesture.view as? SelectionButtonView
if let actualButton = selectionButtonThatWasTapped {
// Find out the index for the button that has been tapped
let selectionTappedIndex:Int? = find(self.selectionButtonArray, actualButton)
**// Find the answer tracker for the button that has been tapped?**
// Append the tracker for the selected button to the User Generated Code
if let actualAnswerTracker:String = self.answerTracker as String! {
self.userGeneratedCode.append(actualAnswerTracker)
}
In the tapGestureRecognizer method above I now need to find the corresponding answerTracker (String) for the answer button that is tapped (UIView) but can't find a way? The answerTracker string corresponding to the tapped answer is to be appended into a String array property called userGeneratedCode.
Any suggestions?
you do not need to add a tapGestureRecogniser to a button, you can add a target and selector to button anyway. If you want to know which button is pressed, you can use tag property on UIButton to check against.

Resources