UISlider value can't be accessed by function in ViewController - ios

I get an error saying "EXC_BAD_INSTRUCTION..." in reference to attempting to use redSlider.value to set a value for a property of my "Color" type from another file.(also pasted below)
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
#IBOutlet weak var colorView: UIView!
#IBOutlet weak var redSlider: UISlider!
#IBOutlet weak var greenSlider: UISlider!
#IBOutlet weak var blueSlider: UISlider!
func updateCurrentColor() {
var currentColor = Color(red: redSlider.value, green: greenSlider.value, blue: blueSlider.value)
print("CurrentColor updated!!!")
}
}
And here is my "Color" Type(in another file):
import Foundation
struct Color {
var red = Float()
var green = Float()
var blue = Float()
}
Here is my ViewController
I call updateCurrentColor() from main.swift
import Foundation
import UIKit
ViewController().updateCurrentColor()

ViewController() creates a new view controller object. Since you don't present it on the screen, its outlets never get initialized. That means that the ! on the end of redSlider: UISlider! is a lie.
Even if it didn't crash, updating the color on something you're not putting on the screen doesn't sound very useful.
Use the ViewController you already have instead of creating a new one.

Related

Storyboard: Connect IBOutlet to a ViewModel/Model bypassing the ViewController

I have a rather complex form designed in the Interface Builder, having about 20 IBOutlets. The form is split onto multiple sections and is static.
Some of the sections might be enabled while the others are disabled (hidden). After the form has been filled in, the app needs to read all of the values (i.e. IBOutlets such as UITextField) and send them to the server.
I used multiple UIStackViews to design each section of the form, so that they could be easily switched on or off.
It's logical after having such a separation with views to have a model that would reflect the same order.
However, I had to link all of the IBOutlets to the UIViewController subclass, flattening any hierarchy.
What I'm trying to achieve is to link individual Form Section Model with specific View. The controller will be responsible only for enabling/disabling the section. The Form Section Model would actually enable specific labels and StackViews and fill in the form values.
Here is the example code I'd like the interface to look like:
import UIKit
class AddressSection {
#IBOutlet weak var sectionStackView: UIStackView!
#IBOutlet weak var sectionTitleLabel: UILabel!
#IBOutlet weak var addressTextField: UITextField!
#IBOutlet weak var isPrimary: UISwitch!
var isHidden: Bool {
get {
return sectionStackView.isHidden
}
set(newValue) {
sectionStackView.isHidden = newValue
}
}
init(){}
}
class NameSection {
#IBOutlet weak var sectionStackView: UIStackView!
#IBOutlet weak var name: UITextField!
#IBOutlet weak var surname: UITextField!
var isHidden: Bool {
get {
return sectionStackView.isHidden
}
set(newValue) {
sectionStackView.isHidden = newValue
}
}
init(){}
}
class MyViewController: UIViewController {
let name = NameSection()
let address = AddressSection()
override func viewDidLoad() {
super.viewDidLoad()
name.isHidden = false
address.isHidden = true
}
}

Swift 4 Why Delegate is not working

