Swift Compiler error while referencing existing variable [duplicate] - swift

This question already has an answer here:
Swift: expected declaration error setting "Label" to a string variable
(1 answer)
Closed 7 years ago.
I am trying to manually create some placeholder text for a UITextView, and when I try to set the placeholder text, I get a Swift compiler error. Xcode is telling me that it expected a declaration for pinContent where I first try to set it's text value. Here's my code:
class FirstViewController: UIViewController {
#IBOutlet var pinTitle: UITextField!
#IBOutlet var pinContent: UITextView!
#IBAction func createPin(sender: AnyObject) {
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
println(userLocation)
}
// Manually create a placeholder for the text view
pinContent.text = "Description" // This line is where I get my error
pinContent.textColor = UIColor.lightGrayColor()
// Change the text properties of the text view when the user begins editing, so it types in the normal black font
func textViewDidBeginEditing(textView: UITextView) {
if textView.textColor == UIColor.lightGrayColor() {
textView.text = nil
textView.textColor = UIColor.blackColor()
}
}
// If the user leaves the text view blank when they're done editing, re-set the placeholder
func textViewDidEndEditing(textView: UITextView) {
if textView.text.isEmpty {
textView.text = "Description" // Sometimes I get the same error here as well
textView.textColor = UIColor.lightGrayColor()
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}

The problem seems to be that you want to set the text outside of the scope of a method or a closure. Try this:
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
// Manually create a placeholder for the text view
pinContent.text = "Description" // This line is where I get my error
pinContent.textColor = UIColor.lightGrayColor()
println(userLocation)
}

Related

How can I add UIView to UITextView

I'm trying to append a UIView inside a UITextView. Visually speaking it would be some text, banner, more text.
This is what I tried:
// does nothing
text.textContainer.exclusionPaths = [UIBezierPath(rect: view.frame)]
// works but it also removes the text
text.addSubview(view)
This is my class
class ViewController: BannerController {
#IBOutlet weak var text: UITextView!
override func viewDidLoad() {
let view = UIView()
banners.append(view)
let myString = NSMutableAttributedString(string: "Text at the beginning\n")
super.viewDidLoad()
// text.textContainer.exclusionPaths = [UIBezierPath(rect: view.frame)]
// text.addSubview(view)
text.attributedText = myString
}
}
I also saw this https://github.com/vlas-voloshin/SubviewAttachingTextView, but I couldn't figure it out how to apply to my code.
Is it even possible? I'm new at Swift and I have no idea what to do.
If you want to use https://github.com/vlas-voloshin/SubviewAttachingTextView
Just follow below link:
https://github.com/vlas-voloshin/SubviewAttachingTextView/blob/master/Example.playground/Contents.swift

Xcode NSEException, signal SIGABRT can't figure it out

