NSInvalidArgumentException when reloading UITableView - ios

This is my UIViewController:
class HabitTableViewController: UIViewController, UITableViewDataSource, UITableViewDelegate{
#IBOutlet weak var habitTableView: UITableView!
private var _numOfRowsInSects: [Int] = []
private var _habitsByDaySet = false
private var _habitsBySection:[[Habit]] = []
private var _whatIsToday = -1
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
habitTableView.delegate = self
habitTableView.dataSource = self
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func reloadTableForDay(sender: DayButton){
if sender.tag != getDayOfWeek(-1){
_whatIsToday = sender.tag
self.habitTableView.reloadData() //line of exception
}
else{
_whatIsToday = -1
}
}
// methods of UITableView delegate and data source implemented
}
I got an NSInvalidArgumentException at the line self.habitTableView.reloadData(), and the reason is -[HabitWiz.HabitTableViewController reloadTableForDay:]: unrecognized selector sent to instance 0x7fb0d351b060. I have no idea what is going on here, any help is appreciated.

Solved it. I realized my app wasn't building correctly: I inserted a couple of print statements which weren't executed. So I just did a clean build, and everything works now.

My guess is that you messed up with the IBAction in the interface builder.
Try to unwire and re-wire the action and be sure the ViewController is set to be a subclass of HabitTableViewController.

Related

Swift3.0 I want to get object of AppDelegate

I wanna get object of AppDelegate.
This program can build but it will stop running with lldb error.
Maybe the problem is the dirrerence of Swift2.0 and 3.0.
My textbook is for swift2.0 but I am using xcode8.0 and Swift3.0.
Error is here.
let ap = UIApplication.shared.delegate as! AppDelegate
I used this page for fixing.
How do I get a reference to the app delegate in Swift?
import UIKit
class FirstViewController: UIViewController {
#IBOutlet weak var dataTextField: UITextField!
let ap = UIApplication.shared.delegate as! AppDelegate
override func viewWillAppear(_ animated: Bool) {
dataTextField.text = String(ap.cmValue)
}
#IBAction func tapInpu() {
dataTextField.resignFirstResponder()
if let text = dataTextField.text{
if let cmValue = Double(text){
ap.cmValue = cmValue
}
}
}
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.
}
}
If you remove ap initialization and ap.cmValue = cmValue, does it works ?
If it does work check your outlet referencing in your storyboard you may have old non existent references

today extension shows "unable to load" after button event (iOS)

