flip card causes fatal error in swift - swift

I am following this card flipping tutorial and instead of creating the UIView and the UIImageViews programmatically I have created these in my storyboard.
When I click the card, the animation kicks in and turns over to the front image, but when I click again, this creates a fatal error:
unexpectedly found nil while unwrapping an Optional value.
I can not figure out why this error occurs.
Here is the code which is the transformation of the above mentioned tutorial:
class FirstViewController: UIViewController {
#IBOutlet weak var flashCardView: UIView!
#IBOutlet weak var backImage: UIImageView!
#IBOutlet weak var frontImage: UIImageView!
var showingBack = true
override func viewDidLoad() {
super.viewDidLoad()
let singleTap = UITapGestureRecognizer(target: self, action: Selector("tapped"))
singleTap.numberOfTapsRequired = 1
flashCardView.addGestureRecognizer(singleTap)
flashCardView.addSubview(backImage)
view.addSubview(flashCardView)
}
func tapped() {
if (showingBack) {
UIView.transitionFromView(backImage, toView: frontImage, duration: 1, options: UIViewAnimationOptions.TransitionFlipFromRight, completion: nil)
showingBack = false
} else {
UIView.transitionFromView(frontImage, toView: backImage, duration: 1, options: UIViewAnimationOptions.TransitionFlipFromLeft, completion: nil)
//here I get the error when flipping the card back to the back image
showingBack = true
}
}
}

I believe that when you transition, the old image's reference count is decremented, and since they're declared as weak it is getting destroyed. Try removing the weak declarations, and it will probably work. Looking at the tutorial, they don't have weak.

Related

How do I give screenshot file a filename when sharing via UIActivityView

I have created a VC with a print and share friendly version of a bunch of calculations. When I press "share" there appears the little icon and all the share options which is great. I cannot figure out how to add a filename of some kind beside the little icon. I think this would look much more professional if I could get this accomplished.
Hope there is a simple solution someone could help with :)
Here is my code:
import UIKit
class EvenPrintableViewController: UIViewController {
#IBOutlet weak var widthSizeTransfer: UILabel!
#IBOutlet weak var heightSizeTransfer: UILabel!
#IBOutlet weak var lengthTransfer: UILabel!
#IBOutlet weak var calcOutput: UILabel!
// Instantiate variables for Even transfer
var largeSizeRelay: String?
var lengthSizeRelay: String?
var heightRelay: String?
var calcOutputRelay: String?
override func viewDidLoad() {
super.viewDidLoad()
// Sets share icon to share/print view
navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .action, target: self, action: #selector(shareTapped))
// Assign labels to Metric Even VC values via instances above
widthSizeTransfer.text = witdhSizeRelay
heightSizeTransfer.text = heightSizeRelay
heightTransfer.text = heightRelay
calcOutput.text = calcOutputRelay
}
// Share function for share button
#objc func shareTapped() {
let renderer = UIGraphicsImageRenderer(size: view.bounds.size)
let image = renderer.image { ctx in
view.drawHierarchy(in: view.bounds, afterScreenUpdates: true)
}
let vc = UIActivityViewController(activityItems: [image], applicationActivities: [])
vc.excludedActivityTypes = [.assignToContact, .addToReadingList]
vc.popoverPresentationController?.barButtonItem = navigationItem.rightBarButtonItem
present(vc, animated: true)
}
}
First save the UIImage as a temporary png/jpg file:
guard let imageData = image.pngData() else { return }
Then save it as a temporary file, which lets you to choose a file name:
let tempDir = FileManager.default.temporaryDirectory
let imgFileName = "YOUR_IMG_FILE_NAME.png"
let tempImgDir = tempDir.appendingPathComponent(imgFileName)
try? imageData.write(to: tempImgDir)
Then you can share the URL instead:
// Your code
let vc = UIActivityViewController(activityItems: [tempImgDir], applicationActivities: [])
P.S. the file is only temporary.