I'm very new to Xcode, and I'm working on this code where, basically, a specific label appears depending on which button is pressed. To make it simpler (I don't know how many buttons and labels I'll have ultimately), I created arrays for labels and buttons (I dragged the buttons and labels to the code as Outlet Collection).
Anyway, here is the code:
import UIKit
class ViewController: UIViewController {
//initialize everything
//labels first
#IBOutlet var labels: [UILabel]!
//buttons now
#IBOutlet var buttons: [UIButton]!
//pictures next
#IBOutlet var pic: UIImageView!
//function for all buttons
#IBAction func button_action(_ sender: UIButton) {
let propertyToCheck = sender.tag
for i in 0...buttons.count-1{
if buttons[i].tag != propertyToCheck{
labels[i].isHidden = true
}
else{
labels[i].text = "The right text"
if labels[i].isHidden == true {
labels[i].isHidden = false
} else {
labels[i].isHidden = true
}
}
}
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
var index = 0
//initialize view
//labels
for label in labels{
label.isHidden = true
}
//pics
pic.isHidden = true
//associate action for every button
for button in buttons {
button.tag = index// setting tag, to identify button tapped in action method
print("Hello", button.tag, buttons.count)
button.addTarget(self, action: #selector(button_action(_:)), for: UIControlEvents.touchUpInside)
index = index + 1
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
I'm getting the following error: "libc++abi.dylib: terminating with uncaught exception of type NSException" and when I look at the AppDelegate, I find this: "Thread 1: signal SIGABRT". Here is the hierarchy:
Again, I'm very new, so I'm guessing it's an error in calling something that doesn't exist or something with the connections, but I can't figure out what it is! I already looked online for possible solutions, like cleaning and rebuilding the project, but nothing has worked so far.
Any suggestion would be really appreciated!

How To Use UserDefaults with Bool (Swift) [duplicate]

I'm trying to save a bool value to UserDefaults from a UISwitch, and retrieve it in another view. However, I've tried following multiple tutorials and stack answers and none seem to work.
This is how I'm saving it:
class SettingsViewController: UITableViewController {
#IBOutlet weak var soundSwitchOutlet: UISwitch!
#IBAction func soundSwitch(_ sender: UISwitch) {
UserDefaults.standard.set(soundSwitchOutlet.isOn, forKey: "sound")
}
and this is how I'm trying to retrieve it in another view:
if let savedValue = UserDefaults.standard.bool(forKey: "sound") {
boolValue = savedValue
}
//this is inside viewDidLoad and "boolValue" was declared outside viewDidLoad//
For a reason this code is giving me errors and none of the things I've tried have worked. How can I save a bool to UserDefaults and retrieve it in another view?
Edit: I think I fixed the first part. However, the way I'm retrieving the boolean seems to be totally wrong. Also: No other stackExchange answer responds to what I'm asking, at least not in swift.
As Leo mentioned in the comments bool(forKey returns a non-optional Bool. If the key does not exist false is returned.
So it's simply
boolValue = UserDefaults.standard.bool(forKey: "sound")
Calling synchronize() as suggested in other answers is not needed. The framework updates the user defaults database periodically.
Do it like this.
In your first view controller.
create an IBoutlet connection to your UISwitch
And then the action for your UISwitch. so in the end, your first view controller should look like this.
import UIKit
class FirstViewController: UIViewController {
#IBOutlet weak var myswitch: UISwitch! // Outlet connection to your UISwitch (just control+ drag it to your controller)
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
#IBAction func myswitchAction(_ sender: Any) { // Action for your UISwitch
var myswitctBool : Bool = false // create a local variable that holds your bool value. assume that in the beginning your switch is offed and the boolean value is `false`
if myswitch.isOn == true { // when user turn it on then set the value to `true`
myswitctBool = true
}
else { // else set the value to false
myswitctBool = false
}
// finally set the value to user default like this
UserDefaults.standard.set(myswitctBool, forKey: "mySwitch")
//UserDefaults.standard.synchronize() - this is not necessary with iOS 8 and later.
}
}
End of the first view controller
Now in your second view controller
you can get the value of userdefault, which you set in first view controller. I put it in the viewdidload method to show you how it works.
import UIKit
class SecondViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let myswitchBoolValuefromFirstVc : Bool = UserDefaults.standard.bool(forKey: "mySwitch")// this is how you retrieve the bool value
// to see the value, just print those with conditions. you can use those for your things.
if myswitchBoolValuefromFirstVc == true {
print("true")
}
else {
print("false")
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
Hope this will help to you. good luck
Use this line of code:
#IBAction func soundSwitch(_ sender: UISwitch) {
UserDefaults.standard.set(soundSwitchOutlet.isOn, forKey: "sound")
}
insteadof :
#IBAction func soundSwitch(_ sender: UISwitch) {
UserDefaults.standard.set(soundSwitchOutlet, forKey: "sound")
}
Try this:
#IBAction func soundSwitchs(_ sender: Any)
{
UserDefaults.standard.set(soundSwitchOutlet.isOn, forKey: "sound")
UserDefaults.standard.synchronize()
}
//this is inside viewDidLoad and "boolValue" was declared outside viewDidLoad//
boolValue = UserDefaults.standard.bool(forKey: "sound")

Learning Swift & Xcode - #IBAction func reset for display if UITextField is empty

Disclaimer: I am teaching myself Swift & Xcode so my question is rather simple.
I'm building a simple application to get started, which has a text field connected to a String output.
The lesson I'm on currently has an excerpt which reads:
"The reset method simply needs to clear out the text of both the nameField and the lyricsView—you can do this by setting each of their text properties to an empty string."
I understand this probably involves an if statement, but I think the explanation on this is rather poor.
Here's the viewcontroller:
class ViewController: UIViewController {
#IBOutlet weak var nameField: UITextField!
#IBOutlet weak var lyricsView: UITextView!
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.
}
#IBAction func reset(_ sender: Any) {
}
#IBAction func displayLyrics(_ sender: Any) {
}
}
Can someone explain what they mean by setting the properties of nameField and lyricsView to an empty string in order to reset?
Thanks!
If you want to clear the text of a textField or a textView, just set the text property to an empty string. As your lesson hint:
The reset method simply needs to clear out the text of both the
nameField and the lyricsView—you can do this by setting each of their
text properties to an empty string.
The reset method should like this:
#IBAction func reset(_ sender: Any) {
nameField.text = ""
lyricsView.text = ""
}
To clear those fields I'd use:
#IBAction func reset(_ sender: Any) {
nameField?.text = ""
lyricsView?.text = ""
}
The question mark will safely execute the code even if, for some reasons, those fields are not loaded yet, or have been freed or removed.
ADD this to reset method to remove the content:-
nameField.text = ""
lyricsView.text = ""
When you enter something into nameField something shows up in your lyricsView. So, there should be a way to clear what you've entered (and what is displayed). Hence, the reset function (I guess it's bound to a button).
Once you hit reset the text in nameField and lyricsView should disappear. You can do this by assigning both to something called an empty string, which is just two double-quotes:
let anEmptyString = ""
You'd need to assign the "" to the nameField and lyricsView text property.

