I am trying to add a photo reveal quiz piece to a larger app that I'm creating. The picture of the set up looks like this so far(rough draft so to speak)
The 16 labeled items are there just to give a sense of the end product(they will be white tiles in the app). How can I program it so that they begin disappearing when they user taps reveal picture? NSTimer? Should they be labels or UIViews or ?? Thanks for any hints.
I can get this far, but would want to add code to make the tiles disappear randomly and roughly each second
import UIKit
class ViewController: UIViewController {
var gameTimer : NSTimer!
#IBOutlet weak var imageView: UIImageView!
#IBOutlet weak var tile15: UILabel!
#IBOutlet weak var tile16: UIView!
#IBOutlet var photoTilesHandler: [UIView]!
//#IBOutlet weak var viewTile: UIView!
//#IBOutlet var pictureTiles: [UILabel]!
#IBOutlet var buttonHandler: [UIButton]!
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func revealButton(sender: AnyObject) {
Hide()
print("button pressed")
}
func Hide() {
var dispatchTime: dispatch_time_t = dispatch_time(DISPATCH_TIME_NOW, Int64(1 * Double(NSEC_PER_SEC)))
dispatch_after(dispatchTime, dispatch_get_main_queue(), {
self.tile15.hidden = true
})
}
override func viewDidDisappear(animated: Bool) {
gameTimer.invalidate()
}
}
Put all of your UILabels/UIViews/etc in an IBOutletCollection. Then inside of dispatch_after's callback do the following steps:
0.- You might want to keep track of which tiles are already facedown. So this way you can know at every time which index you have already used and pick always new ones.
One way to achieve this is storing the full list of indexes available to select and instead of taking into account your IBOutletCollection for the following steps take as reference your unused indexes list and, after you randomly pick one, remove it from the list.
1.- Determine a/(a set of) random integers between 0...[your IBOutletCollection].length - 1]
2.- Use this numbers as an index to set the hidden property of [your IBOutletCollection] corresponding element to true
As your other question, my recommendation would be to use UIViews with your UILabel inside or UIButtons. The tap zone of labels is a bit hard to use.
Related
I have a view that contains labels, and have a button to change the values of the labels. Instead of changing the values one by one in the button, how can I reload the whole view to update the labels.
#IBOutlet weak var one: UILabel!
#IBOutlet weak var two: UILabel!
#IBOutlet weak var three: UILabel!
....
#IBOutlet weak var updateLabels: UIButton!{
//doing something to change the value of the labels
//then wanna reload the whole view
viewDidLoad()
}
I had called the viewDidLoad() method, but didn't work.
You should never call viewDidLoad yourself. It's a framework function that the OS calls, as an indication that your views are ready to be setup.
It would serve better if you separated your function
func updateLabels() {
one.text = "one"
two.text = "two"
three.text = "three"
}
and now you can call the updateLabels function when you want.
Why dont you put all labels on a method. and fire it when ever you need to reload.
override func viewDidLoad() {
super.viewDidLoad()
updateLabels()
}
func updateLabels() {
one.text = "one"
two.text = "two"
three.text = "three"
}
#IBAction func updateLabels(_ sender: Any) {
updateLabels()
}
Your method of updating your labels is incorrect. What you need to do is as follows:
Declare your labels like you did ensuring they are linked in Interface Builder:
//Declare The Labels
#IBOutlet var one: UILabel!
#IBOutlet var two: UILabel!
#IBOutlet var three: UILabel!
Then create an IBAction function which is triggered by a UIButton:
/// Set The Text Labels Text
#IBAction func updateLabelText(){
//Set Label Text
one.text = "one"
two.text = "two"
three.text = "three"
}
Of course remembering to link this to the UIButton instance in Interface Builder.
Hope this helps.
I searched the whole internet but only found solutions for Swift 2 or outdated Xcode versions which doesnt help me :/
Also Im very new to Xcode and Swift, so please excuse that.
I want the user to input some numbers in several UITextFields and then press a "calculate" button which shows the result in a UILabel.
What I tested so far:
Convert input data to Integer in Swift
Swift calculate value of UITextFields and return value
So my code looks really poor so far. Nothing worked so thats all I have and the comment shows how I want it to be:
import UIKit
class ViewController: UIViewController {
//elements from the viewcontroller
#IBOutlet weak var input1: UITextField!
#IBOutlet weak var input2: UITextField!
#IBOutlet weak var calculate: UIButton!
#IBOutlet weak var output: UILabel!
//calculation
//Just simple math like
//output = input1 + input2
//or output = (input1 + 50) + input2
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Thank you for helping me out =)
First of all, you need to create an IBAction for your button by dragging from Storyboard. I think it is not a problem.
//imagine this is your IBAction function on calculate click
#IBAction func calculate(_ sender: UIView) {
output.text = String(Int(input1.text!)! + Int(input2.text!)!)
}
I skipped all validations, but for the happy path it should work
Connect your calculate button to below action.
#IBAction func calculate(sender: Any) {
let result = Int(input1.text!) + Int(input2.text!)
output.text = "\(result)"
}
I'm trying to change the application language using two buttons, First I used this code in this link : https://github.com/marmelroy/Localize-Swift/blob/master/Sources/Localize.swift
Localize.swift and placed it in my project ,
And here is the code of the table view controller that has two buttons and two lables :
import UIKit
class MyTableViewVontroller: UITableViewController {
#IBOutlet weak var firstLabel: UILabel!
#IBOutlet weak var secondLabel: UILabel!
#IBOutlet weak var arabicChanger: UIBarButtonItem!
#IBOutlet weak var englishChanger: UIBarButtonItem!
override func viewDidLoad() {
super.viewDidLoad()
populateValues()
}
#IBAction func englishChanger(sender: AnyObject) {
Localize.setCurrentLanguage("en")
}
#IBAction func arabicChanger(sender: AnyObject) {
Localize.setCurrentLanguage("ar")
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func populateValues(){
firstLabel.text = NSLocalizedString("PETRA",comment: "")
secondLabel.text = NSLocalizedString("AMMAN",comment: "")
}
}
But when I run it and press any of the buttons nothing changes. Even though localization works just fine as I have a Strings files for both languages and when changing language from the system it works, but it doesn't when the buttons are pressed.
let me first quote what the library's github information page says
To update the UI in the viewcontroller where a language change can
take place, observe LCLLanguageChangeNotification :
you have to add an observer for this to change, to know how an observer works,get your self familiar with NSNotificationCenter
by the way, I don't recommend to use a third party library in this case, just go with the standards for simple tasks, try using the default NSLocalizedString localization, it's great !
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var userGuessTextField: UITextField!
#IBOutlet var resultLabel: UIView!
#IBAction func Guess(sender: AnyObject) {
let diceRoll = String(arc4random_uniform(6))
if diceRoll == userGuessTextField.text
{
resultLabel.text = "You are right"
}
else
{
resultLabel.text = "You are "
}
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
Can anyone help me? Why I am getting this error as I am a beginner to iOS and learning this language.
please change...
#IBOutlet var resultLabel: UIView!
to
#IBOutlet var resultLabel: UILabel!
You are setting outlet like #IBOutlet var resultLabel: UIView!, It is type of UIView, so your resultLabel object is of UIView and it's not have property text
I think you should take outlet of UILabel instead of UIView.
So, drag a label in interface builder - ctrl + drag from it to class (in assistant editor) - and give outlet name.
Hope this will help :)
From Apple documents:
The UIView class defines a rectangular area on the screen and the interfaces for managing the content in that area.
... More sophisticated content can be presented by subclassing UIView and implementing the necessary drawing and event-handling code yourself. The UIKit framework also includes a set of standard subclasses that range from simple buttons to complex tables and can be used as-is. For example, a UILabel object draws a text string and a UIImageView object draws an image.
Remove the resultLabel from your storyboard/xib (delete the UIView and drag a new UILabel ) and from code change:
from:
#IBOutlet var resultLabel: UIView!
to
#IBOutlet var resultLabel: UILabel!
Then connect your new UILabel to the IBOutlet writed on code.
I have an experience where a user is rating a product, they do this by dragging sliders. Each slider has a related UILabel for the title and a UILabel for the value. I would like to avoid creating 12 functions, one for each slider and the associated label. I am new to development generally. I am guessing a class or an Array would be useful here, but am not sure how to use either. Here's the code that just updates the one value, and I know why that is, I'm just hoping to avoid declaring 12 variables for the value and 12 functions for each one.
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var slider1: UISlider!
#IBOutlet weak var value1: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func sliderSlide(sender: UISlider) {
value1.text = round(sender.value*100).description
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
Well,you can use Outlet Collection and 'tag',
Drag every label into a same Outlet Collection
Drag every Slider IBAction into a same function
Then set the tag of slider as the index of label in Outlet Collection.
For example,you first drag labelA to Collection,then the tag is 0
Then all the code
import UIKit
class ViewController: UIViewController {
#IBOutlet var labels: [UILabel]!
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func sliderSlide(sender: UISlider) {
let index = sender.tag
let label = labels[index]
label.text = round(sender.value*100).description
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
You can connect more than one slider to the same function. That's the purpose of the sender argument. You can do a switch statement on the pointer in swift, or by a set tag of the slider if you prefer. If it's all updating the same label, why even care which slider is updating?
I can think of two ways of doing this. Make a custom view controller that looks exactly the same as the code you have. It will have the slider and label as subviews. Then you'd only have 12 container views on your storyboard (not the greatest).
The other way would be using IBOutletCollections. These are what they sound like, collections of IBOutlets. Assign each slider that you place on the storyboard a unique tag from 0-11 (this is done under the attributes inspector). The tag will act as an index for the values array. Make sure that when you add each label to the collection, you do it in the correct order (it does matter!). Using IBOutletCollections, your code would look like this:
class ViewController: UIViewController {
#IBOutlet weak var sliders: [UISlider]!
#IBOutlet weak var values: [UILabel]!
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func sliderSlide(sender: UISlider) {
values[sender.tag].text = round(sender.value*100).description
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}