Swift: Help on Extensions - ios

class quizController: UIViewController {
#IBOutlet weak var questionLabel: UILabel!
#IBOutlet weak var button1: UIButton!
#IBOutlet weak var button2: UIButton!
#IBOutlet weak var button3: UIButton!
#IBOutlet weak var button4: UIButton!
var question : String
var options : [String]
var correctAns : Int
init() {
question = "What quiz are you taking?"
options = ["Medical", "Bollywood", "Math", "Trivia"]
correctAns = 0
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
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.
}
}
extension CollectionType where Index == Int{
func shuffle() -> [Generator.Element] {
var readyToAskQuestions : [quizController] {
var questions = Array(question)
questions.count = questionNum
questions.shuffleInPlace()
return questions
}
convenience init() {
}
}
In the var questions line, I'm getting an error saying that
'question' is an unresolved identifier
I know that the function isn't in the quizController class and that's why, but I need that extension so that I can shuffle my quiz questions.
How should I approach this? Also, I'm gonna load the quiz questions from a json file and that's why there's a convenience init method there, but I'm getting an error stating that
initializers can only be declared within a type..
so that means it needs to be within a class?
Thanks for the help.

Try this instead of your code
var question = String()
var options = [String]()
var correctAns = Int()

Related

ui label not printing the value

Good morning. Why my code doesn't change the value of UILabel? When I click the UIButton the function has to multiply the Int value of the variable meters, filled as text, by 3 and show it in the UILabel.
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var meters: UITextField!
#IBOutlet weak var button: UIButton!
#IBOutlet weak var answer: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
#IBAction func buttonClicked(_ sender: UIButton) {
answer.text = String(calculateNumber(meters: Int(meters.text ?? "") ?? 0));
}
func calculateNumber(meters : Int) -> Int {
let result = meters
print(result)
return result;
}
}
Check the code, it should work.
Check that meters are connected correctly.

Better way of handling xib button press than chained delegates?

I have implemented some code including protocols to chain the active instance up to the VC to allow for Segues and am wondering if there's a better way to solve this problem or if I'm handling the Segue the wrong way.
Segues within child classes do not work because they are not in the primary VC
Excerpt from VC file
class ViewController: UIViewController, UITableViewDelegate, TableViewControllerDelegate {
func didButtonPressed() {
performSegue(withIdentifier: "destStory", sender: self)
}
override func viewDidLoad() {
super.viewDidLoad()
tableViewController.delegate = self
}
}
protocol TableViewControllerDelegate {
func didButtonPressed()
}
class TableViewController: UITableViewController, TableViewCellDelegate {
func didButtonPressed() {
delegate?.didButtonPressed()
}
let test = ["test1", "test2", "test3"]
var instanceOf = self
var delegate: TableViewControllerDelegate?
Excerpt from cell file
protocol TableViewCellDelegate {
func didButtonPressed()
}
class TableViewCell: UITableViewCell {
var delegate: TableViewCellDelegate?
#IBOutlet weak var labelOne: UILabel!
#IBOutlet weak var labelTwo: UILabel!
#IBOutlet weak var buttonOne: UIButton!
#IBAction func buttonOnePressed(_ sender: Any) {
delegate?.didButtonPressed()
}
This functions the way I'd expect but seems potentially confusing to work with.
Another option is using closures instead of delegate.
class TableViewCell: UITableViewCell {
var buttonPressedClosure: (() -> Void))?
#IBOutlet weak var labelOne: UILabel!
#IBOutlet weak var labelTwo: UILabel!
#IBOutlet weak var buttonOne: UIButton!
#IBAction func buttonOnePressed(_ sender: Any) {
buttonPressedClosure?()
}
}
Also, you can add target action for cell's button inside cellForRow UITableViewDelegate function directly, but it is a dirty way in my opinion.
let cell = ...
cell.button.addTarget(self, action: #selector(didButtonPressed), for: .touchUpInside)

Swift Delegate returns unexpectedly found nil while unwrapping an Optional value

Setting up my delegate within the protocol continues to throw nil. I have attempted numerous approaches suggested in other posts. I am attempting to get my protocol + delegate up and running, however, unable to solve why it continues to throw nil.
Force unwrapping, calling the delegate from various locations in the file, removing & adding Weak Var.
List View:
protocol MixPlayer : class {
func playMix(message: String)
}
class IssueViewController: UIViewController {
#IBOutlet weak var issueCollection: UICollectionView!
#IBOutlet weak var issueImage: UIImageView!
var viewController: ViewController?
var collectionViewtitle: String?
var mixImageName: String?
var mixList: [[String: String]]!
weak var mixDelegate: MixPlayer?
override func viewDidLoad() {
super.viewDidLoad()
issueCollection.dataSource = self
issueCollection.delegate = self
}
}
....
extension IssueViewController: UICollectionViewDelegate, UICollectionViewDataSource {
....
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
if let url = mixList[indexPath.row]["url"] {
mixDelegate?.playMix(message: url)
}
}
}
View Controller:
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var mainContainer: UIView!
#IBOutlet weak var playerEmbedView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
let secondVC = IssueViewController()
secondVC.mixDelegate = self
}
}
extension ViewController: MixPlayer {
func playMix(message: String) {
print(message)
}
}
Any attempt at calling
mixDelegate?.playMix(message: url)
Is unsuccessful. Currently I'm just trying to log basic print statements.
Probably your secondVC inside the ViewController gets deallocated. Make that a property in your ViewController.
class ViewController: UIViewController {
#IBOutlet weak var mainContainer: UIView!
#IBOutlet weak var playerEmbedView: UIView!
lazy var secondVC: IssueViewController = {
let secondVC = IssueViewController()
secondVC.mixDelegate = self
return secondVC
}()
override func viewDidLoad() {
super.viewDidLoad()
}
...
}
To know if your class gets deallocated, add a deinit with a print statement on it.
deinit {
print("Deallocated")
}

