Swift Thread 1: signal SIGART error after adding a new delegate - swift

I’m new to Swift and have been stuck on this problem for a while.
I’m trying to add a ‘settings’ view where the size of the font can be updated for the main view.
I get a Thread 1: signal SIGART error on the line: class AppDelegate: UIResponder, UIApplicationDelegate
After adding the below code, my app now crashes when I press on the settings button.
Not sure how else to debug this problem, any help will be much appreciated! Thanks in advance.
View Controller:
class ViewController: UIViewController, CLLocationManagerDelegate, SettingsViewControllerDelegate {
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "SettingsViewController" {
let settingsViewController = segue.destination as? SettingsViewController
if let viewController = settingsViewController {
viewController.delegate = self
}
}
}
func makeChangesToFont(size: Int) {
if (self.distanceReading.font.pointSize > 20) {
self.distanceReading.font = UIFont(name: self.distanceReading.font.fontName, size: CGFloat(size))
}
}
...
}
Settings Controller:
import UIKit
protocol SettingsViewControllerDelegate {
func makeChangesToFont(size: Int)
}
class SettingsViewController: UIViewController {
var delegate: SettingsViewControllerDelegate?
#IBAction func IncreaseSize(_ sender: UIButton) {
print("something")
increaseFontSize()
}
func increaseFontSize() {
let mainView = parent as! ViewController
let text = mainView.distanceReading
let fontSize = (text?.font.pointSize)! + 10
print(fontSize)
if let delegate = self.delegate {
delegate.makeChangesToFont(size: Int(fontSize))
}
}
...
}
I'm using Swift 3 in Xcode 8.2.1

Related

Error in calling method from another class when using delegates

