Ray Wenderlich iOS Interview Questions
Automatic Reference Counting
As the Swift program creates new instances, memory resources are used to store the information associated with each instance. When an instance is no longer needed, Swift will reclaim the resources associated with the instance so that these resources can be used with other instances. The system that Swift uses to keep track of all your instances is called automatic reference counting (ARC). ARC works because Swift can keep a count of how many times an instance is referenced in a program. This is called the reference count. Swift takes care of reference counting automatically.
Inheritance
Classes have the ability to inherit methods and properties from a parent class. Inheritance encourages code reuse. Generally, when you inherit a class, you will add custom properties and methods to the new class. class Person { var name: String = "Name" var age:Int = 0 func profile() -> String { return "I'm \(self.name) and I'm \(self.age) years old." } } class Employee: Person { } In your new class Employee is inheriting Person. To indicate what class you are inheriting, add a colon (:) and the name of the class you are inheriting (called the parent class).
Closures
Closures are self-contained blocks of functionality that can be passed around and used in your code. Closures in Swift are similar to blocks in C and Objective-C and to lambdas in other programming languages. Closures take one of three forms: 1. Global functions are closures that have a name and do not capture any values. 2. Nested functions are closures that have a name and can capture values from their enclosing function. 3. Closure expressions are unnamed closures written in a lightweight syntax that can capture values from their surrounding context. Swift's closure expressions have a clean, clear style, with optimizations that encourage brief, clutter-free syntax in common scenarios. These optimizations include: 1. Inferring parameter and return value types from context 2. Implicit returns from single-expression closures 3. Shorthand argument names 4. Trailing closure syntax
Mutable vs Immutable
Constants are mutable and variables are immutable. Mutable means that the value can be changed. Immutable means that the value cannot be changed.
Explain how an autorelease pool works at the runtime level
Each thread (including the main thread) maintains its own stack of NSAutoreleasePool objects (see "Threads"). As new pools are created, they get added to the top of the stack. When pools are deallocated, they are removed from the stack. Autoreleased objects are placed into the top autorelease pool for the current thread. When a thread terminates, it automatically drains all of the autorelease pools associated with itself.
How could you reverse a string as quickly as possible using Swift ?
Long way: let string = "This is a test string." let characters = string.characters let reversedCharacters = characters.reverse() let reversedString = String(reversedCharacters) Shortest way: String("This is a test string.".characters.reverse())
Explain method swizzling. When you would use it?
Method swizzling is the process of changing the implementation of an existing selector. It's a technique made possible by the fact that method invocations in Objective-C can be changed at runtime, by changing how selectors are mapped to underlying functions in a class's dispatch table.
Which is faster: to iterate through an NSArray or an NSSet?
NSArray is faster than NSSet. The reason is that a set uses hash values to find items (like a dictionary) while an array has to iterate over its entire contents to find a particular object.
What happens when you invoke a method on a nil pointer?
Nothing. This is important because, in Objective-C, sending a message to an object means telling that object to do something, or asking that object for some information. If the runtime system did not treat nil as a special case, it would probably crash.
Optional Binding
Optional bindings give you a way to test an optional and unwrap the optional in an if statement. Optional bindings will save you from explicitly unwrapping the optional inside your if statement. if let myString = s{ "The value of s is " myString }else{ "No value in s" } You can see in that you have a constant declaration right after the if statement so that you are both testing for nil and assigning a temporary constant that you can use in the code block if a value is present.
The lifetime of a Swift object consists of five stages:
1. Allocation (memory taken from stack or heap) 2. Initialization (init code runs) 3. Usage (the object is used) 4. De-initialization (deinit code runs) 5. De-allocation (memory returned to stack or heap)
Explain your process for tracing and fixing a memory leak
Step 1 - for prevention: use ARC (Automatic Reference Counting) Step 2 - for cure: use Instruments (Instruments is a powerful and flexible performance-analysis and testing tool that's part of the Xcode tool set )
What is the difference between frames and bounds?
The bounds of an UIView is the rectangle, expressed as a location (x,y) and size (width,height) relative to its own coordinate system (0,0). The frame of an UIView is the rectangle, expressed as a location (x,y) and size (width,height) relative to the superview it is contained within.
Optional Chaining
The postfix optional operator is a question mark (?). Optional chaining does not put the value into a variable, instead it checks whether this value on the left of the question mark is nil. If it isn't, evaluate the rest of the expression. If it is, evaluate to nil. To use optional chaining: if let roomCount = john.residence?.numberOfRooms { print("John's residence has \(roomCount) room(s).") } else { print("Unable to retrieve the number of rooms.") } // Prints "Unable to retrieve the number of rooms." This tells Swift to "chain" on the optional residence property and to retrieve the value of numberOfRooms if residence exists.
Give two separate and independent reasons why retainCount should never be used in shipping code.
1) The value may vary for so many reasons. Threading alone is reason enough to never trust it. 2) You still have to implement correct reference counting. retainCount will never save you from imbalanced reference counting.
List the five iOS app states.
1. Not Running - The app has not been launched or was running but was terminated by the system. 2. Inactive - The app is running in the foreground but is currently not receiving events. (It may be executing other code though.) An app usually stays in this state only briefly as it transitions to a different state. 3. Active - The app is running in the foreground and is receiving events. This is the normal mode for foreground apps. 4. Background - The app is in the background and executing code. Most apps enter this state briefly on their way to being suspended. However, an app that requests extra execution time may remain in this state for a period of time. In addition, an app being launched directly into the background enters this state instead of the inactive state. For information about how to execute code while in the background, see "Background Execution and Multitasking." 5. Suspended - The app is in the background but is not executing code. The system moves apps to this state automatically and does not notify them before doing so. While suspended, an app remains in memory but does not execute any code. When a low-memory condition occurs, the system may purge suspended apps without notice to make more space for the foreground app.
Swift Data Types
1. String let s:String = "Hey There" 2. Integer let i:Int = -25 3. Float let f:Float = 3.14 4. Double let d:Double = 99.99 5. Boolean let b:Bool = true
Forced Unwrapping
If you are sure that an optional has a value, then you can use an exclamation point (!) to unwrap the value. var s: String? s = "ABC" s! If you attempt to unwrap an optional that has no value, then you will get a runtime error. For this reason, you will want to test your optional with an if statement before attempting to unwrap the optional. if s{ "The value of s is " s! } else{ "No value in s" }
Explain how code signing works
If you don't use code signing, you will only be able to run your code on a simulator. Code Signing is used to protect software and its origin. By using Code Signing, a software program will get a digital signature by the developer. The Benefits of Code Signing 1. Build a trusted relationship with your customers 2. Protect your customers against corrupt or modified codes. The signature is part of the software program, which will make it impossible to modify the program. If the code will be changed, the signature is not valid anymore. The signature will give the end user of the software program that the identity of the creator of the software is guaranteed and it also assured that the code is intact and not changed. 3. Reduce errors and security warnings The operation of Code Signing 1. The software developer will request a Code Signing certificate. 2. A software developer uses a Code Signing program, depending on the platform, to add a digital signature to its program code in combination with the Code Signing certificate. 3. The program will be uploaded to a website, mobile network or is otherwise made available to download or run. 4. If users want to download or run the program, the digital signature will be checked. 5. The browser or other executive program will determine whether it will show a warning with an execution block (this depends on the platform, application and security settings of the user) or permit.
What are the differences between copy and retain?
In a general setting, retaining an object will increase its retain count by one. This will help keep the object in memory and prevent it from being destroyed. What this means is that if you only hold a retained version of it, you share that copy with whomever passed it to you. Copying an object should create another object with duplicate values. Think of this as a clone. You do NOT share the clone with whomever passed it to you.
When dealing with property declarations, what is the difference between atomic and non-atomic?
In iOS atomic and non atomic refers to the property from a thread safety point of view. When we say that a property is atomic that means that it is thread safe , when we say it is non-atomic that means that it is not thread safe. Thread safety means that the code can handle multiple threads.
Take three objects: a grandparent, parent and child. The grandparent retains the parent, the parent retains the child and the child retains the parent. The grandparent releases the parent. Explain what happens
There is a retain cycle between the parent and the child. This will prevent any of the associated objects in the chain from being released from memory. You would need to make one of the references "weak" or "unowned" between the parent and child. This will remove a circular strong reference.
List the Instruments that are part of the standard
Time Profiler, Allocations, Leaks, Activity Monitor, Network, Core Animation, Core Data, GPU Driver, Counters, Energy Diagnostics, File Activity, Metal System Trace, OpenGL ES Analysis, System Trace, System Usage, Zombies, Automation, and Cocoa Layout.
Strong References vs Weak References
When a property is defined in a class, the class is said to have a strong relationship with the property. This means that instances of the class will increase the property's reference count in ARC. When the instance's reference count reaches zero and the instance is disposed of, any properties with strong references will be decreased by one. However, it is possible to write code in which an instance of a class never gets to a point where it has zero strong references. This can happen if two class instances hold a strong reference to each other, such that each instance keeps the other alive. This is known as a strong reference cycle. You resolve strong reference cycles by defining some of the relationships between classes as weak or unowned references instead of as strong references. Because a weak reference does not keep a strong hold on the instance it refers to, it is possible for that instance to be deallocated while the weak reference is still referring to it. Therefore, ARC automatically sets a weak reference to nil when the instance that it refers to is deallocated. And, because weak references need to allow their value to be changed to nil at runtime, they are always declared as variables, rather than constants, of an optional type. Like a weak reference, an unowned reference does not keep a strong hold on the instance it refers to. Unlike a weak reference, however, an unowned reference is used when the other instance has the same lifetime or a longer lifetime. You indicate an unowned reference by placing the unowned keyword before a property or variable declaration. An unowned reference is expected to always have a value. As a result, ARC never sets an unowned reference's value to nil, which means that unowned references are defined using nonoptional types.
Initialization
You initialize an instance to get the instance ready for use. Initialization means you set the starting values for the instance.