UIButton become nil when I open settings viewController

I have map and zoom in/out button on it as strong outlet and settings viewController, where show/hide settings crash app because outlet button become nil. How to resolve this?
In mainViewController:
#IBOutlet var zoomIn: UIButton!
#IBOutlet var zoomOut: UIButton!
...
and
func setZoomFalse(){
zoomIn.isHidden = true
zoomOut.isHidden = true
}
func setZoomTrue(){
zoomIn.isHidden = false
zoomOut.isHidden = false
}
SettingsViewController is open with:
self.present(self.settingsViewController, animated: true, completion: nil)
from slide menu
and this call make crash in settingsViewController:
#objc func switchChanged1(_ sender : UISwitch!){
let defaults = UserDefaults.standard
defaults.set(sender.isOn, forKey: settingsView.settingsIsZoom)
isZoom = sender.isOn
if isZoom {
mainViewController.setZoomTrue()
} else {
mainViewController.setZoomFalse()
}
}
I resolve this on this way, I set global variable to true in settingsViewController, which is defined as global in maonViewController, above class definition and in viewWillApear check if this variable is true and if yes I call setZoomTrue and it works on this way, when it's called from different viewController it crashes with nil message ...

Swift SIGABRT Error? But I resolved it? [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
I have yet another error, its the common swift error
Thread 1: signal SIGABRT
I know how to fix this error. Here is my recent question.
Can't resolve error: Thread 1: signal SIGABRT in swift XCODE
But now I am making a new project, and I got this error! So I tried to fix it, I thought I got it - but I didn't.. I have checked all my outlets and everything, But there is no trace of where this is coming from...
Here is my code:
import UIKit
class ViewController: UIViewController {
//Variables
var tempature:Int = 50
var battery:Int = 100
var monsterCount:Int = 0
//Outlets
#IBOutlet weak var BatteryLevel: UILabel!
#IBOutlet weak var TempDisplay: UILabel!
//The spy camera
#IBOutlet weak var monsterImageDisplay: UIImageView?
//The background image
#IBOutlet weak var backgroundImageShow: UIImageView!
//Functions
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
monsterImageDisplay?.isHidden = true
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
//The interval to keep things going
var helloWorldTimer = Timer.scheduledTimer(timeInterval: 3.0, target: self, selector: Selector(("spawnMonstor")), userInfo: nil, repeats: true)
func spawnMonstor() {
monsterImageDisplay?.isHidden = false
monsterCount += 1
if monsterCount >= 3 {
let randomNumberBackgroundImage = arc4random_uniform(10)
if randomNumberBackgroundImage >= 5 {
backgroundImageShow.image = UIImage(named: "main-room-jumpTop")
} else if randomNumberBackgroundImage <= 5 {
backgroundImageShow.image = UIImage(named: "main-room-jumpBottom")
}
} else if monsterCount >= 5 {
let alert = UIAlertController(title: "GAME OVER", message: "Sorry! You died...", preferredStyle: UIAlertControllerStyle.alert)
alert.addAction(UIAlertAction(title: "Okay..", style: UIAlertActionStyle.default, handler: nil))
self.present(alert, animated: true, completion: nil)
}
}
//The shock rooms button
#IBAction func ShockRooms(_ sender: Any) { monsterImageDisplay?.isHidden = true
}
}
Check that your UIImage names are the EXACT same names as the ones in your xcassets folder.
Instead of using the helloWorldTimer, write this at the top of your class, underneath your outlets:
var helloWorldTimer = Timer()
And then inside of your viewDidLoad, add:
helloWorldTimer = Timer.scheduledTimer(timeInterval: 3.0, target: self, selector: Selector(("spawnMonstor")), userInfo: nil, repeats: true)

How can I make this animation work?

