Set inputview for Searchbar - Swift - swift

class TestViewController: UIViewController, UISearchBarDelegate {
#IBOutlet weak var mySearchBar: UISearchBar!
var myOwnInputView = UIView(frame: CGRectMake(100,100,50,50))
overide func viewDidLoad() {
mySearchBar.delegate = self
mySearchBar.inputView = myOwnInputView // errors - "Cannot assign to the result of this expression
}
}
I'm trying to assign a custom input view to my search bar, however based on apple documentation (-sorry could not find link anymore), for UISearchBar it seems to be a read-only value. Looking at this post, it appears that UISearchbar has multiple subviews and I need to get to the UITextField part in order to change the inputview. However, I'm not sufficiently familiar with Obj-C and my attempts to convert the code to Swift have not been successful.

This is the simplest way:
let searchTextField = searchBar.valueForKey("_searchField") as! UITextField
searchTextField.inputView = myOwnInputView

Found out that the textfield is a subview of a subview of UISearchbar.
Code to get to the textfield in swift:
var fakeView: UIView = UIView(frame: CGRectMake(100, 100, 50, 50))
#IBOutlet weak var searchBar: UISearchbar!
override func viewDidLoad() {
fakeView.backgroundColor = UIColor.redColor()
var c = 0
for v in (self.searchBar.subviews[0]).subviews {
c++
println("\(c).\(v)") //you should see two views - UISearchBarBackground and UISearcBarTextField
if let tf = v as? UITextField {
//do stuff to tf here.
//in my case, what I want is:
tf.inputView = fakeView
break
}
}
}}
Result of above code is no keyboard will show up when the searchbar text field is touched, just a red rectangle.
Note - credit goes to Matt Neuburg's "Programming iOS8: Dive Deep into Views, ViewControllers, and Frameworks (ISBN: 978-1491908730). Chapter 8 to be precise.

Related

How to create an effect to highlight correct answer

