EXC_BAD_INSTRUCTION (code = EXC_I386_INVOP, subcode=0x0) - swift

I'm creating a temperature converter. When I run the application; enter a temperature, select which conversion and click convert. An error comes up.
THE ERROR IS: EXC_BAD_INSTRUCTION (code = EXC_I386_INVOP, subcode=0x0)
This is my code for ViewController:
import UIKit
class ViewController: UIViewController,UIPickerViewDataSource,UIPickerViewDelegate {
#IBOutlet weak var orginalValue: UITextField!
#IBOutlet weak var convertFrom: UIPickerView!
let pickerData = ["Celsius", "Fahrenheit"]
override func viewDidLoad() {
super.viewDidLoad()
convertFrom.dataSource = self
convertFrom.delegate = self
}
#IBOutlet weak var labelConvertFrom: UILabel!
#IBOutlet weak var convertTo: UIPickerView!
#IBOutlet weak var labelConverTo: UILabel!
#IBOutlet weak var answer: UILabel!
#IBAction func convertButton(sender: AnyObject) {
let a = Double(orginalValue.text!)
let tempConvertM = TempConvert(temp: a!)
answer.text = String(tempConvertM.convert())
}
func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return pickerData.count
}
func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return pickerData[row]
}
func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
labelConvertFrom.text = pickerData[row]
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Here is where I'm getting the error.
TempConverterModel.swift
import Foundation
extension ViewController{
class TempConvert{
var temp:Double
var view = ViewController()
init (temp:Double){
self.temp = temp
}
func convert()->Double{
if(view.labelConvertFrom.text == "Celsius"){ -->ERROR IS HIGHLIGHTED HERE <--
view.labelConverTo.text = "Fahrenheit"
return (temp-32)/1.8000; //fahrenheit formula
}
else{
view.labelConverTo.text = "Celsius"
return (temp*1.8000)+32; //celsius formula
}
}
}
}
I don't know what I'm doing wrong. I want to check the text in labelConvertFrom and check if it equals to "Celsius". IF it does not then return answer.
I would really appreciate anyones help. Thank you!

As par pointed out, you should be removing the enclosing extension ViewController { } and have your TempConvert as a separate class.
Also, instead of trying to access the ViewController's instance variables in TempConvert, you should be doing the comparisons in your convertButton() method in ViewController class itself and call the appropriate conversion method in TempConvert class.
A better approach is to have a stored property for "Celsius" and a computed property for "Fahrenheit" within your ViewController class. You can refer this link for Properties in Swift language

The problem broadly stems from this line in class TempConvert:
var view = ViewController()
Here you are initializing an empty view controller. The outlets you've defined such as labelConvertFrom are not hooked up to anything, so when you try to deference them here:
view.labelConvertFrom.*text
you crash (specifically, you crash where I put the * character). The reason you crash is because at that point, labelConvertFrom is nil.
To get this to work right, you'll need to initialize the ViewController using the initWithNibName:bundle: method, passing the correct nib filename and bundle id (which is probably just NSBundle.mainBundle()).
Doing this will allow your outlets to be hooked up properly and then they won't be nil when you try to use them.

Related

xcode cannot assign value of type.. to NSSet