I was trying to animate a set of images using this tutorial: https://www.geekylemon.com/animated-loading-screen. I converted the code from objective c to swift in order to implement it into another project, but it seems like it doesn't work properly.
Well, on the the storyboard are three Image Views(AnitmationimageView beeing the same with "L1.png", Loadimageview and the background image of the view controller). I wanted to run the AnitmationimageView and after it a transition to L1,2,3,4 images and after them to Loadimageview and after it to the background image. But when I run the program it only shows me the transition from AnitmationimageView to Loadimageview and the transition from Loadimageview to the background image. Hope this helps in "diagnosing" my problem.
class ViewController: UIViewController {
#IBOutlet weak var AnitmationimageView: UIImageView!
#IBOutlet weak var Loadimageview: UIImageView!
var loading_1: UIImage!
var loading_2: UIImage!
var loading_3: UIImage!
override func viewDidLoad() {
super.viewDidLoad()
AnitmationimageView.animationImages = [UIImage(named: "L1.png"), UIImage(named: "L2.png"), UIImage(named: "L3.png"), UIImage(named: "L4.png")] as? [UIImage]
AnitmationimageView.animationRepeatCount = 1
AnitmationimageView.animationDuration = 3 as CFTimeInterval
AnitmationimageView.startAnimating()
perform(#selector(self.delay1), with: nil, afterDelay: 3)
delay1()
delay2()
delay3()
}
#objc func delay1() {
UIView.beginAnimations(nil, context: nil)
UIView.setAnimationDuration(1.0)
AnitmationimageView.alpha = 0
UIView.commitAnimations()
perform(#selector(self.delay2), with: nil, afterDelay: 1.0)
}
#objc func delay2() {
UIView.beginAnimations(nil, context: nil)
UIView.setAnimationDuration(1.0)
Loadimageview.alpha = 1
UIView.commitAnimations()
perform(#selector(self.delay3), with: nil, afterDelay: 1.5)
}
#objc func delay3() {
UIView.beginAnimations(nil, context: nil)
UIView.setAnimationDuration(1.0)
Loadimageview.alpha = 0
UIView.commitAnimations()
}
}

Unwrapping UILabel always returns nil

I've hooked a UILabel to my VC using the storyboard, does generating a weak var but connected to a storyboard reference. Anyway, whenever I try to unwrap it, all I get is a nil value. What confuses me the most is that I'm able to access it on another method. I've already safe unwrapped it, it avoids the compiler errors, but doesn't solve my problem.
The compiler message is: fatal error: unexpectedly found nil while unwrapping an Optional value
Here is some of the code:
#IBOutlet weak var linesLeftCountLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
skView = SKView(frame: sceneView.frame)
skView.multipleTouchEnabled = false
//Create and configure the scene.
scene = LogoRefactoryScene(size: skView.bounds.size)
scene.scaleMode = .AspectFill
skView.presentScene(scene)
tapGesture = UITapGestureRecognizer(target: self, action: "eraseLine:")
tapGesture.delegate = self
view.addGestureRecognizer(tapGesture)
view.addSubview(skView)
}
Here I'm able to access it:
#IBAction func colorPickerOfColor(sender: UIButton) {
var pickerName = ""
switch sender.tag {
case 0:
pickerName = "green"
case 1:
pickerName = "red"
case 2:
pickerName = "blue"
default:
pickerName = "orange"
}
pickerName += "ColorPicker"
colorPickerView.image = UIImage(named: pickerName)
currentColorName = ColorSelection.fromRaw(sender.tag + 1)!.colorName
let color = ColorSelection.fromRaw(sender.tag + 1)!.getSKColor()
scene.lineColor = color
linesLeftCountLabel.textColor = color
}
Here is where the compiler complains:
func lineHasBeenDrawn() {
linesLeftCountLabel.text = "Any String"
}
Sorry for that guys. lineHasDrawn is a delegate method, that's why the strange behaviour.
My bad.
Please check if you have connected the referencing outlet in the storyboard to the IBOutlet of your code