I am learning Swift, and I am throwing myself in the deep end to force myself to learn the language. I have a nephew who is a baby and thought to make an app to help him learn numbers.
The app is designed to set a set number of buttons on the screen like the one provided below. I have the code to play Directions, which tells the user which number to select. A-N14a, the audio file, says to click the 4. The Done button is set to move to the next screen.
What I am asking is that if I want 4 to be pressed, and they press the 9, I want to know how to implement a feature to give a hint to click the number 4? The idea is to change the background to a button, but I don't know how to implement the feature. I am also open to other ideas. As a note, I do not know what to do, and I'm trying to learn, so the code provided is probably very simplistic and is at the beginning stages.
Below is an image of the screen and the code for that page.
ScreenShot of Page
import UIKit
import AVFoundation
class Intervention_Numerals1: UIViewController {
#IBOutlet weak var Directions: UIButton!
#IBOutlet weak var Done: UIButton!
var audioPlayer = AVAudioPlayer()
override func viewDidLoad() {
super.viewDidLoad()
setUpElements()
//Audio Test
do {
audioPlayer = try AVAudioPlayer(contentsOf: URL.init(fileURLWithPath: Bundle.main.path(forResource: "A-N14a", ofType:"mp3")!))
audioPlayer.prepareToPlay()
} catch {
print(error)
}
}
func setUpElements() {
// Style the elements
Utilities.styleFilledButton(Directions)
Utilities.styleFilledButton(Done)
}
#IBAction func Play(_ sender: Any) {
audioPlayer.play()
}
}
Please let me know any tips or advice or links to similar questions, even though I could not find any on my own.
Here's what I would do:
Record the sound "Tap the number" and then the sounds for the numbers 0 through 9. Name the number sounds "0.mp3" through "9.mp3"
Create a storyboard with 4 buttons on it (like the picture you posted.)
Set up button IBOutlets buttonA - buttonD. Put those buttons into an array:
let buttonsArray = [buttonA, buttonB, buttonC, buttonD]
Fill an array with the numbers 0-9. Shuffle it. Remove 4 values put them into an array "buttonValues" (use the method removeLast().) The code to generate non-repeating values from 0-9 might look like this:
var randomNumbers = [Int]() //Define an array to hold random Ints
var lastValueReturned: Int?
//Function to return a random Int. It won't return the same value twice
func randomNumber() -> Int {
//Remove and return an item from the array
var result: Int
repeat {
//If the array is empty, fill it with the shuffled numbers 0...9
if randomNumbers.isEmpty {
randomNumbers += Array(0...9).shuffled()
}
result = randomNumbers.removeLast()
} while result == lastValueReturned
lastValueReturned = result
return result
}
Loop through your array of buttonValues and install the string for each number as the title of one of your buttons:
for index = 0...3 {
buttonsArray[index].setTitle("(buttonValues[index])", forSate: .normal)
}
Pick an index 0-3 to be the "correct" number.
let indexToPick = Int.random(in: 0...3)
Look up that value in buttonValues, and use it to pick a sound file to play:
let numberToPick = buttonValues[indexToPick]
let soundName = "\(numberToPick).mp3"
Load and play the "tap the number" sound, and then Load and play the sound for the selected number (soundName).
When the user taps a button, have the IBAction method use the sender parameter that is passed to it, and look in the array of buttons, buttonsArray, to see which button index was tapped.
If it is the correct button, take the success action.
If the tapped button index is not indexToPick, do an animation that changes the background color of the button at indexToPick, or the button's border width, or something, and then animates it back to normal. (Look at the UIView animate(duration:) family of methods for how to animate the button's background color. Use the form that takes an options: parameter, and set the .autoreverse option.)
If you're a newbie to iOS development, figuring out how to animate your correct answer button could be a challenge. I created a sample project that just animates one of 4 random buttons: https://github.com/DuncanMC/ButtonAnimation.git
The code for that project is as follows:
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var buttonA: UIButton!
#IBOutlet weak var buttonB: UIButton!
#IBOutlet weak var buttonC: UIButton!
#IBOutlet weak var buttonD: UIButton!
//Define an empty array to hold buttons.
var buttonsArray = [UIButton]()
override func viewDidLoad() {
super.viewDidLoad()
//Put our button outlets into an array so we can reference them by index.
buttonsArray = [buttonA, buttonB, buttonC, buttonD]
//Give our buttons a cornerRadius so they look rounded when we add a border and fill color
for button in buttonsArray {
button.layer.cornerRadius = 10
}
}
#IBAction func handleAnimateButton(_ sender: UIButton) {
sender.isEnabled = false
//Pick a random button
let button = buttonsArray.randomElement()!
//Create an auto-reversing animation that fills the button with cyan, and draws a border around it.
//(Showing the border won't fade in and out, but it doesn't really matter)
UIView.animate(withDuration: 0.25,
delay: 0,
options: [.autoreverse, .curveEaseInOut],
animations: {
button.backgroundColor = .cyan
button.layer.borderWidth = 1.0
}, completion: {
success in
button.backgroundColor = .clear
sender.isEnabled = true
button.layer.borderWidth = 0
})
}
}
I would do as follows:
1. Create as many IBOutlets as your numbers (I suppose 0-9 for your example?) and link them to your buttons - E.g.
#IBOutlet weak var Button1: UIButton!
#IBOutlet weak var Button2: UIButton!
// Create as many as you need - Probably 10?
2. Create an IBAction and link it to all your buttons, with this code
#IBAction func checkCorrectAnswer(_ sender: UIButton) {
let arrayOfButtons:[UIButton] = [Button1, Button2] // Here you add all your buttons
let buttonTitle = sender.title(for: .normal)!
if buttonTitle == "YOUR CORRECT ANSWER" { //You have to substitute "YOUR CORRECT ANSWER" with the right string value
sender.backgroundColor = .green
} else {
sender.backgroundColor = .red
for i in arrayOfButtons {
if i.titleLabel?.text == "YOUR CORRECT ANSWER" { i.backgroundColor = .orange }
}
}
}
Enjoy!

ScrollView Constraint problem threw storyboard

