About AppDelegate window in swift - swift

here is swift default application code in Appdelecage.swift
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
...
Can anyone tell me why create a optional var window?
why no like this as default:
var window: UIWindow = UIWindow()
that will be save lots of "?" and "!"
thx

The job of UIApplicationMain is to see that your window is nil and create and and assign a window for you. I think that's their reasoning.
But in reality, you can just change the question mark to an exclamation mark.
If you were to supply an actual window, it would also be up to you to frame it, as I do here:
https://github.com/mattneub/Programming-iOS-Book-Examples/blob/master/bk2ch01p006customWindowInStoryboardApp/ch14p366customWindowInStoryboardApp/AppDelegate.swift

The var window declaration is to satisfy an optional declaration specified in the UIApplicationDelegate protocol. You're not required to declare it , but if you do, you are not supposed to set it with your own value. The application will set it to its own window and you're only supposed to read it. you still need to provide it as an optional (UIWindow?) because the protocol declares it as such.
Edit:
Oops, I apologize. I've been spoiled by storyboards that I forgot you can actually create the root window programmatically.

Related

Swift performance on optional UI elements

Setting up a UILabel in Swift I can do the following
#IBOutlet var wLabel: UILabel!
or
#IBOutlet var wLabel: UILabel?
Setting the text I can either do
wLabel.text = "..."
or, for the latter do
wLabel?.text = "..." // with a question mark for the optional
Keeping them optional will help for the case when they are unexpectedly nil as it will just skip this call then and go ahead with the code. Having them declared with the ! would crash the app if the label was nil.
Now why would you not make everything optional? The only reason I could think of would be for better performance. Should I stay away from having them optional if my app has a lot of UI elements so them being optional would mean a disadvantage regarding performance? I wasn't able to find any information on this anyhere.
Using ? in your Outlet will make your code untracable
Crashes are very good in some scenarios, because if no crash is there then it becomes super difficult to trace even small error.
Consider the examples of #IBOutlet with !:
#IBOutlet var wLabel: UILabel!
wLabel.isEnabled = true
Just remove the connection of your Outlet label from your storyboard and run the app, your app will crash on wLabel.isEnabled = true. Since you got a crash so you can got to your storyboard see whether the connection is proper or not. In case there is no connect you add it and damn! you solved the problem easily.
Now consider the examples of #IBOutlet with ?:
#IBOutlet var wLabel: UILabel?
wLabel?.isEnabled = true
Do the same thing, just remove the connection of your Outlet label from your storyboard and run the app, your app won't crash at all. You won't be able to know the error, hence making your code a mess and untracable.
Apple guys were very aware of optional thing, they did force unwrapping of #IBOutlet for a reason. And of course there is no performance difference between ! and ?
If you're setting something up as an outlet it's set up as a force unwrapped optional (with exclamation mark !) because Swift requires your classes to have all of their properties initialized when the object is constructed (i.e. init method is called). Outlets are not created during object construction but rather assigned later when the xib or storyboard data is loaded into your component. Force unwrapped optionals are basically a way to say that you guarantee that the property will be initialized after object's init is called and before they're used.
There are no performance gains to using either of these. An Optional? type means that the property can either be nil or have a value. A force unwrapped optional ! means that the property is guaranteed to have a value when it is used. Upholding this is up to the developer and using such property if its value is nil will result in a crash.

Non optional IBOutlet returns Fatal error: when referenced from another UIViewController class