I am working on CoreData with Swift 3 and I am almost done. I did the CoreData entities and now I am trying to save data from a form on the app and I got this error:
import UIKit
import CoreData
class ItemDetailsVC: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource {
#IBOutlet weak var storePicker: UIPickerView!
#IBOutlet weak var titleField: CustomTextField!
#IBOutlet weak var priceField: CustomTextField!
#IBOutlet weak var detailsField: CustomTextField!
var stores = [Store]()
override func viewDidLoad() {
super.viewDidLoad()
storePicker.delegate = self
storePicker.dataSource = self
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
let store = stores[row]
return store.name
}
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return stores.count
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
// update
}
func getStores() {
let fetchRequest: NSFetchRequest<Store> = Store.fetchRequest()
do {
self.stores = try context.fetch(fetchRequest)
self.storePicker.reloadAllComponents()
} catch {
// some code
}
}
#IBAction func savePressed(_ sender: UIButton) {
let item = Item(context: context)
if let title = titleField.text {
item.title = title
}
if let price = priceField.text {
item.price = (price as NSString).doubleValue
}
if let details = detailsField.text {
item.details = details
}
item.toStore = stores[storePicker.selectedRow(inComponent: 0)] error: cannot assign value of type 'Store' to value of type NSSet?
}
I am not asking anyone to solve the error, I just wanna know what the error is telling me to do. Error is on the item.toStore = stores[storePicker... line
When you set a relationship on CoreData model to To Many it starts behaving like an Array. And like so you need to append the data to that array instead of assigning an class to it. You can do so with:
.addingObjects(from: [Any])
I am not asking anyone to solve the error, I just wanna know what the
error is telling me to do.
From what I have understood is that toStore is a to many relationship from Item to Store entity in CoreData.
Now since you need to know about the error only ,if I am correct and the relationship is exactly above then it means that Item entity has a set of stores associated with it not a single Store , hence you are getting this error
error: cannot assign value of type 'Store' to value of type NSSet?
The problem is your entity has one-to-many relationship, if you want to fix this issue try to change it "to one". I know you don't want the answer but here is the hint on how you can fix this. If you go to your *.xcdatamodeld file and locate your Item entity you can see the attributes relationships...find appropriate relationship and modify it from "to-many" to "to-one"

problems at nested hierarchy view using storyboard in Swift

I'm beginner at Swift, so currently i organize most part of my app using storyboard.
I want to construct some view scrollable that contains textField and pickerView.
and each of them is stacked View, and then it is child view of view A.
and view A is child view of scrollView.
help you to understand more, i'll attach my app structure.
Anyway, when i run my apps, it represent well i want to achieve, however, coudn't get any touch reaction.
keyboard isn't popup when i touch textField, pickerView scroll isn't working. I think it's because of nested view, but have no idea how to solve.
plz help! And also glad give some advice learn Swift.
Thx in advance.
* edit 1) attach my code *
import UIKit
class ViewController:
UIViewController, UIPickerViewDataSource, UIPickerViewDelegate
{
#IBOutlet var outerView: UIView!
#IBOutlet weak var scrollView: UIScrollView!
#IBOutlet weak var statePicker: UIPickerView!
#IBOutlet weak var innerView: UIView!
#IBOutlet weak var nameInputer: UITextField!
let states = ["Alaska", "Arkansas", "Alabama", "California", "Maine", "New York"]
override func viewDidLoad() {
super.viewDidLoad()
var scrollViewHeight:CGFloat = 0.0
for view in self.view.subviews as [UIView] {
scrollViewHeight += view.frame.size.height;
}
scrollView.contentSize = CGSize(width: view.frame.width, height: scrollViewHeight)
scrollView.contentInset = UIEdgeInsetsMake(20, 0, 20, 0)
statePicker.dataSource = self
statePicker.delegate = self
statePicker.isExclusiveTouch = true
scrollView.canCancelContentTouches = false
innerView.sendSubview(toBack: outerView)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return states.count
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return states[row]
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
statePicker.isHidden = true
}
}
* EDIT 2 : attach my story board *

Can't save data from UIPickerView