So I maybe successfully created a scroll view following a tutorial but something is terribly wrong. So I'm trying to create a scroll view with a table view inside and some buttons and labels and everything works fine but as soon as I add a single constraint it all goes just white with no explanation. I would assume content view is messing things up but I'm not sure, thx in advance!
So following some other people problems I tried filling constraints programmatically and doing views and subviews programmatically aswell, keep in mind tho that rest of constraints I did on storyboard. Btw I have tried equal width and height on newView --> scroll view and nothing seems to change.
my view hierarchy looks like this
myViewController -> View -> scrollView -> newView
class ThirdViewController: UIViewController {
#IBOutlet weak var scrollView: UIScrollView!
override func viewDidLoad() {
super.viewDidLoad()
scrollView.addSubview(newView)
newView.leftAnchor.constraint(equalTo: scrollView.leftAnchor).isActive = true
newView.topAnchor.constraint(equalTo: scrollView.topAnchor).isActive = true
newView.rightAnchor.constraint(equalTo: scrollView.rightAnchor).isActive = true
newView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor).isActive = true
//tableView1.dataSource = self
//tableView1.delegate = self
//tableView1.register(UITableViewCell.self, forCellReuseIdentifier: "cell1")
}
#IBOutlet weak var newView: UIView!
override func viewWillLayoutSubviews() {
scrollView.contentSize = CGSize(width: 375, height: 1950)
}
}
Sorry, if question is layout pretty badly - I'm not that pro!

How to display lists of strings in array for one UILabel on Storyboard like tablecell (swift)

var comments: [String] = ["Good", "Great","Excellent","Cool"]
I would like to show comments within one UILabel (like tablecell), but I'm not sure it's possible. If possible, how can I achieve this.
I want to use UILabel as space for comments column.
example of image
If you want to add the array of those Strings to the single label then you can follow this approach:
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var lblDynamic: UILabel!
let stringsArray = ["Good", "Great","Excellent","Cool"]
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
lblDynamic.text = stringsArray.joinWithSeparator("\n")
lblDynamic.numberOfLines = self.stringsArray.count + 1
lblDynamic.lineBreakMode = NSLineBreakMode.ByWordWrapping
}
}

How to randomize UILabel text each time the view controller is showed

How do I make a label in my ViewController have a diffrent string of text each time the view crontroller is shown? Thanks! I'm using Swift 3
Assuming you know how to add UILabel to your ViewController, here is quick sample how to pick random text on start:
class ViewController: UIViewController {
let allTexts = ["Hey", "Hi", "Hello"]
#IBOutlet weak var label: UILabel! //get UILabel from storyboard
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.label.text = self.allTexts[Int(arc4random_uniform(UInt32(self.allTexts.count)))]
}
}
Adding this code to viewWillAppear will change your text anytime ViewController is about to appear - which means if you cover it with another ViewController (let's say popup) and then hide popup - it will change text.
If your prefer to just do it one time - when UIViewController is created put the same code inside viewDidLoad method.

UIButton inside table cell not changing attributes

I have a UIButton inside my cell together with an image and a text label. I manage to change the image and label programatically, but the UIButton does not seem to respond to anything except isHidden.
This is my code, the button that is not changing is followButton:
import UIKit
class ProfileTableCell: UITableViewCell {
#IBOutlet weak var name: UILabel!
#IBOutlet weak var profileImage: UIImageView!
#IBOutlet weak var followButton: UIButton!
override func awakeFromNib() {
super.awakeFromNib()
self.profileImage.layer.borderWidth = 0.0;
self.profileImage.layer.cornerRadius = self.profileImage.frame.size.width/2;
self.profileImage.clipsToBounds = true
self.profileImage.image = UIImage(named: "belt")
self.name.text = "Bar Refaeli"
self.followButton.layer.borderColor = UIColor.black.cgColor
self.followButton.layer.borderWidth = 3.0;
self.followButton.layer.cornerRadius = self.frame.size.width/4
self.followButton.backgroundColor = UIColor.black
}
func setCell(image: UIImage, name: String){
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
The profileImage and name outlets change the appearance fine, like mentioned above.
I also tried to remove the button and bring it back in, clean xcode project, remove the outlet reference and connecting it again. Pretty frustrated by now.
I also tried to change the background color of the button through the storyboard, just for testing, and it does not change it! what does change is the titleLabel and the text color.
awakeFromNib()- Prepares the receiver for service after it has been loaded from an Interface Builder archive, or nib file.
Given that, move your code to a view initiating method like viewDidLoad or viewDidAppear(_:)
Child objects that are attributes like textLabels act differently than child view objects.
Eventually I actually solved this by tossing the table view to the garbage and implementing the same needs using a collection view. there was no problem there..