The array is an ordered random-access collection
Read – O(1) – read by index
Search – O(N)
Add element – O(1) or O(N) worst case. If the array should be shifted to the new memory space, than O(N). If the array has enough place from the start or at the end – than O(1). O(N) if adding inside the array with shifting.
Removing element – O(N) should be shifted after deletion.
A set is a collection of unique data
Search – O(1)
Add element – O(1)
Removing element – O(1)
In worst cases with collision, it is O(N) for all operations
Set has a hidden array inside where indexes hash code which is a result of the hash function of value. Value is saved by this calculated index.
If new different values have the same hashcode, they are stored in the same element as the new value of the linked list
If new values are the same and hashcodes are also the same, than this insert operation will be ignored, because this value is not unique and is already in the Set
The dictionary is a collection of pairs of key-value
Search – O(1)
Add element – O(1)
Removing element – O(1)
In worst cases with collision, it is O(N) for all operations
Dictionary has a hidden array inside where indexes hash code which is a result of the hash function of key. Key and value are saved by this calculated index.
If new different key-value has the same hashcode, they are stored in the same element as the new value of the linked list
If new values are the same and hashcodes are also the same, than this insert operation will be ignored, because this value is not unique and is already in the Dictionary
Що відбувається на кожному етапі завантаження контролера:
спочатку викликається функція viewDidLoad.
viewDidLoad – оутлети вже встановлені і можна робити налаштування інтерфейсу з моделі, але врахуйте, що можуть бути не обчислені розмір та положення елементів на екрані, тому намагайтеся не використовувати код пов’язаний з bounds у цій функції. Ця функція викликається один раз на
життєвий цикл контролера.
viewWillAppear – працюємо з даними, які могли змінитися, поки контролер не відображається на екрані (усі розміри вже встановлені). viewWillAppear викликається до того, як екран буде показаний, він викликається після viewDidLoad, тут ми вже можемо зчитувати frame наприклад з Label, Button, які були поставлені, тут frame вже встановлені коректно.
viewDidAppear – стартуємо анімацію
viewWillDisappear – тут ми зупиняємо анімацію робимо чищення екрана, якихось даних, якщо це необхідно
viewDidDisappear – викликається дуже рідко.
Методи можуть викликати кілька разів у життєвому
цикл контролера. Обов’язково викликайте super.view… для всіх
методів.
Вони потрібні для того, щоб відстежувати стан вашого контролера, стан екрану, що взагалі відбувається.
Layout:
func view WillLayoutSubviews()
func viewDidLayoutSubviews()
Методи викликаються щоразу, коли frame був змінений (досить часто). Необхідні для відстеження геометричних параметрів елементів, до та після Autolayout.
Між will і did відбувається Autolayout.
awakeFromNib ()
Метод викликається для всіх елементів, які з’являються з Storyboard, Xib files, відбувається до того, як будуть встановлені всі оутлети, постарайтеся не використовувати цей спосіб і помістити код, в viewDidLoad або
viewWillAppear.
There are three types of closures in Swift:
Global functions are functions that are declared in the global scope of the program.
Nested functions are functions that are declared inside another function and have access to variables and constants from the outer function.
Closure expressions are anonymous functions that can be passed as arguments to other functions or stored in variables or constants.
@escaping, non-escaping and Optional closure:
@escaping – Informs that the closure can be saved or how the calling scope can survive.
non-escaping – Informs that the closure will not be saved and it will not survive the scope of the calling function.
Optional closure – if the closure is optional, then it is not necessary to mark it as @escaping, it will be optional by default.
Func and closures – Reference Type:
This is when functions and closures are written in variables, they do not create new objects, they store references. That is,
a closure can be stored in many places, but it will actually be the same closure, not copies of it.
Retain Cycle is a situation when 2 objects hold strong links to each other and thereby keep each other in memory. This causes them to prevent ARC from destroying itself from memory (because ARC holds on to the object until it has at least one strong reference. This situation leads to a memory leak, which in turn can cause the application to crash.
Classes have additional features that structures do not have:
Comparison of classes and structures
Classes and structures in Swift have a lot in common. In both classes and structs, you can:
The array is an ordered random-access collection
Read – O(1) – read by index
Search – O(N)
Add element – O(1) or O(N) worst case. If the array should be shifted to the new memory space, than O(N). If the array has enough place from the start or at the end – than O(1). O(N) if adding inside the array with shifting.
Removing element – O(N) should be shifted after deletion.
A set is a collection of unique data
Search – O(1)
Add element – O(1)
Removing element – O(1)
In worst cases with collision, it is O(N) for all operations
Set has a hidden array inside where indexes hash code which is a result of the hash function of value. Value is saved by this calculated index.
If new different values have the same hashcode, they are stored in the same element as the new value of the linked list
If new values are the same and hashcodes are also the same, than this insert operation will be ignored, because this value is not unique and is already in the Set
The dictionary is a collection of pairs of key-value
Search – O(1)
Add element – O(1)
Removing element – O(1)
In worst cases with collision, it is O(N) for all operations
Dictionary has a hidden array inside where indexes hash code which is a result of the hash function of key. Key and value are saved by this calculated index.
If new different key-value has the same hashcode, they are stored in the same element as the new value of the linked list
If new values are the same and hashcodes are also the same, than this insert operation will be ignored, because this value is not unique and is already in the Dictionary
Our task is to pass data from the FirstViewController class to the SecondViewController class using a delegate. First, let’s create a protocol with a required method and a String type parameter.
Let’s create a class called First View Controller.
FirstViewController has an optional delegate, type is FirstViewControlleDelegate. The delegate property will be initialized with the SecondViewController class. This class will conform to the FirstViewControlleDelegate protocol
Let’s create two objects and initialize them.
Let’s assign the property optional delegate to the class secondVC.
Next, you can execute the passData method from the class FirstViewController, even though the passData method is in the class SecondViewController.
As shown in the following example:
func funcname() {
//statements of outer function
func anotherFuncname() {
//statements of inner function
}
}
Here, the function anotherFuncname() is inside the body of another function funcname().
It should be noted that, inner functions can be only called and used inside the enclosing function (outer function).
func operate(with symbol:String) -> (Int, Int) -> Int {
func add(num1:Int, num2:Int) -> Int {
return num1 + num2
}
func subtract(num1:Int, num2:Int) -> Int {
return num1 – num2
}
let operation = (symbol == “+”) ? add : subtract
return operation
}
let operation = operate(with: “+”)
let result = operation(2, 3)
print(result)
When you run the program, the output will be: 5 .
In the above program,
The nested function add() and substract() in a way are being used outside of the enclosing function operate() . This is possible because the outer function returns one of these functions.
We’ve used the inner function outside the enclosing function operate() as operation(2, 3). The program internally calls add(2, 3) which outputs 5 in the console.
With @discardableResult attribute, the compiler won’t show a warning about the unused return value
Naming Constants and Variables. Constant and variable names can’t contain whitespace characters, mathematical symbols, arrows, private-use Unicode scalar values, or line- and box-drawing characters. Nor can they begin with a number, although numbers may be included elsewhere within the name.
Once you’ve declared a constant or variable of a certain type, you can’t declare it again with the same name in the same scope, or change it to store values of a different type. Nor can you change a constant into a variable or a variable into a constant.
Optionals. Swift also introduces optional types, which handle the absence of a value. Optionals say either “there is a value, and it equals x” or “there isn’t a value at all”. Using optionals is similar to using nil pointers in Objective-C, but they work for any type, not just classes. Not only are optionals safer and more expressive than nil pointers in Objective-C, but they’re also at the heart of many of Swift’s most powerful features
Unified files make code easier to maintain. Again, an old standard of the C language holds Objective-C back: a two-file requirement. This means that programmers have to update and maintain two separate files of code, whereas, in Swift, these become one. That means less work for programmers, but not at the cost of speed on the front end
Better compiler. Swift is built with the Low-Level Virtual Machine (LLVM), a compiler that’s used by languages like Scala, Ruby, Python, C# and Go. The LLVM is faster and smarter than previous C compilers, so more workload is transferred from the programmer to Xcode, and the compiler
Type inference. Swift uses type inference extensively, allowing you to omit the type or part of the type of many variables and expressions in your code. For example, instead of writing var x: Int = 0, you can write var x = 0, omitting the type completely—the compiler correctly infers that x names a value of type Int
A lot of programming languages has automatic memory management, but also they have garbage collection mechanism which allows removing unused objects from memory. Swift doesn’t have this mechanism. The automatic memory management ins Swift names ARC (Automatic reference counting) and you need to watch out for the weak and strong references between objects. If two or more objects will have strong references to each other, that it will be a retain cycle and all of these objects can’t be removed from memory, which leads to memory leaks and critical app shut down. More about weak and strong links in a source section
The protocol in Swift is a mechanism to achieve abstraction. It is easy with protocols to build a communication between classes or modules with high level of replacability. When class e.g, based on protocol, not on concrete class, then it is super easy to replace this part on another class which just conformed this protocol. This technique is super useful in testing and for applying a OO(object oriented), SOLID and DI (dependency injection) principles.
On the first screen defined protocol and two classes which implemented this protocol. Both of them should implement the load method, but each of them can implement it in different way. RemoteProductsProvider loads products from server, LocalProductsProvider loads products from local disk for example. So this two classes conforms the ProductLoaderProtocol protocol.
On the second screen you can see that HomeController works not with concrete class, but through protocol (abstraction). Controller don’t know with which actual implementation of loader it works.
This concept widely used for testing. For example, in testing mode it is convenient to replace RemoteLoader on LocalLoader and don’t spent time on request to real server
Що відбувається на кожному етапі завантаження контролера:
спочатку викликається функція viewDidLoad.
viewDidLoad – оутлети вже встановлені і можна робити налаштування інтерфейсу з моделі, але врахуйте, що можуть бути не обчислені розмір та положення елементів на екрані, тому намагайтеся не використовувати код пов’язаний з bounds у цій функції. Ця функція викликається один раз на
життєвий цикл контролера.
viewWillAppear – працюємо з даними, які могли змінитися, поки контролер не відображається на екрані (усі розміри вже встановлені). viewWillAppear викликається до того, як екран буде показаний, він викликається після viewDidLoad, тут ми вже можемо зчитувати frame наприклад з Label, Button, які були поставлені, тут frame вже встановлені коректно.
viewDidAppear – стартуємо анімацію
viewWillDisappear – тут ми зупиняємо анімацію робимо чищення екрана, якихось даних, якщо це необхідно
viewDidDisappear – викликається дуже рідко.
Методи можуть викликати кілька разів у життєвому
цикл контролера. Обов’язково викликайте super.view… для всіх
методів.
Вони потрібні для того, щоб відстежувати стан вашого контролера, стан екрану, що взагалі відбувається.
Layout:
func view WillLayoutSubviews()
func viewDidLayoutSubviews()
Методи викликаються щоразу, коли frame був змінений (досить часто). Необхідні для відстеження геометричних параметрів елементів, до та після Autolayout.
Між will і did відбувається Autolayout.
awakeFromNib ()
Метод викликається для всіх елементів, які з’являються з Storyboard, Xib files, відбувається до того, як будуть встановлені всі оутлети, постарайтеся не використовувати цей спосіб і помістити код, в viewDidLoad або
viewWillAppear.
Classes have additional features that structures do not have:
Comparison of classes and structures
Classes and structures in Swift have a lot in common. In both classes and structs, you can:
hitTest methods return nil if
If the hitTest method returns nil, than it won’t pass the event to the hitTest of its subviews
By overriding the hitTest method you can prevent handling or write pass-through logic for subviews. For example, if you want to handle events only in subviews but not for container view.
Understanding cocoa and cocoa touch responder chain
iOS Responder Chain: UIResponder, UIEvent, UIControl and uses
Apps receive and handle events using responder objects. A responder object is any instance of the UIResponder class and common subclasses include UIView, UIViewController, and UIApplication. Responders receive the raw event data and must either handle the event or forward it to another responder object. When your app receives an event, UIKit automatically directs that event to the most appropriate responder object, known as the first responder.
Unhandled events are passed from responder to responder in the active responder chain, which is the dynamic configuration of your app’s responder objects. The following image shows the responders in an app whose interface contains a label, a text field, a button, and two background views. The diagram also shows how events move from one responder to the next, following the responder chain.
If the view chooses to not handle a touch event, then it will be sent up the responder chain, which will follow this path:
The application will receive events from sources such as:
Determine an event’s first responder
UIKit designates an object as the first responder to an event based on the type of that event. Event types include:
Note
Motion events related to the accelerometers, gyroscopes, and magnetometer don’t follow the responder chain. Instead, Core Motion delivers those events directly to the designated object. For more information, see Core Motion Framework
When a touch occurs, UIKit creates an UITouch object and associates it with a view. As the touch location or other parameters change, UIKit updates the same UITouch object with the new information. The only property that doesn’t change is the view. (Even when the touch location moves outside the original view, the value in the touch’s view property doesn’t change). When the touch ends, UIKit releases the UITouch object.