Trouble setting the frame for a custom camera overlay using Swift - swift

As the question states, I'm having trouble setting the view frame for my custom camera overlay using the Swift language. I keep getting an error that states "value of optional type "CGRect" not unwrapped" that I don't quite understand. The problem line is this one:
cameraOverlay.frame = camera.cameraOverlayView?.frame
Xcode attempts to auto-correct the issue by adding a bang (!) at the end of frame, but that does not work either, and creates another error.
Here is my entire nib initialization code for my custom camera overlay:
#IBOutlet var cameraOverlay: UIView!
override func viewDidLoad()
{
super.viewDidLoad()
var camera = UIImagePickerController()
camera.delegate = self
camera.allowsEditing = false
camera.sourceType = UIImagePickerControllerSourceType.Camera
camera.showsCameraControls = false
NSBundle.mainBundle().loadNibNamed("CameraOverlay", owner: self, options: nil)
cameraOverlay.frame = camera.cameraOverlayView?.frame
camera.cameraOverlayView = cameraOverlay
cameraOverlay = nil
self.presentViewController(camera, animated: false, completion: nil)
}
Any help is appreciated. Thanks!
EDIT
Make sure your nib view does not have a white background, or else the camera will not appear. Set the view background color to clearColor, and make sure opaque is unchecked to be safe. I had this problem for a little while until I realized what was happening.

Use this
cameraOverlay.frame = camera.cameraOverlayView!.frame
Actually you are using ? optional chaining which returns frame as wrapped in optional.! is used for optional unwrapping
or you can also do
//it will not crash but you should handle nil case using unwrap by `!` as shown above using `if` condition
cameraOverlay.frame = (camera.cameraOverlayView?.frame)!

Related

Error setting values for one VC for another VC

I am trying to set the values of UILabel's on another view controller. However I keep getting a nil value when I am trying to set temp values for the other view controller's UILabels and such. This is the function that executes the segue:
func swipe(Sender: UISwipeGestureRecognizer!) {
print("swiped left")
let vc = self.storyboard!.instantiateViewControllerWithIdentifier("OnDeck") as! OnDeck
vc.firstBase = UIView(frame: CGRectMake(178, 136, 10, 10))
vc.firstBase.backgroundColor = UIColor.redColor()
vc.firstBase.layer.cornerRadius = vc.firstBase.frame.size.width/2
self.presentViewController(vc, animated: true, completion: nil)
}
I am getting the following error on the line vc.firstBase.backgroundColor = UIColor.redColor()
fatal error: unexpectedly found nil while unwrapping an Optional value
is there something I am missing when attempting to declare the temp values for the outlets?
You should not set those related UI elements, because the UI haven't loaded yet. Instead, pass a value and set it in viewDidLoad of destination controller
class OnDeck: UIViewController {
var color = UIColor.white()
override func viewDidLoad() {
...
firstBase = color
}
}
Then in your swipe method, pass the value only rather than modify the unloaded UILabel or UIView. Else, move the UI related code to the destination viewDidLoad() such as the cornerRadius, frame size, etc

IBOutlet is nil

I have created a standard outlet for a view that will hold different information based on the button selected on the previous screen.
#IBOutlet weak var labelView: UIView!
It shows it is connected in both the story board view and on the code itself, however, every time I get to any reference to the labelView such as:
if detail.description == "About"
{
labelView.backgroundColor = UIColor.red
}
Then the app crashes out with:
fatal error: unexpectedly found nil while unwrapping an Optional value
I have tried everything I can think of or read on the internet:
Removed and replaced the connection
Deleted the derived data folder like one post suggested
Created a reference to self.view to force it to load
Moved it to viewDidAppear
Moved it to viewWillAppear
Moved it to viewDidLoad (which is where it is currently being
called)
I am sure at this point that the answer is rather simple and I am just completely missing it.
To see where the outlet is being set to nil, try this:
#IBOutlet weak var labelView: UIView? {
didSet {
print("labelView: \(labelView)")
}
}
You should see it set to an initial value when the view is loaded. If it then gets set to nil, put a breakpoint on the print and your should be able to see from the backtrace where it's happening.
Views are lazy initialized. In case you are calling the affected line of code before viewDidLoad() in the views life cycle, try to access viewin advance:
if detail.description == "About" {
_ = self.view
labelView.backgroundColor = UIColor.red
}

Simple NSPageController example throws an unknown subview warning and stops working