I have tried to run Second ViewController to change appearance on my first ViewController and progressBar(Progress View) cause error, but if I try to call method keyButtonResponse() from First View Controller error doesn`t appear
First ViewController:
import UIKit
import AVFoundation
import UserNotifications
protocol SomeDelegate {
func keyButtonResponse()
}
class FirstViewController: UIViewController, SomeDelegate{
#IBOutlet weak var label: UILabel!
#IBOutlet weak var progressBar: UIProgressView!
func keyButtonResponse(){
//some code
progressBar.progress = 0.01 //Thread 1: Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value
}
}
Second ViewController:
class SecondViewController: UIViewController {
var delegate: SomeDelegate?
func keyButtonResponse(){
delegate?.keyButtonResponse()
}
#IBAction func leftButtonPressed(_ sender: UIButton) {
let myVar = WarningViewController()
let viewController = ViewController()
myVar.delegate = viewController
myVar.keyButtonResponse()
}
}
You're setting the delegate to an instance of a view controller that's unrelated to FirstViewController here.
let viewController = ViewController()
myVar.delegate = viewController
You need to set the delegate to the existing instance of FirstViewController.
If you're using a segue:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let vc = segue.destination as? SecondViewController, segue.identifier == "firstVCToSecondVCSegue" {
vc.delegate = self
}
}
or
if let vc = self.storyboard?.instantiateViewController(withIdentifier: "SecondViewController") as? SecondViewController {
vc.delegate = self
self.navigationController?.pushViewController(vc, animated: true)
}
This should be placed within FirstViewController, not SecondViewController.

I need help converting a UITextField from string to Int [duplicate]

This question already has answers here:
Converting String to Int with Swift
(31 answers)
Closed 2 years ago.
I have made a simple project which sends data from one view controller to a second.
It works for a string, but I now want to change the code so it can multiply the UITextField answer by 10 and output it to the label in the Second ViewController. I know that I just need to change the string to Int but I've tried lots of things and nothing has worked.
I know there must be some simple way that I'm overlooking.
Any help is appreciated.
ViewController
import UIKit
class ViewController: UIViewController {
#IBOutlet var EnterNumber: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
EnterNumber.delegate = self
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let VC2 : ViewController2 = segue.destination as! ViewController2
VC2.LabelText = EnterNumber.text!
}
}
extension ViewController : UITextFieldDelegate{
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
}
ViewController 2
import UIKit
class ViewController2: UIViewController {
#IBOutlet var Label: UILabel!
var LabelText = String()
override func viewDidLoad() {
super.viewDidLoad()
Label.text = LabelText
}
}
ViewController 1 and 2
Try this:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let VC2: ViewController2 = segue.destination as! ViewController2
if let integerValue = Int(EnterNumber.text!) {
VC2.LabelText = "\(integerValue * 10)"
} else {
print("\(EnterNumber.text!) could not be converted to an integer.")
}
}

My delegate method becomes nil while it shouldn't?

got 2 ViewControllers 1st is ViewController 2nd TableViewCotnroller
class ViewController: UIViewController, CLLocationManagerDelegate, TabVCDelegate {
func reciveData(_ numberOfRows: Int) {
print(numberOfRows)
}
...
}
TableViewController:
protocol TabVCDelegate {
func reciveData(_ numberOfRows: Int)
}
class TabVC: UITableViewController {
var delegate: TabVCDelegate?
#IBAction func passDataBack(_ sender: UIButton) {
delegate?.reciveData(5)
self.dismiss(animated: true, completion: nil)
print(delegate ?? "show me if its nil")
}
my delegate?.reciveData(5) is for some reason nil can't figure it out
it did worked when i had 2 normal ViewController am i missing something about TableViewControllers? or maybe its something else?
any help would be appreciated.
First of:
Make that delegate property weak to avoid strong reference cycle
weak var delegate: TabVCDelegate?
To achieve that your protocol should conform to class
protocol TabVCDelegate: class {
func reciveData(_ numberOfRows: Int)
}
Next:
You must set that delegate somewhere. If you have reference to TabVC instance in your ViewController class then it would look like this:
tabVC.delegate = self
HERE is detailed description about "how to create delegates in Swift"
thanks
actually i did found what was missing, in segue i forgot to set destinationVC.delegate as self when setting segue
:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "goToTableView"{
let destinationVC = segue.destination as! TabVC
destinationVC.delegate = self // <-- this line was missing
destinationVC.dataPassedThroughSegue = locationLabel.text
}
}

Can't pass value from FirstVC to SecondVC using segue

I have two ViewControllers connected via Show segue. I need to pass NSSlider's value from ViewController to SecondViewCotroller.
So, moving slider in ViewController a variable updates in SecondViewController.
How to update a value of imagesQty variable?
// FIRST VIEW CONTROLLER
import Cocoa
class ViewController: NSViewController {
#IBOutlet weak var slider: NSSlider!
#IBOutlet weak var photosLabel: NSTextField!
#IBAction func segueData(_ sender: NSSlider) {
photosLabel.stringValue = String(slider.intValue) + " photos"
self.performSegue(withIdentifier: NSStoryboardSegue.Identifier(rawValue: "SegueIdentifierForSecondVC"), sender: slider)
}
func prepare(for segue: NSStoryboardSegue, sender: NSSlider?) {
if segue.identifier!.rawValue == "SegueIdentifierForSecondVC" {
if let secondViewController =
segue.destinationController as? SecondViewController {
secondViewController.imagesQty = slider.integerValue
}
}
}
}
and
// SECOND VIEW CONTROLLER
import Cocoa
class SecondViewController: NSViewController {
var imagesQty = 30
override func viewWillAppear() {
super.viewWillAppear()
self.view.wantsLayer = true
print("viewWillAppear – Qty:\(imagesQty)")
//let arrayOfViews: [NSImageView] = [view01...view12]
let url = URL(fileURLWithPath: NSHomeDirectory()).appendingPathComponent("Desktop/ArrayOfElements")
do {
let fileURLs = try FileManager.default.contentsOfDirectory(at: url, includingPropertiesForKeys: nil, options: [.skipsHiddenFiles]).reversed()
let photos = fileURLs.filter { $0.pathExtension == "jpg" }
for view in arrayOfViews {
//"imagesQty" is here
let i = Int(arc4random_uniform(UInt32(imagesQty-1)))
let image = NSImage(data: try Data(contentsOf: photos[i]))
view.image = image
view.imageScaling = .scaleNone
}
} catch {
print(error)
}
}
First of all the purpose and benefit of NSStoryboardSegue.Identifier is to create an extension to be able to avoid literals.
extension NSStoryboardSegue.Identifier {
static let secondVC = NSStoryboardSegue.Identifier("SegueIdentifierForSecondVC")
}
Then you can write
self.performSegue(withIdentifier: .secondVC, sender: slider)
and
if segue.identifier! == .secondVC { ...
This error occurs because imagesQty is declared in viewWillAppear rather than on the top level of the class.
Change it to
class SecondViewController: NSViewController {
var imagesQty = 30 // Int is inferred
// override func viewWillAppear() {
// super.viewWillAppear()
// }
}
There is another mistake: The signature of prepare(for segue is wrong. It must be
func prepare(for segue: NSStoryboardSegue, sender: Any?) {
You can‘t change the value because the var is defined in the function and not in the class.
Make your var a class property and it should work.
class SecondViewController: UIViewController {
var imagesQty: Int = 30
...
}

Delegate using Container View in Swift

I'm developing an app for iPad Pro. In this app, containerView use to add additional views and interact with them.
First, I created a protocol:
protocol DataViewDelegate {
func setTouch(touch: Bool)
}
Then, I created my first view controller
import UIKit
class ViewController: UIViewController, DataViewDelegate {
#IBOutlet var container: UIView!
#IBOutlet var labelText: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
}
func setTouch(touch: Bool) {
if touch == true {
labelText.text = "Touch!"
}
}
}
And finally, I created a view that will be embedded in containerView.
import UIKit
class ContainerViewController: UIViewController {
var dataViewDelegate: DataViewDelegate?
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func touchMe(sender: AnyObject) {
dataViewDelegate?. setTouch(true)
}
}
But for some reason, nothing happened, the first view controller receives nothing in setTouch function.
My question is: In this case, using container, how can I make the communication between two ViewsControllers?
Like #nwales said you haven't yet set the delegate. You should do set the delegate in prepareForSegue function on your first viewController (who contain the viewContainer)
First select the embed segue and set an identifier in the attributes inspector.
Then in the parentViewController implement the func prepareForSegue like this:
Swift 4+:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if (segue.identifier == "the identifier") {
let embedVC = segue.destination as! ViewController
embedVC.delegate = self
}
}
Below:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
if (segue.identifier == "the identifier") {
let embedVC = segue.destinationViewController as! ContainerViewController
embedVC.dataViewDelegate = self
}
}
Looks like you defined the delegate, but have not set the delegate. This happens to me all the time.