"fatal error" when calling tableView.reloadData(), the tableView is properly connected

I am trying to dynamically update a tableView while the program is running. I believe I have updated the array that the data loads from correctly, but when I press the button that calls self.eventTable.reloadData() I receive the error:
fatal error: unexpectedly found nil while unwrapping an Optional value
Here is the relevant code:
View Controller:
import UIKit
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
//Timer view
#IBOutlet weak var playButton: UIBarButtonItem!;
#IBOutlet weak var pauseButton: UIBarButtonItem!;
#IBOutlet weak var refreshButton: UIBarButtonItem!;
#IBOutlet weak var timerLabel: UILabel!
var counter = 0
var timer = Timer()
var isTimerRunning = false
//testing view container
var viewShowing = 1;
override func viewDidLoad() {
// Do any additional setup after loading the view, typically from a nib.
pauseButton.isEnabled = false
hideAll();
self.basicContainer.isUserInteractionEnabled = true;
self.basicContainer.isHidden = false;
self.timerLabel.text = String("00:00:00");
eventTable.dataSource = self
eventTable.delegate = self
super.viewDidLoad()
loadEvents(event: "timer start")
}
...
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// Add table to keep track of events
#IBOutlet weak var eventTable: UITableView!
var eventData = [Session]()
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return eventData.count;
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cellReuseIdentifier") as! eventTableViewCell
let event = eventData[indexPath.row]
cell.eventLabel.text = event.session
return cell
}
private func loadEvents(event: String) {
guard let event1 = Session(session: event) else {
fatalError("Unable to instantiate event")
}
eventData += [event1]
DispatchQueue.main.async() {
self.eventTable.reloadData()
}
}
func testPrint() {
loadEvents(event: "testing cell adding")
//self.eventTable.reloadData()
viewWillAppear(false)
print("This is a test print");
}
}
The function works fine when it is called in ViewDidLoad(), but not when it is called by the button in another class ("This is a test print" prints to console so I know the button call is going through).
Expected behavior is the tableView (eventTable) reloading showing two cells, "timer start" and "testing cell adding" (ideally with "testing cell adding" being at the top).
Also want to emphasize that eventTable is connected to the storyboard, which seems to be a common problem on here.
Here is the Session.swift file and the eventTableViewCell.swift file if those are helpful:
Session.swift
import Foundation
import UIKit
class Session {
//MARK: Properties
var session: String
//MARK: Initialization
init?(session: String) {
guard !session.isEmpty else {
return nil
}
self.session = session
}
}
eventTableViewCell.swift
import Foundation
import UIKit
class eventTableViewCell: UITableViewCell {
//MARK: Properties
#IBOutlet weak var eventLabel: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
Thanks!
Edit: The ViewController from where I call testPrint().
import UIKit
class BasicViewController: UIViewController {
var VC = ViewController();
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.
}
//Basic buttons
#IBOutlet weak var warmButton: UIButton!
#IBOutlet weak var dryButton: UIButton!
#IBOutlet weak var stimulateButton: UIButton!
#IBOutlet weak var controlButton: UIButton!
#IBOutlet weak var bedButton: UIButton!
#IBOutlet weak var tempButton: UIButton!
#IBOutlet weak var pulseButton: UIButton!
#IBOutlet weak var ecgButton: UIButton!
#IBOutlet weak var apgarButton: UIButton!
#IBOutlet weak var helpButton: UIButton!
//APGAR options
#IBOutlet weak var skinColor: UIButton!
#IBOutlet weak var pulse: UIButton!
#IBOutlet weak var grimace: UIButton!
#IBOutlet weak var flexion: UIButton!
#IBOutlet weak var respiratoryEffort: UIButton!
#IBAction func warmButton(sender: AnyObject) {
VC.testPrint();
}
}
It would seem that you are all right in stating that I am instantiating a new ViewController which is causing the issue. How should I go about fixing this? Fairly new to Swift
I think, your problem is in this lines of codes:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cellReuseIdentifier") as! eventTableViewCell
let event = eventData[indexPath.row]
cell.eventLabel.text = event.session
return cell
}
Can you check the cell identifier is same as your cell identifier
And number of rows in eventData array