Good morning!
I have an "unable to load" problem in my iOS widget. I've read a lot of about the "unable to load" message but nothing fixed my problem. I'm not sure but I think my problem is to refresh the widget after changing my content.
My widget has one button and one label. If the user press the button the text from the label will changed - in this moment the widget shows "unable to load". Just a milisecond after pressing the button.
import UIKit
import NotificationCenter
class TodayViewController: UIViewController, NCWidgetProviding {
#IBOutlet var segment_att: UISegmentedControl!
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
func widgetPerformUpdateWithCompletionHandler(completionHandler: ((NCUpdateResult) -> Void)) {
completionHandler(NCUpdateResult.NewData)
}
func widgetMarginInsetsForProposedMarginInsets(defaultMarginInsets: UIEdgeInsets) -> UIEdgeInsets {
return UIEdgeInsetsZero
}
#IBAction func button_ae(sender: AnyObject) {
let tableviewclass = TodayTableViewController()
tableviewclass.newData()
}
}
Important is that the label is shown in a TableViewCell of a TableViewController. So the TableViewController is embeded in the ViewController within a Container... The listener from the button call the method newdata() of the file of the TableViewController.
import UIKit
import NotificationCenter
class TodayTableViewController: UITableViewController, NCWidgetProviding {
#IBOutlet var table: UITableView!
#IBOutlet var label1: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
init()
}
func init() {
let meldung: String = "test"
label1.text = meldung
}
func newData() {
let meldung: String = "new test"
label1.text = meldung
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
The code is really simple and basic - so I'm wondering about the problem in this simple mechanism. I hope you can help me!
Thanks at all!
Your code assumes that label1 has been set when newData() is called, even immediately after the constructor is called.
Try using this optional chaining syntax instead, which will quietly fail if the property is nil:
import UIKit
import NotificationCenter
class TodayTableViewController: UITableViewController, NCWidgetProviding {
#IBOutlet var table: UITableView!
#IBOutlet var label1: UILabel!
var meldung: String = "test" // <-- meldung is property
override func viewDidLoad() {
super.viewDidLoad()
init()
}
func init() {
label1?.text = melding // <-- optional chaining
}
func newData() {
melding = "new test" // <-- set the class property
label1?.text = meldung // <-- optional chaining
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
and instead of calling newData(), you might instead just set the meldung property, e.g.:
tableviewclass.meldung = "new test"
as your viewDidLoad() will take care of setting the UILabel text from the property

Can't understand why UISegmentedControl is returning nil

Just messing around with a simple iOS app in Swift that displays an image view and segmented control underneath with 3 options. I'm just trying to get the image to swap out based on which option is chosen from the segmented control. I have this simple code so far:
class ViewController: UIViewController {
var gallery = ["apple", "banana", "coconut"]
#IBOutlet weak var imageView: UIImageView!
#IBAction func changeSegment(sender: AnyObject) {
let segmentedControl = sender as? UISegmentedControl
if let index = segmentedControl?.selectedSegmentIndex {
imageView.image = UIImage(named: gallery[index])
}
}
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.
}
}
I keep running into an error that prints out "(lldb)". It looks like it hits a breakpoint at:
let segmentedControl = sender as? UISegmentedControl
not sure why. Any and all help is greatly appreciated!
You have a breakpoint on the side of your code. I would clean your file and run.

Cannot unwrap optional value to label

I am new to this board. Please, excuse my bad english in advance.
I am trying to send a string from a subview to his parent view. If I try to set that string to a label, my app crashes with the message "unexpectedly found nil while unwrapping an Optional value".
Example code from the subview:
class TableViewController: UITableViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = UIColor.blueColor()
sendDataToVc("test")
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
func sendDataToVc(myString : String) {
let Vc = ViewController()
Vc.dataFromContainer(myString)
}
Example from the parent view:
class ViewController: UIViewController {
#IBOutlet weak var label1: UILabel!
var cacheStr1 : String!
var cacheStr2 : String?
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
label1.text = ""
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func dataFromContainer(containerData : String){
label1.text = cacheStr1
}
#IBAction func changeLabel(sender: AnyObject) {
}
I have no more ideas what I am doing wrong. Thank you for your help.
The problem is this line:
let Vc = ViewController()
You are creating a new instance — a new ViewController instance. That's not what you want to do. You want to get a reference to an existing instance — the one that is your view controller's parent view controller, if that's what a View Controller is in relation to your TableViewController.
You better instance your ViewController form StoryBoard and define what you want to pass as property, and then set this property to the value that you need to show, and in the viewDidLoad of your ViewController update your view as you need

found nil while unwrapping optional

I am trying to create a simple application that consists of one Navigation controller with 2 screens controlled by a single UIViewController class. The app will allow the user to enter a number from 0 to 10 in a text field and when the user presses a button they will be taken to the 2nd screen showing if they guessed the randomly generated number. I get the "unexpectedly found nil while unwrapping an Optional value" error when I am accessing the text property of the label in the second screen. I dont uderstand why, I have connected the label with the class. Any suggetions?
This is my UI:
This is my Navigation controller class code:
class MyNavController: UINavigationController {
var ranNum:Int = 0
override func viewDidLoad() {
super.viewDidLoad()
ranNum = (Int)(arc4random_uniform(10))
NSLog("random number: \(ranNum)")
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
This is my Generic View controller class:
class GenericViewController: UIViewController {
#IBOutlet weak var inputTextField: UITextField!
#IBOutlet weak var outputLabel: UILabel!
var setThisLabel: String = "You Win!"
#IBAction func guessTheNumber(sender: AnyObject) {
var generatedRanNumber = (parentViewController as! MyNavController).ranNum
var userGuessNumer = inputTextField.text.toInt()
if generatedRanNumber == userGuessNumer {
outputLabel.text = "You Win!"
} else if generatedRanNumber < userGuessNumer {
outputLabel.text = "Think Less..."
} else {
outputLabel.text = "Think Big..."
}
}
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
change from
var generatedRanNumber = (parentViewController as! MyNavController).ranNum
to
var generatedRanNumber = (navigationController as! MyNavController).ranNum
also notice that arc4random_uniform(10) returns a number between 0 and 9. you tell the user to guess a number between 0 and 10.
Actually the problem is you are pushing from one instance of Generic View Controller to another without passing on the data. It is generally not recommended to use a generic subclass of UIViewController in this way. If you want your code to work as is, place the UILabel in the same view as your other UI and don't segue (i.e. only have one instance of GenericViewController). Or create two subclasses of UIViewController one called "GuessViewController" and the other called "AnswerViewController" and pass the guess value between them in prepareForSegue. GuessViewController would handle getting the string from the user and evaluate it. AnswerViewController would whether it's right or wrong. It is also generally not necessary to subclass UINavigationController. You could place that code in the viewDidLoad of GuessViewController.

Resources