Learn iOS development using Swift (Arabic tutorials) - Fourth session slides, which covers the following topics:
- Enumerations
- Auto References Count (ARC)
- Delegation Pattern
- Closures
.
The video end up demonstrating: UITableView, performing segues programmatically, passing data between screens, and access information on iOS Documentation.
2. TODAY TOPICS
• Enumerations
• Automatic Reference Count (ARC)
• Delegation pattern
• Closures
• Demo:
• Table view
• Move to another screen programmatically
• Pass data between screens
Ahmed Ali
3. ENUMERATIONS
• An enumeration is a value type used to define a common type for a group of related values.
• Enumeration can have methods and computed properties.
• Also it can deal with numeric data types, strings, and characters.
• Example:
enum Direction
{
case UP
case DOWN
case LEFT
case RIGHT
}
Ahmed Ali
enum Direction : String
{
case UP = "Up"
case DOWN = "Down"
case LEFT = "Left"
case RIGHT = "Right"
}
4. ENUMERATIONS (CONT)
• There are two ways to create enum instances:
• Using enum case directly.
• Create instance from a raw value. This is only available if the enum type is specified.
• Example:
//Use direct case
let up = Direction.UP
//Creating from raw value.
//fromRaw static method returns an optional type
let down = Direction.fromRaw("Down")
Ahmed Ali
5. ENUMERATIONS (CONT)
• Usage example:
//The raw value may come from a user input or a web service response
let rawDir = "Left"
if let dir = Direction.fromRaw(rawDir){
//The rawDir value is one of our supported directions. Lets see which one it is
switch dir{
case .UP:
println("Selected direction is Up")
case .DOWN:
println("Selected direction is Down")
default:
println("Selected direction is (dir.toRaw())")
}
}
Ahmed Ali
6. ENUMERATIONS (CONT)
• Enumeration in Swift are more complicated than this, they can have associated values
with each case.
• Example:
enum Shape{
case SQUARE(width: Int, height: Int)
case CIRCLE(centerX: Int, centerY: Int, radius: Int)
}
let shape = Shape.SQUARE(width: 50, height: 50)
Ahmed Ali
7. ENUMERATIONS (CONT)
• Checking the value for associated value cases example:
switch shape{
case .SQUARE(width: let width, height: let height):
println("Square shape with dimension ((width), (height))")
case .CIRCLE(20, let y, let r) where r > 5:
println("Circle shape with center point ((20), (y))")
case .CIRCLE(let x, let y, _):
println("Circle shape with center point ((x), (y))")
}
Ahmed Ali
8. ARC
• A garbage collector is not a good solution for a limited resources devices.
• Automatic Reference Count (ARC) is the memory management mechanism used widely in
iOS (by Objective-C and Swift).
• ARC keeps track of how many references refer to each class instance.
• When these references become zero, the object’s memory space is deallocated.
• ARC is only applied on class instances; structs and enums are value types, they are not
stored or passed by reference.
Ahmed Ali
9. ARC (CONT)
• Explanation example:
class Order{
var orderDate : NSDate
var product : Product
init(orderDate: NSDate, product: Product){
self.orderDate = orderDate;self.product = product
}
deinit{ println("Order has been removed from the memory") }
}
class Product{
var name : String
init(name: String){ self.name = name }
deinit{ println("Product (name) has been removed from the memory") }
}
Ahmed Ali
10. ARC (CONT)
• Explanation example (Cont):
var product : Product! = Product(name:"iPhone")
var order : Order! = Order(orderDate: NSDate(), product: product)
product = nil
order = nil
Ahmed Ali
11. ARC – RETAIN CYCLE
• All references are strong by default.
• When two instances strongly refer to each other, they will remain in memory even when
they are no more in use.
• Your app may run out of memory and crash.
Ahmed Ali
12. ARC – RETAIN CYCLE (CONT)
• Explanation example:
class Apartment{
var tenant : Person!
deinit{ println("Apartment has been removed from memory")}
}
class Person{
var apartment : Apartment!
deinit{ println("Persone has been removed from memory")}
}
var apartment : Apartment! = Apartment()
var tenant : Person! = Person()
apartment.tenant = tenant
tenant.apartment = apartment
apartment = nil; tenant = nil;
Ahmed Ali
13. ARC – RETAIN CYCLE (CONT)
• Break retain cycle example:
class Apartment{
weak var tenant : Person!
deinit{ println("Apartment has been removed from memory")}
}
class Person{
var apartment : Apartment!
deinit{ println("Persone has been removed from memory")}
}
var apartment : Apartment! = Apartment()
var tenant : Person! = Person()
apartment.tenant = tenant
tenant.apartment = apartment
apartment = nil; tenant = nil;
Ahmed Ali
14. DELEGATION PATTERN
• Delegation pattern allows one type to delegate some of its behaviors to an instance of
another type.
• A real-world example will be used in the demo.
• Example:
class PhotosSlideshow : UIView
{
func show(){}
//the rest of the implmenetation
}
Ahmed Ali
15. DELEGATION PATTERN (CONT)
1. Define a protocol which wraps the needed functionality.
protocol ImagesDataSource
{
func numberOfImagesInSlideshow(slideShowView: PhotosSlideshow) -> UInt
func slideShowView(slideShowView: PhotosSlideshow, imageAtIndex: UInt) ->
UIImage
}
Ahmed Ali
16. DELEGATION PATTERN (CONT)
1. Use this protocol as weak reference in your delegating type
class PhotosSlideshow : UIView
{
weak var delegate : ImagesDataSource!
func show(){}
//the rest of the implmenetation
}
Ahmed Ali
18. DELEGATION PATTERN (CONT)
1. Objective-c protocols allows optional requirements.
class PhotosSlideshow : UIView
{
weak var delegate : ImagesDataSource!
func show(){}
func userDidSelectImage(image: UIImage)
{
delegate?.slideShowView?(self, userSelectedImage: image)
}
//the rest of the implmenetation
}
Ahmed Ali
19. CLOSURES
• A closure encapsulates a code block to be used later.
• Think of it as an function without a name.
• A closure can be used as any type, for example it can be used:
• As the type of a property.
• As a method’s parameter type.
• As a return type.
• Closures are passed by reference.
Ahmed Ali
20. CLOSURES (CONT)
• Example of using Closure as a property type:
var myClosure : ((param1: Int, param2: String) -> String)!
• Or define the closure type with tyepalias:
typealias MyClosureType = (param1: Int, param2: String) -> String
var myClosure : MyClosureType!
Ahmed Ali
21. CLOSURES (CONT)
• Assigning it a value and calling it:
myClosure = {
(firstParam, secondParam) -> String in
println("First param: (firstParam), Second param: (secondParam)")
return "(firstParam) and (secondParam)”
}
myClosure(param1: 4, param2: "String")
Ahmed Ali
22. CLOSURES (CONT)
• Using a closure as a parameter type with typealias:
typealias MyClosureType = (param1: String, param2: String) -> Void
func myMethod(param1: String, param2: Int, closure: MyClosureType){
//method body
closure(param1: "param1", param2: "param2")
}
Ahmed Ali
23. CLOSURES (CONT)
• Calling a method that takes a closure as a parameter:
//use either way
myMethod("param1", param2: 4) {
(param1, param2) -> Void in
//closure body goes here
}
//or
myMethod("param1", param2: 5, closure: {
(param1, param2) -> Void in
//closure body goes here
});
Ahmed Ali
24. CLOSURES (CONT)
• Closure capture their body references.
• Can cause retain cycles if it refers strongly to the instance that refers strongly to it.
• Use weak reference to break the retain cycle.
myMethod("param1", param2: 4) {
[weak self] (param1, param2) -> Void in
}
Ahmed Ali