Everyone,
I'm trying to understand why the exemple 1 return nil ( don't call a goooo function ), and the second exemple call it. Do I need to do something extra ?
Exemple 1 :
class A: UICollectionViewCell {
var exempleOneDetail: ExempleOneDetail?
...
}
func handleZoomTap(_ tapGesture: UITapGestureRecognizer) {
self.exempleOneDetail?.goooo(imageView)
}
=>> Result Nil
Exemple 2 :
func handleZoomTap(_ tapGesture: UITapGestureRecognizer) {
let exempleOneDetail = ExempleOneDetail()
exempleOneDetail?.goooo(imageView)
}
=>> Result : Call de function goooo
Thanks for help,
Regards
In example 1, you're never setting exempleOneDetail to anything before you call goooooo() on it, so it's nil.
In example 2, you're creating a local variable called exempleOneDetail and assigning an initialized object to it, and then calling goooooo(), so it does what you expect. However, be aware that your local copy, because it has the same name as the instance variable, is shadowing that variable, and if you try to use exempleOneLabel anywhere outside of handleZoomTap(), it will still be nil because you never assigned anything to it.
Related
I'm creating an app which chooses two random cards out of a 52-card deck. Then, if one of the card is strong (in my case, strong cards are "10" or stronger) I want it to show an image "yes" (tick). If both of the cards are weak, then I want it to show an image "no" (cross). I've been trying to find a problem, but every time I change something, a new type of error occurs.
I tried to set an unknown output type in func resultOfShuffle, I tried creating and naming an outlet for my UIImageView couple of times.
let cardArray = ["1.png", (...), "52.png"]
// All of the cards, from 2 to Ace (with every color). Number "33" is a card 10.
...
let cardResults = ["yes.png"]
...
#IBOutlet weak var theResult: UIImageView!
...
func randomizeCards() {
chooseCardOne = Int.random(in: 0 ... 51)
chooseCardTwo = Int.random(in: 0 ... 51)
...
func resultOfShuffle(firstCard : Int, secondCard : Int) -> UIImageView {
if firstCard > 33 {
return theResult.image = UIImage(named: cardResults)
}
}
And now, the return of the last func resultOfShuffle is wrong - telling me: Use of unresolved identifier 'theResult'. I also tried to find the solution to this problem, but it is kinda tricky and I don't get it.
That's how my app looks like:
https://imgur.com/a/kjdcqcO
Is every statement executed in the same ViewController?
It should recognize theResult as a UIImageView, then.
Update
The problem is, as solved in the comments, based on the scope of the function declaration. Since it is declared outside of the class where theResult is defined, it can't get access to it.
The solutions could be passing the variable as an argument to the function, or declaring the function in the same scope of the variable - inside the ViewController.
Other notes
You are, anyway, trying to return something with this line:
theResult.image = UIImage(named: cardResults)
which doesn't evaluate to a type, but simply sets the image of the view to what's in cardResults. Therefore, you shouldn't return anything, but merely using this function in order to update the content of the view - this means you should use a Void return type.
Furthermore, you are passing to the image initializer a [String] type, while you should just pass a String.
Try something like this:
func resultOfShuffle(firstCard : Int, secondCard : Int) {
if firstCard > 33 {
theResult.image = UIImage(named: cardResults[0])
}
}
When a gameOver() function is triggered, I would like all variables to reset to their original, unchanged values (as in, the values that are assigned in the ViewController file) when a user presses a Restart button. How can I do this?
Depending on the specific variables you have, one solution would be to create a struct with the fixed initial values and assign those to your active game variables in the Restart function.
You can define a function that reset the variables to the default value like this :
func resetGame(){
score = 0 // or default value
life = 3 // or default value
//.... and so on
}
Assume the restart button are connected to this function
#IBAction func restartGame(sender: UIButton){
gameOver()
resetGame()
}
you can call this function after calling gameOver() inside the restart button function.
If your question is about how to declare default values you can use struct as Jay said like this :
struct DefaultValues {
let score = 0
let lifes = 3
let level = 1
}
and resetGame() will be like this :
func resetGame(){
score = DefaultValues().score
life = DefaultValues().life
level = DefaultValues().devel
}
I have a feeling there is more than one problem with this code, but my first issue is that my delegate returns nil and I do not know why. First, is my delegate:
import UIKit
//delegate to move information to next screen
protocol userEnteredDataDelegate {
func userDidEnterInformation(info:NSArray)
}
Next, I have a var defined for the delegate and I believe the ? makes it an optional variable? This is defined inside the class
var dataPassDelegate:userEnteredDataDelegate? = nil
Now, after my user has entered information into the fields in the view, I want to add those field values to an array and then pass that array on to the next view where it will be added to. I have pieced this code together from some YouTube examples but I think I am missing a needed part. When do I assign some kind of value to the dataPassDelegate var so it is not nil when the if statement comes? Do I even need that if statement?
if blankData != 1 {
//add code to pass data to next veiw controller
enteredDataArray = [enterDate.text, enterSeason.text, enterSport.text, enterDispTo.text]
//println(enteredDataArray)
self.appIsWorking ()
if (dataPassDelegate != nil) {
let information: NSArray = enteredDataArray
println(information)
dataPassDelegate!.userDidEnterInformation(information)
self.navigationController?.popViewControllerAnimated(true)
} else {
println ("dataPassDelegate = nil")
}
//performSegueWithIdentifier("goToDispenseScreenTwo", sender: self)
activityIndicator.stopAnimating()
UIApplication.sharedApplication().endIgnoringInteractionEvents()
}
blankData = 0
}
Your help is appreciated.
A delegate is a pointer to another object that conforms to a particular protocol. Often you use delegates to refine the behavior of your class, or to send back status information o the results of an async network request
When you set your dataPassDelegate delegate is up to you.
What is the object that has the dataPassDelegate property? What object will be serving as the delegate?
You need to create 2 objects (the object that will be serving as the delegate, and the object that has the dataPassDelegate property) and link them up.
We can't tell you when to do that because we don't know what you're trying to do or where these objects will be used.
I am using a simple function to call a random image when a view controller is loaded.
override func viewDidLoad() {
super.viewDidLoad()
var randomtest = ReturnRandom()
mainImage.image = UIImage(named: randomtest)
}
I want a button's action to be based on what image was displayed. For example
#IBAction func Button1(sender: AnyObject) {
switch randomtest {
case 1: //Do something here
case 2: //Do something different here
default:
}
However I can not figure out how to get the value of "randomtest" out of ViewDidLoad. I also can not seem to create the random number outside the ViewDidLoad then pass the variable in. Sorry I'm new to all this, iOS development is a long way away from php...
The reason I was having trouble declaring the result of my function as a instance variable is that my function is also an instance function. I can not call it, there has been no instance. So this
class ViewController : UIViewController {
var randomtest: Int = ReturnRandom();
Will return a "Missing argument for parameter #1 in call"
For more details please check out this very helpful thread on setting initial values. Since my function was so simple I just computed the property while setting the initial value, no need for an additional class level function.
dynamic var randomtest:String {
let imageNumber = arc4random_uniform(3)
var imageString = String(imageNumber)
return (imageString)}
Hope this helps someone.
I want to run different functions depending on selected level Integer
so if selected level is 1 then runfunc1(), if 2 then runfunc2()...
I know this is possible using if else
if levelselected == 1 {
runfunc1()
} else if levelseletecd == 2 {
runfunc2()
// ... and so on
}
Is there any better way than this, perhaps something like this
runfunc%i(),levelselected // I know its not correct but something similar
I dont want to write new code for every level, so any better way?
You can use something like:
var levelSelected = 0 //
var selector = Selector("runFunc\(levelSelected)")
if self.respondsToSelector(selector) {
NSThread.detachNewThreadSelector(selector, toTarget: self, withObject: nil)
}
You could have an array or dictionary of functions. A dictionary might be nicer since the logic for checking if the level is valid is a lot simpler:
let funcs = [1: runfunc1, 2: runfunc2]
if let funcToRun = funcs[levelselected] {
funcToRun()
}
However, you won't be able to easily dynamically build a function name from strings and numbers without using #objc functionality.
(except in the sense that you could make the key to the dictionary a string of the function name, but you still have to build the dictionary using actual function names determined at compile time)
That said, you can add to the funcs variable from elsewhere in the code so it does mean to can "hook up" new levels without changing this dispatching logic.
Not the exact solution you are looking for but this can make it easier :
Declare an array of the desired functions:
var levelFunctions: [()->()] = [runfunc1, runfunc2, runfunc3]
This syntax declares an array of functions that have zero argument and return nothing. You initialize this array with the required function names and then execute the desired function using the levelselected variable:
levelFunctions[levelselected]() // Or levelselected-1 if the variable is not zero-based
EDIT:
As Airspeed Velocity mentioned in the comment and his answer you should make sure the level is in the array bounds.
I prefer to create a function, for example runFuncFromLevel::Int -> (() -> Void). runFuncFromLevel return a proper function that you need.
func runFuncFromLevel(level: Int) -> () -> Void
{
switch level
{
case 1: return runfunc1
case 2: return runfunc2
default: return {}
}
}