In ViewController :
protocol SearchResultDelegate {
func SendDataToResultController(_ result: [SkelbimasModel])
}
class ViewController: UIViewController, UISearchBarDelegate, CLLocationManagerDelegate, MKMapViewDelegate, AddSkelbimas {
#IBOutlet weak var Label: UILabel!
#IBOutlet weak var SearchBar: UISearchBar!
// #IBOutlet weak var boomFilter: BoomMenuButton!
// #IBOutlet weak var Label: UILabel!
#IBOutlet weak var CategoryView: UIView!
#IBOutlet weak var Map: MKMapView!
#IBOutlet weak var bmb: BoomMenuButton!
var Delegate:SearchResultDelegate?
.........
//ijungimiame lentele su paieskos rezultatais
if(result.count > 1) {
Delegate?.SendDataToResultController(result)
GoToSearchResultVC(result)
}
Function GoToSearchResultVC(result) is called it opens new controller
in that new controller code is :
import UIKit
class SearchResultTableViewController: UITableViewController, SearchResultDelegate {
.....
func SendDataToResultController(_ result: [SkelbimasModel]) {
print("result count: \(result.count)")
results = result
}
But this function is never called.
I used delegates before and was fine. Or i'm just tired and do not see where i did wrong...
Somewhere where you create the ViewController in your code in SearchResultTableViewController you have to set the value of the delegate:
let viewController = ViewController()
viewController.Delegate = self
// present viewController
If you are showing after SearchResultTableViewController from ViewController, isn't it easier to do something like:
func GoToSearchResultVC(result: Any) {
let searchVC = SearchResultTableViewController()
searchVC.results = results
self.present(searchVC, animated: true, completion: nil)
}
Delegate design patter is to receive events from other classes, if you only want to set a variable, this way is better for me
BTW checking your code, you are calling first the delegate before creating the SearchResultsVC

How do I assign the tab bar item to a specific view controller when clicked?

import UIKit
import ARNTransitionAnimator
import AVFoundation
import MediaPlayer
final class ViewController: UIViewController, AVAudioPlayerDelegate{
#IBOutlet fileprivate(set) weak var containerView : UIView!
#IBOutlet fileprivate(set) weak var tabBar : UITabBar!
#IBOutlet fileprivate(set) weak var miniPlayerView : LineView!
#IBOutlet fileprivate(set) weak var miniPlayerButton : UIButton!
#IBOutlet weak var miniPlay: UIButton!
#IBOutlet weak var tabone: UITabBarItem!
private var animator : ARNTransitionAnimator?
fileprivate var modalVC : ModalViewController!
override func viewDidLoad() {
super.viewDidLoad()
tabBar.barTintColor = UIColor.black
let musicVC = MusicViewController()
}
}
I am trying to assign the a tab bar item to a view controller. The current view controller is a not a special tab bard controller.( I know it would of been easier to make a tab bar controller in storyboard). The tab bar is an object made in storyboard and is connected by IBoutlet with its first bar item connected as well. Is there a way to assign the connected programmatically?
I would suggest an extension on UIViewController which copied the tab bar item properties to it's UITabBarItem instance.
extension UIViewController {
func copyTabBarItem(_ item: UITabBarItem) {
tabBarItem.badgeColor = item.badgeColor
tabBarItem.badgeValue = item.badgeValue
if #available(iOS 11.0, *) {
tabBarItem.isSpringLoaded = item.isSpringLoaded
}
tabBarItem.selectedImage = item.selectedImage
for state in [UIControlState.application, UIControlState.disabled, UIControlState.focused, UIControlState.highlighted, UIControlState.normal, UIControlState.reserved, UIControlState.selected] {
tabBarItem.setBadgeTextAttributes(item.badgeTextAttributes(for: state), for: state)
}
tabBarItem.titlePositionAdjustment = item.titlePositionAdjustment
}
}

Passing data between view controllers inside page view controllers in Swift

Sorry if this particular problem has been asked about, I followed the answers on other threads but none of them seemed to work, but I just started learning Swift so all of this is pretty new to me.
So, I have a text field in two View Controllers and I want the third View Control to display a result based on the input from the other two controllers when I press a button.
I followed this tutorial and placed the text fields, label and button like I said before.
I placed my code (which you can see below) inside ViewControl.swift.
The problem is that when I attempt to run it I get a "Thread 1 :EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)" error in the last two lines.
class ViewController: UIViewController {
var a: String = ""
var b: String = ""
#IBOutlet weak var aTextField: UITextField!
#IBOutlet weak var bTextField: UITextField!
#IBOutlet weak var calculateButton: UIButton!
#IBOutlet weak var resultLabel: UILabel!
#IBAction func calculateButtonPressed(_ sender: UIButton) {
let a = aTextField.text!;
let b = bTextField.text!;
I think that the error is from the data not passing between the views (because before I had everything in the same view and it worked fine), but since I only have one ViewController.swift file I couldn't figure out how to use a Segue.
Do not declare same variables multiple times. Remove let before a & b . You have already declared a & b globally and then tried to redeclare it inside IBAction
class ViewController: UIViewController {
var a: String = ""
var b: String = ""
#IBOutlet weak var aTextField: UITextField!
#IBOutlet weak var bTextField: UITextField!
#IBOutlet weak var calculateButton: UIButton!
#IBOutlet weak var resultLabel: UILabel!
#IBAction func calculateButtonPressed(_ sender: UIButton) {
a = aTextField.text!;
b = bTextField.text!;
Make sure your control outlets are setted properly.
In your two variables a & b are re-declared.Just update your code like below
#IBAction func calculateButtonPressed(_ sender: UIButton) {
self.a = aTextField.text!
self.b = bTextField.text!
}

Xcode - Pass data between view controllers, then cast to integer

I have a textfield in my first View Controller. The input is numbers only, but it's obviously in the form of a string. I've passed it to my second view controller. The code is as follows:
import Foundation
import UIKit
class View3on3Results : UIViewController {
#IBOutlet weak var APResult1: UILabel!
#IBOutlet weak var APResult2: UILabel!
#IBOutlet weak var APResult3: UILabel!
#IBOutlet weak var APResult4: UILabel!
var AP1: String? = String()
var AP2: String? = String()
var AP3: String? = String()
let x:Int? = Int(AP1)
override func viewDidLoad() {
APResult1.text = AP1
APResult2.text = AP2
}
}
I set the Label text to equal the strings I passed just to test if it was working; it is.
I'd now like to cast the strings I just passed to integers. I tried doing that with:
let x:Int? = Int(AP1)
It throws the error: View3on3Results.type does not have a member named 'AP1'. Anyone know what's up with this?
All coded in XCode 7.0 beta 3, using Swift 2.
You can not Initialise your instance that way but you can do that in viewDidLoad method this way:
let x:Int? = AP1?.toInt()

Resources