I tried to program a sign up view controller and use a UIPickerView for country choice. The issue is that when I tried to pass the picker country to Parse to save the input, Xcode give me an error. Why Xcode can't allow me to use the selected data to Parse? The error is in the last line.
Any help guys?
#IBOutlet var usernameTextField: UITextField!
#IBOutlet var fullnameTextField: UITextField!
#IBOutlet var emailTextField: UITextField!
#IBOutlet var passwordTextField: UITextField!
#IBOutlet var phonenumberTextField: UITextField!
#IBOutlet var countryPicker: UIPickerView!
let countryData: [String] = ["Saudi Arabia", "Turkey"]
#available(iOS 2.0, *)
public func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return countryData.count
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
let countrySelect = countryData[row]
print(countrySelect)
}
override func viewDidLoad() {
super.viewDidLoad()
countryPicker.dataSource = self
countryPicker.delegate = self
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func signUpAction(sender: AnyObject) {
// Declare user object
let newUser = PFUser()
let fullName = fullnameTextField.text!
let username = usernameTextField.text!
let email:String = emailTextField.text!
let password:String = passwordTextField.text!
let phoneNumber:Int? = Int(phonenumberTextField.text!)
// Passing arguments
newUser.username = username
newUser["fullName"] = fullName
newUser.email = email
newUser.password = password
newUser["phoneNumber"] = phoneNumber! as Int
newUser["country"] = countryData [row]
Based on your comment that the error is "unresolved identifier row":
You are never declaring a variable named row, yet you're using it. You can either replace the use of this undefined variable with the correct array index that will give you the country from the countryData variable OR you make sure that row is actually declared and accessible in your function.

How to change Labels and Table View from another Class?

I made an application, this application have a couple of functions. It has Table View, Labels, Buttons etc. I made a Picker View in a class called SettingsViewController that is useful for choosing language. I made it and it's working good but I don't know how to change text of Table View and Labels of other classes. I'm not to experienced in calling classes.
This is my class SettingsViewController:
import Foundation
import UIKit
class SettingsViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource {
var languages = ["English", "German", "French"]
var selectedLanguage = 0
#IBOutlet var languageLabel: UILabel!
#IBOutlet var topPartView: UIView!
#IBOutlet weak var languagePicker: UIPickerView!
#IBOutlet var SubmitLanguageButton: UIButton!
#IBAction func pickLanguageButton(sender: AnyObject) {
//Show Picker
topPartView.hidden = false
languagePicker.hidden = false
SubmitLanguageButton.hidden = false
}
#IBAction func submitLanguageButton(sender: AnyObject) {
//Hidde Picker
topPartView.hidden = true
languagePicker.hidden = true
SubmitLanguageButton.hidden = true
if (selectedLanguage == 0) {
languageLabel.text = "English"
}
else if (selectedLanguage == 1) {
languageLabel.text = "German"
}
else if (selectedLanguage == 2) {
languageLabel.text = "French"
}
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
topPartView.hidden = true
languagePicker.hidden = true
SubmitLanguageButton.hidden = true
languagePicker.delegate = self
languagePicker.dataSource = self
}
func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return languages[row]
}
func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return languages.count
}
// returns the number of 'columns' to display.
public func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
selectedLanguage = row
}
}
Another random ViewController with Table View and Label:
import UIKit
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
let foodList:[String] = ["Apple", "Bread", "Phineapple", "Water", "Other"]
#IBOutlet weak var myTableView: UITableView!
#IBOutlet var foodTitleLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
foodTitleLabel.text = "Food"
myTableView.reloadData()
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
var returnValue = 0
return returnValue
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let myCell = tableView.dequeueReusableCellWithIdentifier("myCells", forIndexPath: indexPath)
myCell.textLabel!.text = foodList[indexPath.row]
myCell.textLabel!.numberOfLines = 0
return myCell
}
}
So how I'm gonna change Labels and Table View from another class, because every text have to be on language that is chose in SettingsViewController ?
For ex: When user choose English, the text in all ViewControllers have to be in English.
When user choose French, the text in all ViewControllers have to be in French.
If this question was not clear, please inform me, I wil try to show more info. Thanks for your contribution.
We can accomplish this in a cleaner way with less code like :
enum names{
case English, German, French
func food() -> String {
switch self {
case English: return "food"
case German: return "Lebensmittel"
case French: return "Aliments"
}
}
func foodList() -> [] {
switch self {
case English: return ["Apple", "Bread", "Pineapple", "Water", "Other"]
case German: return [ "Apfel", "Brot", "Pineapple", "Wasser","Andere"]
case French: return ["Pomme", "Pain", "Ananas", "Eau", "Autre"]
}
}
}
import UIKit
var lang = names.English
class SettingsViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
foodTitleLabel.text = lang.food()
foodList = lang.foodList()
So you could address by different approachs the problem, but for my point of view the easiest one is to implement a protocol that handles events in a viewcontroller and has an impact in another one for examlple
protocol ChangeLanguagesProtocol
{
func returnNewLanguages(newlanguages:[String])
}
then you you will need to implement the protocol and its method in your viewcontroller like
class SettingsViewController: UIViewController,
UIPickerViewDelegate, UIPickerViewDataSource , ChangeLanguagesProtocol {
var languages = ["English", "German", "French"]
func returnNewLanguages(newlanguages:[String]){
self.languages = newlanguages
}
Then in you second ViewController class you need to have a var of the type of your protocol and trigger its method when your need it
//variable
var delegate:ChangeLanguagesProtocol!
//for example when clicking a button
#IBAction func SampleButtonPress(sender:UIButton){
let newlanguages:[String] = ["Spanish", "Chinesse", "German", "French", "Other"]
delegate.returnNewLanguages(newlanguages)
}
last step we need to assign the delegate variable when we are going to push to the desired viewcontroller, in the case where viewcontrollers are not next to each other you can use singleton or a shared instance to maintain your delegate property until you need it, but it will look something like
// this should be in your first ViewController
#IBAction func gotoNextViewController(sender:UIButton){
let _localization = Localization(nibName: "Localization", bundle:nil)
_localization .delegate = self
self.navigationController?.pushViewController(_localization , animated: true)
}
You are trying to internationalize your app. Apple has some built in stuff for this that you should check out: https://developer.apple.com/internationalization/
If that doesn't suit your needs, to answer your question, your views should set their text when they either load (viewDidLoad) or right before they appear (viewWillAppear) as a result of the user's language choice, which could possibly be stored in NSUserDefaults. Your settings class shouldn't have to force any change in other views, your other views should set their own text to the right language before they are displayed.
struct Localization {
static func stringsForScreen(screenName:String, forLanguage language:String) -> [String:String] {
//parse a file that has the strings for the given screen in the given language, and return it
}
}
class HomeViewController:UIViewController {
#IBOutlet var titleLabel:UILabel?
#IBOutlet var bodyLabel:UILabel?
override func viewDidLoad() { //or possibly viewDidAppear, depends on your needs
super.viewDidLoad()
let language = NSUserDefaults.standardUserDefaults().stringForKey("currentLanguage") ?? "English"
let textDict = Localization.stringsForScreen("HomeViewController" forLanguage:language)
titleLabel.text = textDict["titleLabelText"] ?? ""
bodyLabel.text = textDict["bodyLabelText"] ?? ""
}
}
class PickLanguageViewController:UIViewController, UIPickerViewDelegate {
var languages = ["English","French","Spanish"]
//Whatever method the picker uses
func pickerView(pickerView:UIPickerView didSelectRow row:Int inComponent component:Int) {
NSUserDefaults.standardUserDefaults().setObject(languages[row] forKey:"currentLanguage")
}
}
skeleton example of how this might be structured.
I found solution. First of All the variable selectedLanguage I declared it out of the class SettingsViewController.
import UIKit
var selectedLanguage = 0 //<<< Here
class SettingsViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource {
var languages = ["English", "German", "French"]
After that I did this in method viewDidLoad to every ViewController (I will show just one ViewController).
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
if (selectedLanguage == 0) { //English
foodTitleLabel.text = "Food"
foodList = ["Apple", "Bread", "Pineapple", "Water", "Other"]
}
else if (selectedLanguage == 1) { //German
foodTitleLabel.text = "Lebensmittel"
foodList = [ "Apfel", "Brot", "Pineapple", "Wasser","Andere"]
}
if (selectedLanguage == 2) { //French
foodTitleLabel.text = "Aliments"
foodList = ["Pomme", "Pain", "Ananas", "Eau", "Autre"]
}
I hope this will be helpful for other users, because It worked perfectly for me.

segue to another view controller

I've been trying to segue some labels across to another view controller but i can't seem to work it out.
my first view controller:
import UIKit
class firstViewController: UIViewController,UITextFieldDelegate {
#IBOutlet weak var label1: UILabel!
#IBOutlet weak var label2: UILabel!
#IBOutlet weak var label3: UILabel!
#IBOutlet weak var label4: UILabel!
#IBOutlet weak var label5: UILabel!
#IBOutlet weak var label6: UILabel!
var pickerLabels: [String!] {
return [label1.text,label2.text,label3.text,label4.text,label5.text,label6.text]
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
let controller = segue.destinationViewController as thirdViewController
controller.vc2Labels = pickerLabels //pickerLabels shows error
}
}
the labels in here are what I'm trying to segue but "pickerLabels" keeps coming up with an error
my second view controller:
import UIKit
class secondViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource {
var vc2Labels: [String]!
func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int{
return 1
}
func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component:Int) -> Int{
return vc2Labels.count
}
func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String!{
return vc2Labels[row]
}
I think I know your problem. You seem to be passing in an array of String into a string object.
Maybe you can alter your second view controller's variable to be:
var vc2Labels: [String]!
but I wouldn't recommend using implicit unwrapping of optional, since it allows a passing in of nil. You can declare an empty array like this.
var vc2Labels = [String]()
Hope this helps. More context would be helpful.