I have a UIView defined in
class InteractViewController: UIViewController {
#IBOutlet weak var tipsView: UIView!
var tipslayer: CALayer {
return tipsView.layer
}
}
There are a number of constraints also attached in the class as well as labels for example.
#IBOutlet weak var tips1Top: NSLayoutConstraint!
#IBOutlet weak var tips1Right: NSLayoutConstraint!
#IBOutlet weak var tipsTitle: UILabel!
#IBOutlet weak var tipsDesc: UILabel!
All are connected on the storyboard to their correct outlets. Referencing these within the actual InteractViewController itself I am able to adjust opacity, update labels on the layer etc.
However, these are not needed unless the user is first using the application so a simple if else on the InteractViewController calls a function to either display and update properties of these or not show them at all.
The function that controls and updates these properties is in another class (Swift file in the project called.
class TipsViewController: UIViewController {
func tips() {
InteractViewController().tipslayer.transform = CATransform3DMakeScale(0.8, 0.8, 1.0)
}
}
Causes the app to crash creating
Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value
on
return tipsView.layer (the InteractViewController)
tipsView and tipslayer are of cause not optionals and are not declared as optionals.
I have three questions I hope I can get assistance with.
Is having the physical reference to the outlets on the ViewController class InteractViewController: UIViewController the problem? If so is it because they are supposed to be programmatically added instead on the class TipsViewController: UIViewController (which does not have a physical visual view controller in Xcode)?
Does having a physical reference to the outlets on the
class InteractViewController: UIViewController
create unnecessary memory use if on InteractViewController the call to the function on the second ViewContoller TipsViewController.tips() is never called so in other words the answer to question 1 is essentially any physical outlets should be programmatically added on lass TipsViewController: UIViewController?
If there is no memory issue and knowing that tipsView and the returning tipslayer are not optionals why am I simply unable to reference them from the tips() function in the other class (TipsViewController: UIViewController)? I have seen multiple posts about "passing data between view controllers" but I am not passing data between variables or arrays. I want/ need to simply update label string, constraints (objects in one view controller class from another view controller class.
I know people are busy so just to say in advance I appreciate all feedback and assistance with the problem.
It was suggested that my question was a duplicate of [What does "fatal error: unexpectedly found nil while unwrapping an Optional value" mean?
But this is not my question. MY question relates specifically to accessing an Outlet from another ViewController which is then generating a Nil response to the Outlet because as explained InteractViewController is apparently not referencing the ViewController. Please read the explanations and answer provided by Rob which answers this specific question.
Your title says "IBOutlet returns Fatal error: when referenced from another UIViewController class". The bottom line is that one view controller should never access another view controller's outlets.
In your code snippet, you employ the InteractViewController() syntax. Unfortunately, this just instantiates view controller, but does not hook up outlets in storyboard. You need to instantiate via storyboard and, even then, you can’t reference your outlets immediately, but only after viewDidLoad is called later. Only the view controller itself should be trying to access its own outlets, anyway.
The TipsViewController() or InteractViewController() syntax says "create a new, blank instance of that view controller". It's equivalent to saying TipsViewController.init() or InteractViewController.init(). And, worse, it's not using the storyboard at all (and thus no outlets will be hooked up). That's not what you want. You should avoid using this ViewController() syntax, as outlets will never been accessible that way.
InteractViewController should determine whether TipsViewController should be presented (e.g. checking user defaults), and if so, present it. The only thing InteractViewController should do, though, is:
figure out whether to present TipsViewController;
if so, present that TipsViewController; and
pass model data (e.g. whatever InteractViewController retrieved from UserDefaults) to the TipsViewController instance that is created for you.
But anything and everything about how TipsViewController presents its subviews, is the purview of TipsViewController alone. InteractViewController should never interact directly with any outlets of TipsViewController.

Why does Swift insist on this being an optional?

Caveat: I've been coding in Swift for about 2 days!
I am following along with some simple tutorials to build a status menu application. The following is a reduction of my AppDelegate.swift class:
import Cocoa
#NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
#IBOutlet weak var window: NSWindow!
#IBOutlet weak var statusMenu: NSMenu!
let statusItem = NSStatusBar.systemStatusBar().statusItemWithLength(-2)
func applicationDidFinishLaunching(aNotification: NSNotification) {
let icon = NSImage(named: "StatusBarImage")
icon?.setTemplate(true)
}
}
My question is, why does Xcode insist that my icon constant be an optional (it was also OK with me forcing it to be unwrapped). The tutorial didn't show that the ? was needed, but Xcode shows me the following error if I leave it out:
Value of optional type 'NSImage' not unwrapped; did you mean to use '!' or '?'?
(I'm using Xcode 6.4, if that makes a difference.)
From Document:
Declaration:
init?(named name: String) -> NSImage
Which means by default it's initialiser is an optional.
Return Value
The NSImage object associated with the specified name or nil if no
such image was found.
Discussion
The NSImage class may cache a reference to the returned image object
for performance in some cases. However, the class holds onto cached
objects only while the object exists. If all strong references to the
image are subsequently removed, the object may be quietly removed from
the cache. Thus, if you plan to hold onto a returned image object, you
must maintain a strong reference to it like you would any Cocoa
object. You can clear an image object from the cache explicitly by
calling the object’s setName: method and specifying nil for the image
name.
That's why it is asking you did you mean to use '!' or '?'
So if you use ! that means you are unwrapping optional value and if you use ? compiler will consider it as optional.
Because image named StatusBarImage might as well not be in the assets and it would result in bad access exception.
Actually Xcode is not forcing anything : if you check the NSImage documentation you will see that the NSImage initializer is a failable initializer.
Like #FruitAddict said the whole point of those initializers is to fail gracefully (by returning an optional with a nil value) when the object could not be created. Check Apple Developer Blog
By adding ! or this ? You know explicitly that imageNamed can returned you a nil.
And Compiler just makes sure that you know about it.

swift and sharedapplication

first post!
i've been working with swift for a while now, but decided to move some of my code to using shared variables and objects. I'm having a fundamental issue with being able to reference appDelegate.SharedApplication().delegate. Even with a basic test application (to see if I could see any fundamental problems), I cannot get a reference to the shared variable -
// AppDelegate.swift
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
let info: String = "test"
}
trying to add - "let ref = UIApplication.sharedApplication().delegate as appDelegate" in another class complains of use of undeclared type app delegate.
removing that cast allows that, but once I try to create another variable reference to the info string, complains of no member named ref.
this seems such an obvious and confusing issue that I thought it time to ask for an answer :) all i want is to be able to use the appdelegate for controlling cllocationmanager and storing the return data in a variable for a view controller class to refer to.
xcode 6.1.1
cheers
Maybe you are confusing the compiler because you are not using the proper case (upper or lower) when referring to variables or classes.
A class starts with an UpperCase letter.
Any variable starts with a lowerCase letter.
While this is not a rule for variables, it is a well-heeded convention.
Thus:
let stringFromDelegate =
(UIApplication.sharedApplication() as AppDelegate).info

Calling method using optional chaining on weak variable causes EXC_BAD_ACCESS

Update: This is fixed in Xcode 6 beta 6.
The following code causes an EXC_BAD_ACCESS on the delegate?.thing() line:
#class_protocol protocol Fooable {
func foo()
}
class Bar : Fooable {
func foo() {
}
}
weak var delegate: Fooable?
let bar = Bar()
delegate = bar
delegate?.foo()
But everything seems right to me. In order for a variable to be weak, it must have optional type. So the variable delegate is optional. A weak variable's type must also be a class type, so I made the protocol a class protocol. Since I use optional chaining, I expect it to either 1) be nil, and do nothing, or 2) not be nil, and call the method, which should succeed. However, it crashes.
Could it be that optional chaining is not atomic and doesn't retain the expression and the object somehow gets deallocated in between the check for nil and the subsequent call?
Interestingly, if you eliminate the variable bar and assign it directly as delegate = Bar(), the crash goes away. This is really perplexing because assigning an expression to a variable and then assigning the variable and assigning the expression directly should generally behave the same.
I suspect the reason weak var delegate: Fooable?is not working is because that line of code, which is using optional chaining, is checking for protocol conformance.
According to Apple Swift Programming manual:
“Even if you are not interoperating with Objective-C, you need to mark
your protocols with the #objc attribute if you want to be able to
check for protocol conformance.”
If you substitute #class_protocol with #objc it should not crash. Also as per the manual, using #objc only allows the protocol to be adopted by classes (no structs or enums conformance).
Like #PartiallyFinite, I had to play with the code a little too. Apple's iBook on Swift has a blurb about this that may help (with a protocol named ExampleProtocol and a class SimpleClass that conforms to that protocol):
"Even though the variable protocolValue has a runtime type of SimpleClass, the compiler treats it as the given type of ExampleProtocol. This means that you can’t accidentally access methods or properties that the class implements in addition to its protocol conformance.”
That said, you should be able to call foo() on your delegate (barring it doesn't go away before calling it), but just remember the delegate here is declared to be of type Fooable?, not Bar, under the hood. This may be a bug, but I got it to work by entering:
weak var delegate: Bar? = bar
delegate?.foo()