segue to another view controller - swift

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.

Related

Custom UITableViewCell has no initialiser error on only one of the two created classes. Swift

I'm adding a new TableVIewto the project and I'm also creating a custom class fro the cell. I'm doing as usual : New file/ Cocoa Touch Class / UITableViewCell / name. As soon as I start adding properties I get the error dough properties are declared as!. It doesn't happen on my other custom cell class. Can you see what am I doing wrong with this new class?
No error on this class :
import UIKit
class CalendarTableViewCell: UITableViewCell {
#IBOutlet weak var dayLabel: UILabel!
var cellId: String!
var cellWeekday: Int!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func prepareForReuse() {
super.prepareForReuse()
// Set your default background color, title color etc
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
and the new class that makes xCode complain:
import UIKit
class ProductTableViewCell: UITableViewCell {
#IBOutlet weak var productImageView: UIImageView!
#IBOutlet weak var productIDLabel: UILabel!
#IBOutlet weak var productIDInfoLabel: UILabel!
#IBOutlet weak var categoryLabel: UILabel!
#IBOutlet weak var categoryInfoLabel: UILabel!
#IBOutlet weak var nameLabel: UILabel!
#IBOutlet weak var nameInfoLabel: UILabel!
#IBOutlet weak var priceLabel: UILabel!
#IBOutlet weak var priceInfoLabel: UILabel!
#IBOutlet weak var quantityLabel: UILabel!
#IBOutlet weak var quantityInfoLabel: UILabel!
var productImage: UIImage!
var category: String!
var productId: String!
var name: String!
var price: String
var vendor: String!
var cellId: Int64
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
It's something I overlooked for sure but I can't spot it.
What should I check?
Your var cellId: Int64 is not initialized. In first cell you explicitly specified that you will initialize it before use with exclamation mark, but not in the second cell.

How can I create a protocol for a UITableViewCell?

I have a few UITableViewCell's that have a few different layouts depending on if they're teammates, enemies, etc. But I have to treat each type differently etc. So I tried to cut down on replicated code by using a protocol,
I've created a protocol for a UITableViewCell like so:
protocol ViewCellProtocol {
var teamRank: UILabel! { get set }
var ranking: UILabel! { get set }
var rankDelta: UILabel! { get set }
var upDownIndicator: UILabel! { get set }
var textLabel : UILabel? { get }
}
This is my class:
import UIKit
class TeamStatsTableViewCell: UITableViewCell {
#IBOutlet weak var teamRank: UILabel!
#IBOutlet weak var ranking: UILabel!
#IBOutlet weak var rankDelta: UILabel!
#IBOutlet weak var upDownIndicator: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
Then when I try to use it
func playerViewCell(_ tableView: UITableView, indexPath: IndexPath) -> ViewCellProtocol {
let cell = tableView.dequeueReusableCell(withIdentifier: "teamNameCell")! as! TeamStatsTableViewCell
let rank = sections[indexPath.section].data[indexPath.row]["rank"] as? Int
let (rating, ratingDelta) = selectRating(section: indexPath.section, row: indexPath.row)
let indicator = decideRatingIndicator(ratingDelta: ratingDelta, cell: cell)
cell.upDownIndicator?.text = "\(indicator)"
cell.teamRank?.text = "#\(rank!)"
cell.ranking?.text = String(rating)
cell.rankDelta.text = String(format: "%.0f", ratingDelta)
cell.textLabel?.text = sections[indexPath.section].data[indexPath.row]["username"] as? String
return cell as! ViewCellProtocol
}
I get an error:
Could not cast value of type '.TeamStatsTableViewCell' (0x1008d35d8) to '.ViewCellProtocol' (0x10ea37db8).
2018-04-24 22:00:27.137516-0600[434:72294] Could not cast value of type '.TeamStatsTableViewCell' (0x1008d35d8) to '.ViewCellProtocol' (0x10ea37db8).
I wish it would tell me what part it doesn't conform to. Any suggestions? Fairly new to swift kind of looking at protocols like interface{} in Go. Thanks.
Your custom cell class might be implementing all the stuff that's in the protocol, and that'd be enough in objC perhaps, but here you must declare that you implement that protocol explicitly
class TeamStatsTableViewCell: UITableViewCell, ViewCellProtocol {
#IBOutlet weak var teamRank: UILabel!
#IBOutlet weak var ranking: UILabel!
#IBOutlet weak var rankDelta: UILabel!
#IBOutlet weak var upDownIndicator: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
You need to declare that TeamStatsTableViewCell conforms to ViewCellProtocol, for example by adding this extension:
extension TeamStatsTableViewCell: ViewCellProtocol { }

EXC_BAD_INSTRUCTION (code = EXC_I386_INVOP, subcode=0x0)

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.

ScrollView, TextField and pickerview trouble

My problem is that when I run the project and click the first textfield ( the others are empty for now ) the app crashes with this error :
Terminating app due to uncaught exception 'UIViewControllerHierarchyInconsistency', reason: 'child view controller:<UICompatibilityInputViewController: 0x12dd4c600> should have parent view controller:<Sai_Service.ServiceAppointment: 0x12dd151a0> but requested parent is:<UIInputWindowController: 0x12e00b600>'.
This is my code:
import UIKit
class ServiceAppointment: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource {
#IBOutlet weak var ScrollView: UIScrollView!
#IBOutlet weak var pickerView: UIPickerView!
#IBOutlet weak var StateField: UITextField!
#IBOutlet weak var CityField: UITextField!
#IBOutlet weak var VehRegNumberField: UITextField!
#IBOutlet weak var LocationField: UITextField!
#IBOutlet weak var CurrentKmsField: UITextField!
#IBOutlet weak var apptDateFIeld: UITextField!
#IBOutlet weak var apptTypeField: UITextField!
#IBOutlet weak var pickupField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
ScrollView.contentSize.height = 1000
pickerView.hidden = true;
StateField.text = States[0]
self.pickerView.dataSource = self;
self.pickerView.delegate = self;
self.StateField.inputView = pickerView
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
var States = ["Italy","United States","UK","France"]
//MARK: - Delegates and data sources
//MARK: Data Sources
func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return States.count
}
//MARK: Delegates
func pickerView2(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String! {
return States[row]
}
func pickerView3(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
StateField.text = States[row]
pickerView.hidden = true;
}
func textFieldShouldBeginEditing(textField: UITextField) -> Bool {
pickerView.hidden = false
return false
}
}
I think it's a problem of multiple view, so I wrote in the viewDidLoad:
self.StateField.removeFromSuperView()
but then all the ScrollViews disappeared obviously.
How I can make this work so that when I press the textfield, the pickerview appears?

Random name selector using a picker view with swift

I'm trying populate a pickerview using the text from labels.
I've tried searching online and in books for how to do this but no luck yet.
what i have so far shows no errors but still won't run
thanks
import UIKit
class ViewController: UIViewController, UIPickerViewDelegate,UIPickerViewDataSource,UITextFieldDelegate{
#IBOutlet weak var label3: UILabel!
#IBOutlet weak var label2: UILabel!
#IBOutlet weak var label: UILabel!
#IBOutlet weak var textField: UITextField!
#IBOutlet weak var textField2: UITextField!
#IBOutlet weak var textField3: UITextField!
#IBAction func button(sender: UIButton) {
label.text = textField.text
label2.text = textField2.text
label3.text = textField3.text
self.textField.resignFirstResponder()
self.textField2.resignFirstResponder()
self.textField3.resignFirstResponder()
}
func textFieldShouldReturn(textField: UITextField) -> Bool {
textField.resignFirstResponder()
return false
}
override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
self.view.endEditing(true)
}
var pickerLabels: [UILabel!] {
return [label,label2,label3]
}
func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int{
return 1
}
func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component:Int) -> Int{
return pickerLabels.count
}
func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> NSArray{
return pickerLabels
}
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.
}
}
You are sending UILabels to your array.
I believe what you are trying to achieve needs you to get the text from the UILabels and also to format the array as [String] on your computed property..
var pickerLabels: [String!] {
return [label.text, label2.text, label3.text]
}