Swift delegate not working

I have a stepper in my ViewController that controls the value of a variable in my UIView. When I reset the variables to 0 in my UIView, I also want the stepper and label to reset, but they won't. I tried using a delegate, but am getting an error. Thanks in advance!
ViewController:
protocol CircleViewDelegate: class {
func updateStepper(view: CircleView)
}
class ViewController: UIViewController, CircleViewDelegate {
var colors = CircleView()
#IBOutlet weak var circleView1: CircleView!
#IBOutlet weak var blueStepper: UIStepper!
#IBOutlet weak var greenStepper: UIStepper!
#IBOutlet weak var redStepper: UIStepper!
#IBOutlet weak var redValue: UILabel!
#IBOutlet weak var greenValue: UILabel!
#IBOutlet weak var blueValue: UILabel!
var circleViewDelegate: CircleView!
override func viewDidLoad() {
super.viewDidLoad()
circleViewDelegate!.delegate = self
}
func updateStepper(view: CircleView) {
redStepper.value=0.0;
greenStepper.value=0.0;
blueStepper.value=0.0;
}
#IBAction func stepperChange(sender: UIStepper) {
circleView1.redd1 = Int(redStepper.value);
redValue.text = Int(sender.value).description;
}
#IBAction func stepperChange1(sender: UIStepper) {
circleView1.greenn1 = Int(greenStepper.value);
greenValue.text = Int(sender.value).description;
}
#IBAction func stepperChange2(sender: UIStepper) {
circleView1.bluee1 = Int(blueStepper.value);
blueValue.text = Int(sender.value).description;
}
}
UIView:
class CircleView: UIView {
var redd1 = 0
var greenn1 = 0
var bluee1 = 0
weak var delegate: CircleViewDelegate?
func updateStepper() {
delegate?.updateStepper(self)
}
func game() {
if(redd1==Int(red1) && greenn1==Int(green1) && bluee1==Int(blue1)) {
redd1 = 0;
green1 = 0;
blue1 = 0;
updateStepper()
}
}
}
Try this:
override func viewDidLoad() {
super.viewDidLoad()
circleView1.delegate = self
}
func updateStepper(view: CircleView) {
redStepper.value = 0.0
greenStepper.value = 0.0
blueStepper.value = 0.0
stepperChange(redStepper)
stepperChange(greenStepper)
stepperChange(blueStepper)
}
Instead of assigning the delegate like this circleViewDelegate!.delegate = self in viewDidLoad try circleView1.delegate = self

Resources