Why is my prepareForSegue code activating the wrong button?

I'm learning how to program and am playing with a Swift project in Xcode. The main storyboard has two view controllers. The first view controller is simply called ViewController and the second view controller is called HelpScreenViewController.
In ViewController I have a "help" button that switches the user to HelpScreenViewController. This button uses a segue called "goToHelpScreenSegue".
In HelpScreenViewController I have three buttons:
"Close" button to dismisses the view (no segue used)
"Send Feedback" button to generate a new email in the Mail app (no segue used)
"Reset Game" button to call a function that is coded within the first ViewController. This third button uses a segue called "resetGameSegue".
What I'm trying to do is...
...Get the "Reset Game" button on the HelpScreenViewController to reset the game by calling a function that's coded within the first view controller.*
To try and get this to work the way I want, I've used the following code:
WITHIN first main ViewController
import UIKit
import iAd
import AdSupport
import AVFoundation //audio
import GameplayKit
class ViewController: UIViewController, ADBannerViewDelegate, MyResetGameProtocol {
#IBOutlet weak var Banner: ADBannerView!
#IBOutlet weak var buttonA: UIButton!
#IBOutlet weak var buttonB: UIButton!
#IBOutlet weak var buttonC: UIButton!
#IBOutlet weak var buttonD: UIButton!
#IBOutlet weak var labelQuestion: UILabel!
#IBOutlet weak var labelScore: UILabel!
#IBOutlet weak var labelTotalQuestionsAsked: UILabel!
#IBOutlet weak var labelFeedback: UILabel!
#IBOutlet weak var buttonNext: UIButton!
var score :Int! = 0
var totalquestionsasked :Int! = 0
var allEntries : NSArray!
var shuffledQuestions: [AnyObject]!
var nextQuestion = -1
var currentCorrectAnswerIndex : Int = 0
var audioPlayer = AVAudioPlayer()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.Banner?.delegate = self
self.Banner?.hidden = true
LoadAllQuestionsAndAnswers()
if #available(iOS 9.0, *) {
shuffledQuestions = GKRandomSource.sharedRandom().arrayByShufflingObjectsInArray(allEntries as [AnyObject])
nextQuestion++
LoadQuestion(nextQuestion)
// Fallback on earlier versions
}else{
let randomNumber = Int(arc4random_uniform(UInt32(allEntries.count)))
LoadQuestionPreiOS9(randomNumber)
}
LoadScore()
AdjustInterface()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
let viewController = segue.destinationViewController as! HelpScreenViewController
viewController.controller = self
}
func ResetGame() {
PlaySoundReset()
score = 0
totalquestionsasked = 0
SaveScore()
LoadScore()
}
func PlaySoundReset()
{
let alertSound = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("pcbeep", ofType: "wav")!)
do {
audioPlayer = try AVAudioPlayer(contentsOfURL: alertSound)
} catch {
}
audioPlayer.prepareToPlay()
audioPlayer.play()
}
func SaveScore()
{
let defaults = NSUserDefaults.standardUserDefaults()
defaults.setInteger(score, forKey: "Score")
defaults.setInteger(totalquestionsasked, forKey: "Out of")
}
func LoadScore()
{
let defaults = NSUserDefaults.standardUserDefaults()
score = defaults.integerForKey("Score")
totalquestionsasked = defaults.integerForKey("Out of")
labelScore.text = "Score: \(score)"
labelTotalQuestionsAsked.text = "out of \(totalquestionsasked)"
}
and so on....
WITHIN the second HelpScreenViewController
import UIKit
protocol MyResetGameProtocol {
func ResetGame()
}
class HelpScreenViewController: UIViewController, MyResetGameProtocol {
var controller: MyResetGameProtocol? // reference to the delegate alias First Controller
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
}
*/
#IBAction func SendFeedback(sender: AnyObject) {
UIApplication.sharedApplication().openURL(NSURL(string: "mailto:feedback#felice.ws?")!)
}
#IBAction func DismissView(sender: AnyObject) {
self.dismissViewControllerAnimated(true, completion: nil) }
#IBAction func buttonResetGame(sender: AnyObject) {
controller.ResetGame()
}
}
Now, at the moment with the above code what happens is that if the user taps the "help" button in the first main ViewController (i.e. goToHelpScreenSegue), not only does it take the user to the help screen, but it also calls the function I want activated when the user taps on the "Reset Game" button instead. That is, at the moment, it's the "help" button that resets the game before taking the user to the help screen.
Now, within the help screen, the first two buttons work normally (but they're not using segues). Tapping on the third button (the Reset Game one) simply returns the user back to the main screen. It doesn't call the function, doesn't reset the game.
I've lost count of the times I've changed the code around to try and get it to work right, but I've obviously missed something really obvious.
In particular, I've tried using the following code instead within the main ViewController:
override func prepareForSegue(segue: UIStoryboardSegue?, sender: AnyObject?) {
if segue?.identifier == "resetGameSegue" {
let viewController = segue!.destinationViewController as! HelpScreenViewController
viewController.controller = self
}
However, this results in nothing happening. What I mean is that the button on the main screen works properly (taking the user to the help screen and not incorrectly calling the resetGame function). And, within the help screen the first two buttons work as expected, but the "Reset Game" button just returns the user to the first screen but without calling the ResetGame function.
I also tried removing the IBActions from both my code and the connections inspector for the "Reset Game" button, but that made no difference either.
Any assistance would be most appreciated as I'm just not getting it! :(
I'm agree with MikeG, that you should probably learn about how delegates should be implemented. But the thing you're doing wrong inside this code is that you're not actually calling ResetGame() function on your delegate. Try to implement your #IBAction function in this way:
#IBAction func buttonResetGame(sender: AnyObject) {
controller?.ResetGame()
}
And yeah, if I understand your logic correctly your HelpScreenViewController should not implement MyResetGameProtocol cause your ViewController is the one who's implementing it.