I'm trying to get a very basic NSPageController to work (in book mode, not history mode). It will successfully transition once, and then stop working.
I suspect I'm creating the NSImageViews I'm loading into it wrong, but I can't figure out how.
The storyboard has a the SamplePageController which holds in initial hard-coded NSImageView.
I suspect I'm missing something really obvious here, since all of the tutorial's I've found for NSPageController are in Objective C not swift, and tend to focus on the history view mode.
The code is:
import Cocoa
class SamplePageController: NSPageController, NSPageControllerDelegate {
private var images = [NSImage]()
#IBOutlet weak var Image: NSImageView!
//Gets an object from arranged objects
func pageController(pageController: NSPageController, identifierForObject object: AnyObject) -> String {
let image = object as! NSImage
let image_name = image.name()!
let temp = arrangedObjects.indexOf({$0.name == image_name})
return "\(temp!)"
}
func pageController(pageController: NSPageController, viewControllerForIdentifier identifier: String) -> NSViewController {
let controller = NSViewController()
let imageView = NSImageView(frame: Image.frame)
let intid = Int(identifier)
let intid_u = intid!
imageView.image = images[intid_u]
imageView.sizeToFit()
controller.view = imageView
return controller
// Does this eventually lose the frame since we're returning the new view and then not storing it and the original ImageView is long gone by then?
// Alternatively, are we not sizing the imageView appropriately?
}
override func viewDidLoad() {
super.viewDidLoad()
images.append(NSImage(named:"text")!)
images.append(NSImage(named:"text-2")!)
arrangedObjects = images
delegate = self
}
}
In this case your pageController.view is set to your window.contentView and that triggers the warning. What you need to do is add a subview in the window.contentView and have your pageController.view point to that instead.
The reason for the warning is that since NSPageController creates snapshots (views) of your content history, it will add them at the same level as your pageController.view to transition between them: that means it will try to add them to pageController.view.superview.
And if your pageController.view is set to window.contentView, you are adding subviews to the window.contentView.superview, which is not supported:
New since WWDC seed: NSWindow has never supported clients adding subviews to anything other than the contentView.
Some applications would add subviews to the contentView.superview (also known as the border view of the window). NSWindow will now log when it detects this scenario: "NSWindow warning: adding an unknown subview:".
Applications doing this will need to fix this problem, as it prevents new features on 10.10 from working properly. See titlebarAccessoryViewControllers for official API.

Swift: UIImageView - Unexpectedly found nil while unwrapping an Optional value

class DisplayImageVC: BasePageView { //BasePageView inherits from UIViewController
#IBOutlet weak var displayImage: UIImageView!
override func viewDidLoad() {
self.displayImage.backgroundColor = UIColor.yellowColor()
}
....
in another class I try this and get a fatal error:
var displayImageView = self._pageContent[1] as DisplayImageVC
displayImageView.displayImage.image = UIImage(named: ("displayChecklane"))
Log:
fatal error: unexpectedly found nil while unwrapping an Optional value
Images.xcassets
var displayImageView = self._pageContent[1] as DisplayImageVC
displayImageView.displayImage.image = UIImage(named: ("displayChecklane"))
You are crashing on the second line. You know this is because something is nil, but you do not know what is nil here. You are assuming it is the image. That is a false assumption; if it were correct, there would be no crash, as you are not force-unwrapping it, and it is legal to assign nil to an image view's image.
Instead, consider this: maybe displayImageView.displayImage is nil. That is, what is nil is the UIImageView you are trying to assign to. This would make sense since this is an outlet. If the DisplayImageVC's view has not loaded, its outlets have not been filled - they are still nil.
How you solve this depends on what you want to do. Personally I think your approach is bogus from the start; you have no business setting another view controller's outlet or a property of its outlet, or any aspect of its interface. You should have an image property in DisplayImageVC, and here, you should be setting that property; that way, when the view controller shows its view, it can configure its own interface.

Set Image of UIImageView

I currently have a UITableView that holds a list of events. Each event has a button where the user can press it to get access to a larger view of a photo associated with the event. I have the UIButton connected and set up but I'm having a hard time setting the image in the new window. Here is my function:
func largeMap(sender: UIButton!) {
let documentsPath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as String
let manager = NSFileManager.defaultManager()
self.performSegueWithIdentifier("largeMapView", sender: self)
println(sender.tag.description)
println(documentsPath+"/Flight"+(sender.tag.description)+"/Map.png")
if let image = UIImage(data: manager.contentsAtPath(documentsPath+"/Flight"+(sender.tag.description)+"/Map.png")!) {
largeMapView.image = image
}
}
When I run the app, it crashes at largeMapView.image = image and gives me "fatal error: unexpectedly found nil while unwrapping an Optional value". I've checked and the path for the image is correct and it is accessing the image but it's not able to set it to the UIImageView. I have the UIImageView outlet set at the top of the class. Why is this happening? I've set UIImageView's in this manner before but it just won't work now.
Basically the problem is that you are using exclamation marks. Exclamation marks are never safe! They can be a "bad smell", a danger signal - and in your code, that's just what they are.
(1)
I have the UIImageView outlet set at the top of the class.
But you do not show how it is set. You do not show what largeMapView is or how it is declared. The declaration might look like this:
#IBOutlet var largeMapView : UIImageView!
If so, that is bad - that is an implicitly unwrapped optional, which means it might be nil. This could be the source of your problem. By using a conditionally unwrapped optional you are covering up the problem - until you try to set into nil, and then you crash. If it is never being set properly, that's the reason for the crash.
(2)
Along the same same lines, the rest of your code, too, should not force-unwrap Optionals (using ! postfix operator) unless you know for certain that they can never be nil. Rewrite like this so that every Optional is unwrapped conditionally and safely:
if let d = manager.contentsAtPath(documentsPath+"/Flight"+(sender.tag.description)+"/Map.png") {
if let image = UIImage(data: d) {
largeMapView.image = image
}
}
This way, if contentsAtPath fails or UIImage(data:) fails, nothing will happen - you won't set your image - but at least you won't crash. And you can use stepping in the debugger to figure out where you are failing. - But even this will not save you if the problem is that largeMapView is a nil implicitly unwrapped Optional.