├── LICENSE ├── README.md ├── version_EN-US.md └── version_PT-Br.md /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Vinicius Carvalho Marques 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Questões de entrevistas em iOS 2 | 3 | O intuito deste repositório é montar um guia de perguntas mais comuns em entrevistas para vagas em iOS, onde a base e as principais perguntas são uma transcrição dos vídeos da [Harsivu Edu](https://www.youtube.com/channel/UCKIpdz6fS_CTemcqMrFhDwQ) 4 | 5 | Link para versão [PT-Br](version_PT-Br.md) / [EN-US](version_EN-US.md) 6 | 7 | ### Importante 8 | 9 | > Alguns termos não são literalmente traduzidos pois não temos algo relativo em PT-BR ou não faria sentido ler de acordo com a linguagem. 10 | 11 | ### Material de estudo 12 | 13 | Um guia para ter um norte nos estudos e ver os tópicos importantes em conjunto com as questões você encontra nesse [roadmap de iOS](https://medium.com/@ronanrodrigo/siga-por-este-caminho-um-guia-de-estudos-sobre-desenvolvimento-de-software-db857c4f04f9) 14 | 15 | ## Contribuindo 16 | 17 | Caso queira contribuir com alguma pergunta que viu em algum teste, seu PR será muito bem vindo! 18 | 19 | -------------------------------------------------------------------------------- /version_EN-US.md: -------------------------------------------------------------------------------- 1 | ## Questions 2 | 3 | 1. [Copy vs Readonly](#copy-vs-readonly) 4 | 2. [Copy vs Strong](#copy-vs-strong) 5 | 3. [Weak vs Strong](#weak-vs-strong) 6 | 4. [Weak vs Unowned](#weak-vs-unowned) 7 | 5. [Gist of all the attributes](#gist-of-all-the-attributes) 8 | 6. [ARC & Retain Cycle](#arc-and-retain-cycle) 9 | 7. [Optional in Swift](#optional-in-swift) 10 | 8. [What is ??](#what-is-??) 11 | 9. [Optional Chaining](#optional-chaining) 12 | 10. [Optional Binding](#optional-binding) 13 | 11. [Delegate vs Notification](#delegate-vs-notification) 14 | 12. [Class vs Struct](#class-vs-struct) 15 | 13. [Enum](#enum) 16 | 14. [Guard](#guard) 17 | 15. [Defer](#defer) 18 | 16. [MVVM](#mvvm) 19 | 17. [Dynamic Dispatch](#dynamic-dispatch) 20 | 18. [Static Dispatch](#static-dispatch) 21 | 19. [Closure](#closure) 22 | 20. [@escaping & nonescaping](#@escaping-and-nonescaping) 23 | 21. [What is "lazy"?](#what-is-lazy?) 24 | 22. [Unowned self & weak self](#unowned-self-&-weak-self) 25 | 23. [Process & Threads](#process-&-threads) 26 | 24. [Operation & GCD](#operation-&-GCD) 27 | 25. [Operation](#operation) 28 | 26. [OperationQueue](#operationQueue) 29 | 27. [GCD - Grand Center Dispatch](#GCD-grand-center-dispatch) 30 | 28. [What does a Dispatchgroup do?](#what-does-a-dispatchgroup-do?) 31 | 29. [Codable & Decodable in Swift](#codable-&-decodable-in-swift) 32 | 30. [Codable for complex JSON](#codable-for-complex-JSON) 33 | 31. [Any vs AnyObject](#any-vs-anyobject) 34 | 32. [Access Specifiers in Swift](#access-specifiers-in-swift) 35 | 33. [Generics](#generics) 36 | 34. [CoreData Stack](#coredata-stack) 37 | 35. [Why use NSFetchedResultsController?](#why-use-nsfetcherresultscontroller?) 38 | 36. [POP: Protocol Oriented Programming](#pop-protocol-oriented-programming) 39 | 37. [KVC & KVO](#kvc-&-kvo) 40 | 38. [Push Notification](#push-notification) 41 | 39. [Content Hugging & Compression resistance](#content-hugging-&-compression-resistance) 42 | 40. [Singleton](#singleton) 43 | 41. [Why Singleton is bad?](#why-singleton-is-bad?) 44 | 42. [Dependency Injection](#dependency-injection) 45 | 43. [What is ABI?](#what-is-ABI?) 46 | 44. [What is viewDidLayoutSubviews?](#what-is-viewDidLayoutSubviews?) 47 | 45. [What is loadView?](#what-is-loadView?) 48 | 46. [NSArray vs Array](#nsarray-vs-array) 49 | 47. [NSDictionary vs Dictionary](#nsdictionary-vs-dictionary) 50 | 48. [Computted and stored properties](#computed-and-stored-properties) 51 | 49. [Property Observer for computed properties](#property-observer-for-computed-properties) 52 | 50. [Can we use computed or stored properties in extension?](#can-we-use-computed-or-stored-properties-in-extension?) 53 | 51. [Can we write extension for struct/enum/protocol?](#can-we-write-extension-for-struct-enum-protocol?) 54 | 52. [Is Optional an Enum?](#is-optional-an-enum?) 55 | 53. [Sync vs Async: deadlock situation](#sync-vs-async-deadlock-situation) 56 | 54. [Example of Strong & Weak](#example-of-strong-weak) 57 | 58 | ## Copy vs Readonly 59 | 60 | - Copy 61 | 62 | It creates new copy of an object, and once new object is created retain count will be 1 63 | Use copy when you need the value of an object as it is, and you don’t want other object to update the value of your object 64 | 65 | - Readonly 66 | 67 | Indicates that the property is readonly 68 | Only generates getter, no setters will be generated 69 | If you try to change value, you will get compiler error 70 | 71 | # Copy vs Strong 72 | 73 | - Copy 74 | 75 | It creates new copy of an object, and once new object is created retain count will be 1 76 | Use copy when you need the value of an object as it is, and you don’t want other object to update the value of your object 77 | Create setters e getters 78 | 79 | - Strong 80 | 81 | Increases the retain count by 1 82 | Creates setters and getters 83 | Object will be mutable 84 | 85 | # Weak vs Strong 86 | 87 | - Weak 88 | 89 | Does not increase the retain count 90 | Don’t protect the object from being deallocated by ARC 91 | On deallocation, weak objects will be set to nil, and that’s all weak references are optional 92 | Creates setters and getters 93 | 94 | - Strong 95 | 96 | Increases the retain count by 1 97 | Protects the object from being deallocated by ARC 98 | Creates setters and getters 99 | Object will be mutable 100 | 101 | # Weak vs Unonwned 102 | 103 | - Weak 104 | 105 | Does not increase the retain count 106 | Don’t protect the object from being deallocated by ARC 107 | On deallocation, weak objects will be set to nil, and that’s all weak references are optional 108 | Creates setters and getters 109 | 110 | - Unowned 111 | 112 | Does not increase the retain count 113 | On deallocation, weak objects will be set to nil, and that’s why all weak references are optional 114 | Creates setters and getters 115 | 116 | Note: It’s important that you only use unowned references when you really know that the object will never be nil once it has been set 117 | 118 | # Gist of all the attributes 119 | 120 | - Strong: Add reference to keep the object alive; 121 | - Weak: doesn’t add reference so object can become nil by arc 122 | - Assign: normal assign, no reference, used mostly for primitive data types 123 | - Copy: makes new copy of an object, the copy will be immutable 124 | - Nonatomic: makes not thread safe objects, increases perfomance 125 | - Readwrite: Creates the getter & setters 126 | - Readonly: Creates only getters 127 | 128 | # ARC & Retain Cycle 129 | 130 | ARC is apples way of handling memory management for us. What is does is, for each object it keeps a count of how many strong references are pointing to that object. And as long as there is a strong reference for a object, the object will stay in memory. 131 | 132 | # Optional in Swift 133 | 134 | Optional allows you to write flexible and more safe code; 135 | Question mark means, it can be nil or some value 136 | 137 | # What is ?? 138 | 139 | To provide default value for a variable which can be nil 140 | It says hey if its nothing there then use this value 141 | It is similar to saying “!=nil” 142 | 143 | # Optional Chaining 144 | 145 | Optional chaining is the way by which we try to retrieve a values from a chain of optional values 146 | Allows you to fail gracefully when you try to access a property of an object which is nil 147 | 148 | ex: `let album = albumReleased(year: 2006)?.uppercased()` 149 | 150 | Optional chaining can be as long as required 151 | 152 | # Optional Binding 153 | 154 | Other than forced unwrapping, optional binding is a simpler and recommended way to unwrap an optional. You use optional binding to check if the optional contains a value or not. If it does contain a value, unwrap it and put it into a temporary constant or variable; With optional binding, you are creating a new reference to whatever you just unwrapped, and generally, that’s strong reference. 155 | 156 | ex: 157 | 158 | ``` 159 | if let constantName = someOptional { 160 | statements 161 | } 162 | ``` 163 | 164 | # Delegate vs Notification 165 | 166 | Delegates: used in one to one communication 167 | Notification: used in one to many communication 168 | 169 | # Class vs Struct 170 | 171 | Class: reference type, means any changes in one ref, will effect other ref as well 172 | Struct: value type, means changes in one value will not effect the others 173 | 174 | ex: 175 | 176 | ``` 177 | class SomeClass { 178 | var name: String 179 | init(name: String) { 180 | self.name = name 181 | } 182 | } 183 | 184 | Var aClass = SomeClass(name: “”Bob) 185 | Var bClass = aClass // aClass and bClass now reference the same instance! 186 | bClass.name = “Sue” 187 | print(aClass.name) //“Sue” print(bClass.name) //“Sue” 188 | ``` 189 | 190 | ``` 191 | struct SomeStruct { 192 | var name: string 193 | init(name: String) { 194 | self.name = name 195 | } 196 | } 197 | 198 | var aStruct = SomeStruct(name: “Bob”) 199 | var bStruct = aStruct // aStruct and bStruct now reference the same instance 200 | bStruct.name = “Sue” 201 | print(aStruct.name) // “Bob” 202 | print(bStruct.name) // “Sue” 203 | ``` 204 | 205 | # Enum 206 | 207 | Group of related values 208 | 209 | Raw = values defined in Enum 210 | 211 | ``` 212 | Enum Directions: Int { 213 | case up = 1 214 | case down 215 | case left 216 | case right 217 | } 218 | ``` 219 | 220 | Associated = passed as param to a enum 221 | 222 | ``` 223 | Enum ExampleAssociation { 224 | case name(String) 225 | } 226 | ``` 227 | 228 | # Guard 229 | 230 | Provides early exit, and doesn’t allow any code if condition is not true 231 | 232 | # DEFER 233 | 234 | Defer statement is used to execute a piece of code exactly before the execution departs the recent scope; 235 | The defer statement is executed after the return! 236 | The defer statement is executed no matter how you exit 237 | 238 | ``` 239 | Func deferEx() { 240 | print(“”beginning) 241 | var value: String? 242 | defer { 243 | if let v = value { 244 | print(“Ending execution of \(v)”) 245 | } 246 | } 247 | value = “defer function” 248 | print(“Ending”) 249 | } 250 | ``` 251 | 252 | # MVVM 253 | 254 | In MVC - View send events to the Controller, the controller then send request to model for data and perform business logic if required, model notifies controller in case of any data change and controller send data to View to presentMVC - Resulted into massive view controller which were difficult to manage 255 | In MVVM - View Controller and View is combined to become “View”And one more layer is added called “ViewModel”, this new layer will communicate with model and process the data and perform some business logic if required and sends final data to ViewController that is only required to update the UI. 256 | 257 | # Dynamic Dispatch 258 | 259 | Dynamic dispatch is the process of selecting which implementation of a polymorphic operation (method or function) to call at run time; 260 | For example, if a subclass overrides a method of its superclass, dynamic dispatch figures out which implementation of the method needs to be invoked, that of the subclass or that of the parent class; 261 | By applying the “dynamic” declaration modifier to a member of a class, you tell the compiler that dynamic dispatch should be used to access that member; 262 | “Dynamic” declaration modifier can only be used for members of a class. Structures and enumerations don’t support inheritance, which means the runtime doesn’t have to figure out which implementation it needs to use;Swift provides 2 ways to achieve dynamism: Table Dispatch and Message Dispatch; 263 | Table Dispatch: With this method, a class is associated with a so-called virtual table which comprises an array of function pointers to the real implementation corresponding to that class. Note that the table is constructed at compile time. Thus, there are only two additional instructions (read and jump) as compared to static dispatch. So the dispatch should be theoretically pretty fast. 264 | 265 | Message Dispatch: It is objective-c that provides this mechanism. Every time an Objective-C method is called, the invocation is passed to “objc_msgSend” which handles the look ups. Unlike table dispatch, the message passing dictionary could be modified at runtime, enabling us to adjust the program behaviors while running. 266 | 267 | # Static Dispatch 268 | 269 | When something is statically dispatched, we are dealing with the opposite scenario. With static dispatch, the compiler does in fact know which property or method is being called at runtime, which is a performance boost. You can achieve static dispatch by marking a base class with the “final” keyword. This lets the compiler know that this class can not have any subclasses and that the method/property you are referring to is its only implementation. 270 | 271 | Another example is the “static“ keyword for when defining type methods of properties. This keyword is really just short for “final class”. This lets the compiler know that this is the final implementation of this method and it will not be overridden. Therefore, it will be statically dispatched.When defining a type method you can mark it with “class” or “static”, but which you choose determine how it will be dispatched. 272 | 273 | 274 | # Closure 275 | 276 | Closures are self-contained blocks of functionality that can be passed around and used in your code; 277 | Closures are headless functions. Closures are functions without the func keyword and the function name. They are also known as anonymous functions. 278 | 279 | Syntax - 280 | ``` 281 | { (parameter) -> return type in 282 | statement 283 | } 284 | ``` 285 | 286 | ex: 287 | ``` 288 | var sayHello = {(name: String) -> String in 289 | return “Hello \(name)” 290 | } 291 | sayHello(“Richa”) 292 | 293 | Passing inside a function syntax - 294 | 295 | Func sayHello(name: string, closure(String) -> void) { 296 | closure(“Hello \(name)”) 297 | } 298 | sayHello(name: “Richa”) { name in 299 | print(name) 300 | } 301 | ``` 302 | 303 | # @escaping & @nonescaping 304 | 305 | If a closure is passed as an argument to a function and it is invoked after the function returns, the closure is escaping; 306 | Its mostly useful/required for network calls, you would want your completion handler to live after return statement; 307 | There are many different benefits of making non-escaping, it will take care about the memory allocation for the closure 308 | 309 | # What is “lazy”? 310 | 311 | A lazy stored property is a property whose initial value is not calculated until the first time it is used. You indicate a lazy stored property by writing the “lazy” modifier before its declaration. If the your app is a complex one, then the memory issues are one of the major challenges. So, the developer should be really writing an optimized code which consider memory allocation at first place. The developer need to avoid doing expensive work unless it’s really needed. We can achieve that by using lazy; 312 | 313 | You can’t use lazy with let; 314 | Your can’t use it with computed properties. Because, a computed property returns the value every time we try to access it after executing the code inside the computation block; 315 | You can use lazy only with members of struct and class; 316 | Lazy variables are not initialized automatically and so is not thread safe 317 | 318 | # [unowned self] & [weak self] 319 | 320 | The only time where you really want to use [unowned self] or [weak self] is when you could create a strong reference cycle. A strong reference cycle is when there is a loop of ownership where objects end up owning each other (maybe through a third party) and therefore they will never be deallocated because they are both ensuring that each other stick around; 321 | 322 | In case of a closure, you just need to realize that any variable that is referenced inside of it, gets “owned” by the closure. As long as the closure is around, those objects are guaranteed to be around. The only way to stop that ownership, is to use the [unowned self] or [weak self]. So if a class owns a closure, and that closure captures a strong reference to that class, then you have a strong reference cycle between the closure and the class. This also includes if the class owns something that owns the closure; 323 | 324 | If self could be nil in the closure use [weak self]; 325 | If self will never be nil in the closure use [unowned self] 326 | 327 | # Process & Threads 328 | 329 | A process can contain multiple threads of execution, and each thread can perform multiple tasks one at a time; 330 | Task: A simple, single piece of work that needs to be done; 331 | Thread: A mechanism provide by the operating system that allows multiple sets of instructions to operate at the same time within a single application; 332 | Process: An executable chunk of code, which can be made up of multiple threads 333 | 334 | # Operation & GCD 335 | 336 | Both are used to do any type of multithreading operation in iOS 337 | GCD: Is a lightweight way to represent units of work that are going to be executed concurrently. You don’t schedule these units of work; The system takes care of scheduling for you. Adding dependency among blocks can be a headache. Cancelling or suspending a block creates extra work for you as a developer! Operation: Adds a little extra overhead compared to GCD, but you can add dependency among various operations and re-use, cancel or suspend them. 338 | 339 | Operation and OperationQueue are built on top of GCD. As a very general rule, apple recommends using the highest-level abstraction, then dropping down to lower levels when measurements show this is necessary. 340 | 341 | 342 | # Operation 343 | 344 | Operation is an abstract class, designed for sub-classing. Each subclass represents a specific task. 345 | Main() is the method you override in Operation subclasses to actually perform work. 346 | 347 | ``` 348 | Class ImageDownloader: Operation { 349 | let photoRecord: PhotoRecord 350 | init (_ photoRecord: PhotoRecord) { 351 | self.photoRecord = photoRecord 352 | } 353 | override func main() { 354 | guard let imageData = try? Data(contentsOf: photoRecord.url) else { return } 355 | if !imageData.isEmpty { 356 | photoRecord.image = UIImage(data: imageData) 357 | } 358 | } 359 | } 360 | ``` 361 | 362 | # OperationQueue 363 | 364 | A queue that regulates the execution of operations 365 | An operation queue executes its queued Operation objects based on they priority and readiness. After being added to an operation queue, an operation remains in its queue until it reports that it is finished with its task;OperationQueue is particularly powerful because it lets you control precisely how many simultaneous operations can run and what quality of service you need, while also letting you schedule work using closures. You can even ask the operation queue to wait until all its operations are finished, which makes scheduling easier. 366 | 367 | ``` 368 | let queue = OperationQueue() 369 | for image in images { 370 | queue.addOperation { 371 | self.process(image) 372 | } 373 | } 374 | queue.waitUntiAllOperationsAreFinished() 375 | ``` 376 | 377 | You can add as many operations as you want, but they don’t all get executed at the same time. Instead, OperationQueue limits the number of operations based on system conditions - if it’s a more powerful device that isn’t doing much right now, you’ll get more operations than a less powerful device or a device that’s busy with other work. 378 | 379 | # GCD - Grand Center Dispatch 380 | 381 | Is a low-level API for managing concurrent operations 382 | DispatchQueue - 383 | - Global Queue: Using to perform non-UI work in the background 384 | - Main Queue: Using to update the UI after completing work in a task on a concurrent queue 385 | 386 | List of priority: 387 | - .userInteractive 388 | - .userInitiated 389 | - .default 390 | - .utility 391 | - .background 392 | - .unspecified 393 | 394 | ``` 395 | DispatchQueue.global(cos: .background).async { 396 | // Call your background task 397 | DispatchQueue.main.async { 398 | // UI updates here for task complete. 399 | } 400 | } 401 | ``` 402 | 403 | # What does a DispatchGroup do? 404 | 405 | Let’s say you’ve got several long running tasks to perform. After all of them have finished you’d like to run some further logic. You could run each task in a sequential fashion, but that isn’t so efficient - you’d really like the former tasks to run concurrently. DispatchGroup enables you to do exactly this. 406 | 407 | Ex: You need to run two distinct network calls. Only after they’ve both returned do you have the necessary data to parse the responses. 408 | An animation is running, parallel to a long database call. Once both of those have finished, you’d like to hide a loading spinner. 409 | 410 | 411 | # Codable & Decodable in Swift 412 | 413 | Make your data types encodable and decodable for compatibility with external representations such as JSON. 414 | Codadle protocol is new protocol introduced by Apple in Swift 4 can provide Encodable and Decodable built-in feature. It will make JSON parsing easier. 415 | 416 | ``` 417 | Struct User: Codable { 418 | var userId: Int 419 | var id: Int 420 | var title: String 421 | var completed: Bool 422 | } 423 | do { 424 | let decoder = JSONDecoder() 425 | let model = try decoder.decode([User].self, from: dataResponse) 426 | print(model) 427 | } catch let parsingError { 428 | print(“Error”, parsingError) 429 | } 430 | ``` 431 | 432 | # Codable for complex JSON 433 | 434 | ``` 435 | Let jsonDataString = “” { 436 | “status”: “success”, 437 | “statusCode”: 123, 438 | “document”: { 439 | “count”: 1, 440 | “profiles”: [{ 441 | “name”: “Luísa”, 442 | “email”: “luisa@gmail.com” 443 | }] 444 | } 445 | }“”.data(using: .utf8)! 446 | 447 | struct Response: Codable { 448 | let status: String? let statusCode: Int? let document: Document? 449 | }struct Document: Codable { 450 | let count: Int? let profiles: [Profiles]?} 451 | 452 | struct Profiles: Codable { 453 | let name: String? 454 | let email: String? 455 | } 456 | do { 457 | let response = try JSONDecoder().decode(Response.self, from: jsonData) print(response) 458 | } catch { 459 | print(error) 460 | } 461 | ``` 462 | 463 | # Any vs AnyObject 464 | 465 | Any can represent an instance of any type at all including function type and optional type; 466 | AnyObject can represent an instance of any class type. 467 | 468 | Ex: 469 | ``` 470 | Var anyArray: [Any] = [1,2, “Hello”, true] 471 | Var myPerson: AnyObject = Person() 472 | ``` 473 | 474 | 475 | # Access Specifiers in Swift 476 | 477 | 478 | Open and Public: can be accessed from they module’s entities and any module’s entities that imports the defining module; 479 | 480 | Public: classes and class members can only be subclassed and override within the defining module (target).Open: classes and class members can be subclassed and override both within and outside the defining module (target).Internal: can only be accessed from they module’s entities. It is the default access level. 481 | 482 | Fileprivate and Private: can only be accessed in a limited scope where you define them.Fileprivate: restrict the use of entity in its defining source file. 483 | Private: restricts the use of entity to its enclosing declaration. 484 | 485 | 486 | # Generics 487 | 488 | Generic code enables you to write flexible, reusable functions and types that can work with any type; 489 | For example, swift’s array and dictionary types are both generic collections. You can create an array that holds Int values, or an array that holds String values, or indeed an array for any other type that can be created in Swift. Similarly, you can create a dictionary to store values of any specified type. 490 | 491 | Ex: 492 | ``` 493 | Func doNothing(x: T) { 494 | return x 495 | } 496 | doNothing(x: “Hello”) // Hello 497 | doNothing(x: 123) // 123 498 | doNothing(x: true) // true 499 | ``` 500 | 501 | # Core Data Stack 502 | 503 | Managed Object - is NSManagedObject Class or subclass and represent a single data record based on model; 504 | 505 | Managed Object Context - is like workspace which contains many managed objects. App can have many managed objected. With MOC we perform CRUD operation; 506 | 507 | Managed Object Model - describes data structure and relationships, we define it using the data model editor in Xcode. And this model gets saved as .xcdatamodelId; 508 | 509 | Persistent Store coordinator: mediate between the persistent store and data model and context; 510 | 511 | ManagedObjectContext is in persistent store. Persistent store represent the actual file on disk with your data. You can have multiple persistent store. To manage the case where are multiple persistent store there is persistent store coordinator; 512 | 513 | CoreData offers three native file types for a persistent store: binary, XML, and SQLite; 514 | 515 | Data Model - create data model with entity and attributes. Entity is like class or table and attributes are like fields of that class or table. 516 | 517 | 518 | # Why to use NSFetchedResultsController? 519 | 520 | A fetched results controller manages the results of a fetch request. It notifies its delegate about any changes that affect the results of that fetch request. It even offers the ability to use an in-memory cache to improve perfomance; 521 | 522 | Even though the NSFetchResultsController class was designed with table views in mind, it also works great with collection views. 523 | 524 | 525 | # POP: Protocol Oriented Programming 526 | 527 | Drawbacks of objected oriented programming. 528 | - It has only one inheritance. If we have every complicated hierarchy of inheritance, the bottom class may have a lot of unnecessary state to hold. 529 | - it uses class which is a reference type. Reference type may cause code unsafe. Processing collection of reference types while they are being modified. 530 | 531 | While protocol oriented programming in Swift: 532 | - It can conform multiple protocols; 533 | - It can be used by not only class, but also structures and enumerations; 534 | - it has protocol extension which gives us common functionality to all types that conforms to a protocol; 535 | - It prefers to use a value type instead of reference type 536 | 537 | # KVC & KVO 538 | 539 | KVC: Adds stands for key-value coding. It’s a mechanism by which an object’s properties can be accessed using string’s at runtime rather than having to statically know the property names at development time. 540 | 541 | KVO: stands for key-value observing and allows a controller or class to observe changes to a property value. In KVO, an object can ask to be notified of any changes to a specific property, whenever that property changes value, the observer is automatically notified. You can use KVO in Swift, but only for dynamic properties of NSObject subclass. 542 | 543 | Ex: KVC: `let robertLastName = self.value(forKey: “lastName”)` 544 | 545 | KVO: 546 | ``` 547 | @objc class Person: NSObject { 548 | @objc dynamic var name = “Taylor Swift” 549 | } 550 | 551 | Let taylor = Person() 552 | 553 | Taylor.observe(\Person.name, options: .new) { person, change in 554 | print(“I’m now called \(person.name)”) 555 | } 556 | ``` 557 | 558 | # Push Notification 559 | 560 | DEVICE -> APP -> SERVER -> APNS 561 | 562 | 1. Register for push notification 563 | 2. Send request to APNS 564 | 3. Reply with Device Token 565 | 4. Device sends token to App 566 | 5. Sends Device token to Server 567 | 6. Server ends notification payload with device token to APNS 568 | 7. Sends Notification to Device 569 | 570 | So the checklist of APNS: 571 | - Create appId allowed with push notification 572 | - Create SSL certificate with valid certificate and app ID 573 | - Create Provisioning profile with same certificate and make sure to add device in case of sandboxing (development provisioning) 574 | 575 | # Content Hugging & Compression resistance 576 | 577 | Hugging - content doesn’t want to grow 578 | Compession Resistance - Content doesn’t want to shrink 579 | 580 | # Singleton 581 | 582 | The singleton pattern is a very useful pattern. There are times that you want to make sure only one instance of a class is instantiated and that your application only uses that instance. That’s the primary and only goal of the singleton pattern. Singleton objects can be access globally 583 | 584 | If you’ve worked with Apple’s frameworks, then chances are that you’ve already used the Singleton pattern. 585 | 586 | Ex: 587 | ``` 588 | Let sharedURLSession = URLSession.shared 589 | Let standardUserDefaults = UserDefaults.Standard 590 | 591 | Class LocationManager { 592 | static let shared = LocationManager() 593 | var locationGranted: Bool? // Initializer access level change now private init() {} func requestForLocation() { 594 | locationGranted = true 595 | print(“Location granted”) 596 | } 597 | }// Access class function in a single line 598 | LocationManager.shared.requestForLocation() 599 | ``` 600 | 601 | # Why Singleton is bad? 602 | 603 | Singleton pattern has a side effect that’s often the true reason for adopting the singleton pattern, global access. Many developers use the singleton pattern to have easy access to the singleton object from anywhere in their project. While this is convenient, that convenience comes at a price. 604 | 605 | Drawbacks of using Singleton: 606 | - Sacrifing transparency for convenience: By using singletons, you almost always sacrifice transparency for convenience. Since singletons are so convenient and easy to access - using them extensively usually leads to very hard to maintain “Spaghetti code” that doesn’t have clear separations between objects. 607 | - They are global mutable shared state: Their state is automatically shared across the entire app, and bugs can often start occurring when that state changes unexpectedly. 608 | - Managing their lifecycle can be tricky: Since singletons are alive during the entire lifespan of an application, managing them chan be really hard, and they usually have to rely on optionals to keep track of values. 609 | 610 | # Dependency Injection 611 | 612 | The cure to solve singleton disease is dependency injection. While a key advantage of the singleton pattern is convenience, the most important advantage of dependency injection is transparency. 613 | If an object requires a valid user object to do its job, then that user object should be injected as a dependency. 614 | 615 | Ex: 616 | ``` 617 | Class User { 618 | var firstName = “” 619 | var lastName = “” 620 | } 621 | 622 | Class NetworkController { 623 | let user: User 624 | init (user: user) { 625 | self.user = user 626 | } 627 | } 628 | ``` 629 | 630 | # What is ABI? 631 | 632 | ABIs are important when it comes to applications that use external libraries. If a program is built to use a particular library and that library is later updated, you don’t want to have to re-compile that application (and from the end-user’s standpoint, you may not have the source). If the updated library uses the same ABI, then your program will not need to change. 633 | 634 | # What is viewDidLayoutSubviews? 635 | 636 | viewDidLayoutSubviews is called to notify the view controller that its view has just laid out its subviews. 637 | In another word, viewDidLayoutSubviews is called every time the view is updated, rotated or changed or its bounds change. The keyword here is bounds change. 638 | 639 | # What is loadView? 640 | 641 | Only override this method if you create your views manually (i.e NOT storyboard). loadView() creates and instantiates the UIView. 642 | 643 | viewDidLoad() is called when the view has finished loading, while loadView() is called when the view starts loading. 644 | 645 | # NSArray vs Array 646 | 647 | Array is a struct, therefore it is a value type in Swift. NSArray is an immutable Objective C class, therefore it is a reference type in Swift and it is bridged to Array. NSMutableArray is the mutable subclass of NSArray. 648 | 649 | # NSDictionary vs Dictionary 650 | 651 | Dictionary is a native Swift struct. NSDictionary is a Cocoa class. They are bridged to on another (within the usual limits), as the docs explain very clearly and fully. 652 | 653 | # Computed and Stored Properties 654 | 655 | - Stored Property 656 | 1. Store constant and variable values as instance 657 | 2. Provided by classes and structures 658 | 659 | - Computed Property 660 | 1. Calculate a value rather than storing the value, ‘let’ declarations cannot be computed properties 661 | 2. Provided by classes, enumerations, structures and extensions 662 | 663 | 664 | # Property Observer for computed properties 665 | 666 | Each and every time when property values are set property observers called; 667 | Before Storing the value - willSet 668 | After Storing the new value - didSet 669 | When a property is set in an initializer willSet and didSet observers cannot be called. 670 | 671 | Ex: 672 | ``` 673 | class PropertyObserverEx { 674 | var counter: Int = 0 { 675 | willSet(newTotal) { 676 | print(“Total Counter is :\(newTotal)”) 677 | } 678 | 679 | didSet { 680 | if counter > oldValue { 681 | print(“Newly added counter \(counter - oldValue)”) 682 | } 683 | } 684 | } 685 | } 686 | 687 | let newCounter = PropertyObserverEx() 688 | newCounter.counter = 10 689 | newCounter.counter = 60 690 | 691 | Response -
Total Counter is: 10 692 | Newly Added Counter 10 693 | Total Counter is: 60 694 | Newly Added Counter 50 695 | ``` 696 | 697 | # Can we use computed or stored properties in extension? 698 | 699 | We can use Computed properties with extension but stored properties 700 | 701 | # Can we write extension for struct/enum/protocol? 702 | 703 | Yes, we can write extension for all of them 704 | 705 | # Is Optional an Enum? 706 | 707 | Yes, basically, an Optional is an Enum with 2 cases and on of the cases has an associated value attached to it. 708 | - .Some(Wrapped) 709 | - .None 710 | 711 | # Sync vs Async: deadlock situation 712 | 713 | When you invoke something synchronously, it means that the thread that initiated that operation will wait for the task to finish before continuing. Asynchronous means that it will not wait. 714 | 715 | The goal is to free the main thread so that it can continue to respond to the user interface (rather than freezing) 716 | 717 | There are two part in that: 718 | - Grab a background queue (ex: CGD) 719 | - Dispatch your task to that queue synchronously / asynchronously 720 | 721 | 722 | Sync Async: Deadlock Situation
 723 | ```swift 724 | let queue = DispatchQueue(label: “label”) 725 | queue.async { 726 | queue.sync { 727 | // outer block is waiting for this inner block to complete, 728 | // inner block won’t start before outer block finishes 729 | // => deadlock 730 | } 731 | // this will never be reached 732 | } 733 | ``` 734 | 735 | ```swift 736 | queue.sync { 737 | queue.sync { 738 | // outer block is waiting for this inner block to complete, 739 | // inner block won’t start before outer block finishes 740 | } 741 | } 742 | ``` 743 | 744 | Sync Async: No Deadlock 745 | 746 | ```swift 747 | queue.sync { 748 | queue.async { 749 | // outer block is waiting for this inner block to complete, 750 | // inner block won’t start before outer block finishes 751 | // => deadlock 752 | } 753 | // this will never be reached 754 | } 755 | ``` 756 | 757 | ```swift 758 | queue.async { 759 | queue.async { 760 | // outer block is waiting for this inner block to complete, 761 | // inner block won’t start before outer block finishes 762 | // => deadlock 763 | } 764 | // this will never be reached 765 | } 766 | ``` 767 | 768 | # Example of Strong & Weak 769 | 770 | - Use of Weak: 771 | 772 | 1. Delegates 773 | 2. Outlets 774 | 3. Subviews 775 | 4. Controls 776 | 777 | - Use of Strong: 778 | 779 | 1. Remaining everywhere which is not included in Weak 780 | 781 | # Semaphore 782 | 783 | Only one thread can access one resource at a time. Semaphores gives us the ability to control access to a shared resource by multiple threads. 784 | 785 | let semaphore = DispatchSemaphore(value: 1) // only one thread can access this resource at a time 786 | 787 | - Call wait() each time before using the shared resource. We are basically asking the semaphore if the shared resource is available or not. If not, we will wait. 788 | - Call signal() each time after using the shared resource. We are basically signaling the semaphore that we are done interacting with the shared resource. 789 | 790 | Ex: Downloading 15 songs from a url 791 | 792 | ```Swift 793 | let queue = DispatchQueue(label: “com.gcd.myQueue”, attributes: .concurrent) 794 | let semaphore = DispatchSemaphore(value: 3) // Only 3 songs can be downloaded at a time 795 | 796 | for i in 0 ..> 15 { 797 | queue.async { 798 | let songNumber = i + 1 799 | semaphore.wait() 800 | print(“Downloading song”, songNumber) 801 | sleep(2) // Download take ~2 sec each 802 | print(“Downloaded song”, songNumber) 803 | 804 | } 805 | } 806 | ``` 807 | -------------------------------------------------------------------------------- /version_PT-Br.md: -------------------------------------------------------------------------------- 1 | ## Questões 2 | 3 | ## Questões 4 | 5 | 1. [Copy vs Readonly](#copy-vs-readonly) 6 | 2. [Copy vs Strong](#copy-vs-strong) 7 | 3. [Weak vs Strong](#weak-vs-strong) 8 | 4. [Weak vs Unowned](#weak-vs-unowned) 9 | 5. [Gist of all the attributes](#gist-of-all-the-attributes) 10 | 6. [ARC & Retain Cycle](#arc-and-retain-cycle) 11 | 7. [Optional in Swift](#optional-in-swift) 12 | 8. [What is ??](#what-is-??) 13 | 9. [Optional Chaining](#optional-chaining) 14 | 10. [Optional Binding](#optional-binding) 15 | 11. [Delegate vs Notification](#delegate-vs-notification) 16 | 12. [Class vs Struct](#class-vs-struct) 17 | 13. [Enum](#enum) 18 | 14. [Guard](#guard) 19 | 15. [Defer](#defer) 20 | 16. [MVVM](#mvvm) 21 | 17. [Dynamic Dispatch](#dynamic-dispatch) 22 | 18. [Static Dispatch](#static-dispatch) 23 | 19. [Closure](#closure) 24 | 20. [@escaping & nonescaping](#@escaping-and-nonescaping) 25 | 21. [What is "lazy"?](#what-is-lazy?) 26 | 22. [Unowned self & weak self](#unowned-self-&-weak-self) 27 | 23. [Process & Threads](#process-&-threads) 28 | 24. [Operation & GCD](#operation-&-GCD) 29 | 25. [Operation](#operation) 30 | 26. [OperationQueue](#operationQueue) 31 | 27. [GCD - Grand Center Dispatch](#GCD-grand-center-dispatch) 32 | 28. [What does a Dispatchgroup do?](#what-does-a-dispatchgroup-do?) 33 | 29. [Codable & Decodable in Swift](#codable-&-decodable-in-swift) 34 | 30. [Codable for complex JSON](#codable-for-complex-JSON) 35 | 31. [Any vs AnyObject](#any-vs-anyobject) 36 | 32. [Access Specifiers in Swift](#access-specifiers-in-swift) 37 | 33. [Generics](#generics) 38 | 34. [CoreData Stack](#coredata-stack) 39 | 35. [Why use NSFetchedResultsController?](#why-use-nsfetcherresultscontroller?) 40 | 36. [POP: Protocol Oriented Programming](#pop-protocol-oriented-programming) 41 | 37. [KVC & KVO](#kvc-&-kvo) 42 | 38. [Push Notification](#push-notification) 43 | 39. [Content Hugging & Compression resistance](#content-hugging-&-compression-resistance) 44 | 40. [Singleton](#singleton) 45 | 41. [Why Singleton is bad?](#why-singleton-is-bad?) 46 | 42. [Dependency Injection](#dependency-injection) 47 | 43. [What is ABI?](#what-is-ABI?) 48 | 44. [What is viewDidLayoutSubviews?](#what-is-viewDidLayoutSubviews?) 49 | 45. [What is loadView?](#what-is-loadView?) 50 | 46. [NSArray vs Array](#nsarray-vs-array) 51 | 47. [NSDictionary vs Dictionary](#nsdictionary-vs-dictionary) 52 | 48. [Computted and stored properties](#computed-and-stored-properties) 53 | 49. [Property Observer for computed properties](#property-observer-for-computed-properties) 54 | 50. [Can we use computed or stored properties in extension?](#can-we-use-computed-or-stored-properties-in-extension?) 55 | 51. [Can we write extension for struct/enum/protocol?](#can-we-write-extension-for-struct-enum-protocol?) 56 | 52. [Is Optional an Enum?](#is-optional-an-enum?) 57 | 53. [Sync vs Async: deadlock situation](#sync-vs-async-deadlock-situation) 58 | 54. [Example of Strong & Weak](#example-of-strong-weak) 59 | 55. [Semaphore](#semaphore) 60 | 61 | ## Copy vs Readonly 62 | 63 | - Copy 64 | 65 | Ele cria uma nova cópia de um objeto e, uma vez que o novo objeto é criado, a contagem de retenção será 1; 66 | Use copy quando precisar do valor de um objeto como está e não quiser que outro objeto atualize o valor do seu objeto; 67 | Criar setters e getters 68 | 69 | - Readonly 70 | 71 | Indica que a propriedade é somente leitura; 72 | Só gera getter, nenhum setter será gerado; 73 | Se você tentar alterar o valor, receberá um erro do compilador 74 | 75 | # Copy vs Strong 76 | 77 | - Copy 78 | 79 | Ele cria uma nova cópia de um objeto e, uma vez que o novo objeto é criado, a contagem de retenção será 1; 80 | Use copy quando precisar do valor de um objeto como está e não quiser que outro objeto atualize o valor do seu objeto; 81 | Criar setters e getters 82 | 83 | - Strong 84 | 85 | Aumenta a contagem de retenção em 1; 86 | Cria setters e getters; 87 | O objeto será mais mutável 88 | 89 | # Weak vs Strong 90 | 91 | - Weak 92 | 93 | Não aumenta a contagem de retenção 94 | Não proteja o objeto de ser desalocado pelo ARC 95 | Na desalocação, objetos fracos serão definidos como nil, e todas as referências fracas são opcionais 96 | Cria setters e getters 97 | 98 | - Strong 99 | 100 | Aumenta a contagem de retenção em 1 101 | Protege o objeto de ser desalocado pelo ARC 102 | Cria setters e getters 103 | O objeto será mutável 104 | 105 | # Weak vs Unonwned 106 | 107 | - Weak 108 | 109 | Não aumenta a contagem de retenção 110 | Não proteja o objeto de ser desalocado pelo ARC 111 | Na desalocação, objetos fracos serão definidos como nil, e todas as referências fracas são opcionais 112 | Cria setters e getters 113 | 114 | - Unowned 115 | 116 | Não aumenta a contagem de retenção 117 | Na desalocação, objetos fracos serão definidos como nil, e é por isso que todas as referências fracas são opcionais 118 | Cria setters e getters 119 | 120 | Nota: É importante que você use apenas referências sem dono quando você realmente sabe que o objeto nunca será nulo depois de definido 121 | 122 | # Gist of all the attributes 123 | 124 | - Strong: Adiciona referência para manter o objeto vivo; 125 | - Weak: não adiciona referência para que o objeto possa se tornar nil por arco; 126 | - Assign: atribuição normal, sem referência, usado principalmente para tipos de dados primitivos; 127 | - Copy: faz nova cópia de um objeto, a cópia será imutável; 128 | - Nonatomic: não torna objetos thread-safe, aumenta o desempenho; 129 | - Readwrite: Cria os getters e setters; 130 | - Readonly: Cria apenas getters; 131 | 132 | # ARC & Retain Cycle 133 | 134 | ARC é uma maneira que a Apple lida com o gerenciamento de memória para nós. Para cada objeto, ele mantém uma contagem de quantas referências fortes estão apontando para aquele objeto. E enquanto houver uma referência forte para um objeto, o objeto permanecerá na memória. 135 | 136 | # Optional in Swift 137 | 138 | Permite escrever código flexível e mais seguro; 139 | Ponto de interrogação significa que pode ser nulo ou algum valor 140 | 141 | # What is ?? 142 | 143 | Para fornecer o valor padrão para uma variável que pode ser nula 144 | Ele diz ei, se não houver nada lá, use esse valor 145 | É semelhante a “!=nil” 146 | 147 | # Optional Chaining 148 | 149 | O encadeamento opcional é a maneira pela qual tentamos recuperar valores de uma cadeia de valores opcionais 150 | Permite que você falhe normalmente ao tentar acessar uma propriedade de um objeto que é nil 151 | 152 | ex: 153 | ```swift 154 | let album = albumReleased(year: 2006)?.uppercased() 155 | ``` 156 | 157 | O encadeamento opcional pode ser tão longo quanto necessário 158 | 159 | # Optional Binding 160 | 161 | Além do desempacotamento forçado, a vinculação opcional é uma maneira simples e recomendada de desempacotar um opcional. Você usa a ligação opcional para verificar se o opcional contém um valor ou não. Se contiver um valor, desembrulhe-o e coloque-o em uma constante ou variável temporária; Com a vinculação opcional, você está criando uma nova referência para o que acabou de desempacotar e, geralmente, essa é uma referência forte. 162 | 163 | ex: 164 | 165 | ``` swift 166 | if let constantName = someOptional { 167 | statements 168 | } 169 | ``` 170 | 171 | # Delegate vs Notification 172 | 173 | Delegates: usado em comunicação um para um 174 | Notication: usado em comunicação um para vários 175 | 176 | # Class vs Struct 177 | 178 | Class: tipo de referência, significa que qualquer alteração em uma referência afetará outras referências também; 179 | Struct: tipo de valor, significa que as alterações em um valor não afetarão os outros 180 | 181 | ex: 182 | 183 | ```swift 184 | class SomeClass { 185 | var name: 186 | init(name: String) { 187 | self.name = name 188 | } 189 | } 190 | 191 | var aClass = SomeClass(name: “”Bob) 192 | var bClass = aClass // aClass and bClass now reference the same instance! 193 | bClass.name = “Sue” 194 | print(aClass.name) //“Sue” print(bClass.name) //“Sue” 195 | ``` 196 | 197 | ``` 198 | struct SomeStruct { 199 | var name: string 200 | init(name: String) { 201 | self.name = name 202 | } 203 | } 204 | 205 | var aStruct = SomeStruct(name: “Bob”) 206 | var bStruct = aStruct // aStruct and bStruct now reference the same instance 207 | bStruct.name = “Sue” 208 | print(aStruct.name) // “Bob” 209 | print(bStruct.name) // “Sue” 210 | ``` 211 | 212 | # Enum 213 | 214 | Grupo de valores relacionados 215 | 216 | Raw = valores definidos no Enum 217 | 218 | ```swift 219 | Enum Directions: Int { 220 | case up = 1 221 | case down 222 | case left 223 | case right 224 | } 225 | ``` 226 | 227 | Associated = Passagem de parametrôs pelo o Enum 228 | 229 | ```swift 230 | enum ExampleAssociation { 231 | case name(String) 232 | } 233 | ``` 234 | 235 | # Guard 236 | 237 | Fornece saída antecipada e não permite nenhum código se a condição não for verdadeira 238 | 239 | # DEFER 240 | 241 | A instrução Defer é usada para executar um trecho de código exatamente antes da execução sair do escopo recente; 242 | A instrução defer é executada após o retorno! 243 | A instrução defer é executada independentemente de como você sai 244 | 245 | ``` swift 246 | func deferEx() { 247 | print(“”beginning) 248 | var value: String? 249 | defer { 250 | if let v = value { 251 | print(“Ending execution of \(v)”) 252 | } 253 | } 254 | value = “defer function” 255 | print(“Ending”) 256 | } 257 | ``` 258 | 259 | # MVVM 260 | 261 | No MVC - View envia eventos para o Controller, o controller então envia solicitação para model para dados e executa lógica de negócios se necessário, model notifica controller em caso de qualquer mudança de dados e controller envia dados para View to presentMVC - Resultou em massivo view controller que eram difíceis de administrar; 262 | No MVVM - View Controller e View são combinados para se tornarem “View” 263 | E mais uma camada é adicionada chamada “ViewModel”, essa nova camada se comunicará com o modelo e processará os dados e executará alguma lógica de negócios se necessário e enviará os dados finais para o ViewController que só é necessário para atualizar a interface do usuário. 264 | 265 | # Dynamic Dispatch 266 | 267 | O despacho dinâmico é o processo de selecionar qual implementação de uma operação polimórfica (método ou função) chamar em tempo de execução; 268 | Por exemplo, se uma subclasse substituir um método de sua superclasse, o despacho dinâmico descobre qual implementação do método precisa ser invocada, a da subclasse ou a da classe pai; 269 | Ao aplicar o modificador de declaração “dynamic” a um membro de uma classe, você informa ao compilador que o dispatch dinâmico deve ser usado para acessar esse membro; 270 | 271 | O modificador de declaração “Dinâmico” só pode ser usado para membros de uma classe. Estruturas e enumerações não suportam herança, o que significa que o tempo de execução não precisa descobrir qual implementação precisa usar; O Swift oferece 2 maneiras de obter dinamismo: Despacho de Tabela e Despacho de Mensagem; 272 | 273 | Table Dispatch: Com este método, uma classe é associada a uma chamada tabela virtual que compreende uma matriz de ponteiros de função para a implementação real correspondente a essa classe. Observe que a tabela é construída em tempo de compilação. Assim, existem apenas duas instruções adicionais (ler e pular) em comparação com o despacho estático. Portanto, o despacho deve ser teoricamente bem rápido. 274 | 275 | Message Dispatch: É o objetivo-c que fornece esse mecanismo. Toda vez que um método Objective-C é chamado, a invocação é passada para “objc_msgSend”, que trata das pesquisas. Ao contrário do despacho de tabela, o dicionário de passagem de mensagens pode ser modificado em tempo de execução, permitindo-nos ajustar os comportamentos do programa durante a execução. 276 | 277 | # Static Dispatch 278 | 279 | Quando algo é despachado estaticamente, estamos lidando com o cenário oposto. Com o despacho estático, o compilador de fato sabe qual propriedade ou método está sendo chamado em tempo de execução, o que aumenta o desempenho. Você pode obter despacho estático marcando uma classe base com a palavra-chave “final”. Isso permite que o compilador saiba que esta classe não pode ter nenhuma subclasse e que o método/propriedade a que você está se referindo é sua única implementação. 280 | Outro exemplo é a palavra-chave “static“ para definir métodos de tipo de propriedades. Esta palavra-chave é realmente a abreviação de “classe final”. Isso permite que o compilador saiba que esta é a implementação final desse método e não será substituída. Portanto, ele será despachado estaticamente. 281 | 282 | Ao definir um método de tipo você pode marcá-lo com “classe” ou “estático”, mas o que você escolhe determina como ele será despachado. 283 | 284 | # Closure 285 | 286 | Closures são blocos autocontidos de funcionalidade que podem ser passados e usados em seu código; 287 | Os fechamentos são funções sem cabeça. Closures são funções sem a palavra-chave func e o nome da função. Eles também são conhecidos como funções anônimas. 288 | 289 | Syntax - 290 | ```swift 291 | { (parameter) -> return type in 292 | statement 293 | } 294 | ``` 295 | 296 | ex: 297 | ```swift 298 | var sayHello = {(name: String) -> String in 299 | return “Hello \(name)” 300 | } 301 | sayHello(“Richa”) 302 | 303 | Passing inside a function syntax - 304 | 305 | Func sayHello(name: string, closure(String) -> void) { 306 | closure(“Hello \(name)”) 307 | } 308 | sayHello(name: “Richa”) { name in 309 | print(name) 310 | } 311 | ``` 312 | 313 | # @escaping & @nonescaping 314 | 315 | Se uma closure é passada como argumento para uma função e é invocada após o retorno da função, a closure está escapando; 316 | É principalmente útil/necessário para chamadas de rede, você deseja que seu manipulador de conclusão viva após a instrução de retorno; 317 | Existem muitos benefícios diferentes de fazer sem escape, ele cuidará da alocação de memória para a closure. 318 | 319 | # What is “lazy”? 320 | 321 | Uma propriedade armazenada lenta é uma propriedade cujo valor inicial não é calculado até a primeira vez que é usado. Você indica uma propriedade armazenada lazy escrevendo o modificador “lazy” antes de sua declaração. Se o seu aplicativo for complexo, os problemas de memória serão um dos principais desafios. Então, o desenvolvedor deve estar realmente escrevendo um código otimizado que considere alocação de memória em primeiro lugar. O desenvolvedor precisa evitar fazer um trabalho caro, a menos que seja realmente necessário. Podemos conseguir isso usando lazy; 322 | 323 | Você não pode usar lazy com let; 324 | Você não pode usá-lo com propriedades computadas. Pois, uma propriedade computada retorna o valor toda vez que tentamos acessá-la após executar o código dentro do bloco de computação; 325 | Você pode usar lazy apenas com membros de struct e class; 326 | As variáveis lazy não são inicializadas automaticamente e, portanto, não são seguras para threads. 327 | 328 | # [unowned self] & [weak self] 329 | 330 | A única vez em que você realmente deseja usar [unowned self] ou [weak self] é quando você pode criar um ciclo de referência forte. Um ciclo de referência forte é quando há um loop de propriedade onde os objetos acabam se possuindo (talvez por meio de terceiros) e, portanto, eles nunca serão desalocados porque ambos estão garantindo que um ao outro permaneça; 331 | 332 | No caso de uma closure, você só precisa perceber que qualquer variável que é referenciada dentro dele, fica “propriedade” do encerramento. Enquanto o fechamento estiver por perto, esses objetos estarão garantidos. A única maneira de parar essa propriedade é usar o [unowned self] ou [weak self]. Portanto, se uma classe possui uma closure e essa closure captura uma referência forte a essa classe, você tem um ciclo de referência forte entre a closure e a classe. Isso também inclui se a classe possui algo que possui a closure; 333 | 334 | Se self pudesse ser nulo na closure, use [weak self]; 335 | Se self nunca será nulo na closure, use [unowned self] 336 | 337 | # Process & Threads 338 | 339 | Um processo pode conter vários encadeamentos de execução e cada encadeamento pode executar várias tarefas, uma de cada vez; 340 | Task: Um trabalho simples e único que precisa ser feito; 341 | Thread: Um mecanismo fornecido pelo sistema operacional que permite que vários conjuntos de instruções operem ao mesmo tempo em um único aplicativo; 342 | Process: Um pedaço de código executável, que pode ser composto de vários threads 343 | 344 | # Operation & GCD 345 | 346 | Ambos são usados para fazer qualquer tipo de operação multithread no iOS 347 | GCD: É uma maneira leve de representar unidades de trabalho que serão executadas simultaneamente. Você não agenda essas unidades de trabalho; O sistema cuida do agendamento para você. Adicionar dependência entre blocos pode ser uma dor de cabeça. Cancelar ou suspender um bloco cria um trabalho extra para você como desenvolvedor! 348 | Operation: Adiciona um pouco de sobrecarga extra em comparação com o GCD, mas você pode adicionar dependência entre várias operações e reutilizá-las, cancelá-las ou suspendê-las. 349 | 350 | Operation e OperationQueue são construídos sobre o GCD. Como regra geral, a apple recomenda usar a abstração de nível mais alto e, em seguida, descer para níveis mais baixos quando as medições mostrarem que isso é necessário. 351 | 352 | # Operation 353 | 354 | Operation é uma classe abstrata, projetada para subclasses. Cada subclasse representa uma tarefa específica. 355 | Main() é o método que você substitui nas subclasses de Operação para realmente realizar o trabalho. 356 | 357 | ```swift 358 | class ImageDownloader: Operation { 359 | let photoRecord: PhotoRecord 360 | init (_ photoRecord: PhotoRecord) { 361 | self.photoRecord = photoRecord 362 | } 363 | override func main() { 364 | guard let imageData = try? Data(contentsOf: photoRecord.url) else { return } 365 | if !imageData.isEmpty { 366 | photoRecord.image = UIImage(data: imageData) 367 | } 368 | } 369 | } 370 | ``` 371 | 372 | # OperationQueue 373 | 374 | Uma fila que regula a execução das operações; 375 | Uma fila de operação executa seus objetos de operação enfileirados com base em sua prioridade e prontidão. Depois de ser adicionada a uma fila de operações, uma operação permanece em sua fila até relatar que terminou com sua tarefa; 376 | O OperationQueue é particularmente poderoso porque permite controlar com precisão quantas operações simultâneas podem ser executadas e qual qualidade de serviço você precisa, além de permitir que você agende o trabalho usando encerramentos. Você pode até pedir à fila de operações que espere até que todas as suas operações sejam concluídas, o que facilita o agendamento. 377 | 378 | ```swift 379 | let queue = OperationQueue() 380 | for image in images { 381 | queue.addOperation { 382 | self.process(image) 383 | } 384 | } 385 | queue.waitUntiAllOperationsAreFinished() 386 | ``` 387 | 388 | Você pode adicionar quantas operações quiser, mas nem todas são executadas ao mesmo tempo. Em vez disso, o OperationQueue limita o número de operações com base nas condições do sistema - se for um dispositivo mais poderoso que não está fazendo muito agora, você obterá mais operações do que um dispositivo menos poderoso ou um dispositivo ocupado com outro trabalho. 389 | 390 | # GCD - Grand Center Dispatch 391 | 392 | É uma API de baixo nível para gerenciar operações simultâneas 393 | DispatchQueue - 394 | - Global Queue: usado para executar trabalho sem interface do usuário em segundo plano 395 | - Main Queue: usado para atualizar a interface do usuário após concluir o trabalho em uma tarefa em uma fila simultânea 396 | 397 | List of priority: 398 | - .userInteractive 399 | - .userInitiated 400 | - .default 401 | - .utility 402 | - .background 403 | - .unspecified 404 | 405 | ```swift 406 | DispatchQueue.global(cos: .background).async { 407 | // Call your background task 408 | DispatchQueue.main.async { 409 | // UI updates here for task complete. 410 | } 411 | } 412 | ``` 413 | 414 | # What does a DispatchGroupd do? 415 | 416 | Digamos que você tenha várias tarefas de longa duração para executar. Depois que todos eles terminarem, você gostaria de executar mais alguma lógica. Você pode executar cada tarefa de forma sequencial, mas isso não é tão eficiente - você realmente gostaria que as tarefas anteriores fossem executadas simultaneamente. DispatchGroup permite que você faça exatamente isso. 417 | 418 | Ex: 419 | Você precisa executar duas chamadas de rede distintas. Somente depois que ambos retornarem, você terá os dados necessários para analisar as respostas. 420 | Uma animação está em execução, paralela a uma longa chamada de banco de dados. Depois que ambos terminarem, você gostaria de ocultar um spinner de carregamento. 421 | 422 | # Codable & Decodable in Swift 423 | 424 | Torne seus tipos de dados codificáveis e decodificáveis para compatibilidade com representações externas, como JSON. 425 | O protocolo Codadle é o novo protocolo introduzido pela Apple no Swift 4 que pode fornecer o recurso embutido Encodable e Decodable. Isso tornará a análise de JSON mais fácil. 426 | 427 | ```swift 428 | struct User: Codable { 429 | var userId: Int 430 | var id: Int 431 | var title: String 432 | var completed: Bool 433 | } 434 | do { 435 | let decoder = JSONDecoder() 436 | let model = try decoder.decode([User].self, from: dataResponse) 437 | print(model) 438 | } catch let parsingError { 439 | print(“Error”, parsingError) 440 | } 441 | ``` 442 | 443 | # Codable for complex JSON 444 | 445 | ```swift 446 | Let jsonDataString = “” { 447 | “status”: “success”, 448 | “statusCode”: 123, 449 | “document”: { 450 | “count”: 1, 451 | “profiles”: [{ 452 | “name”: “Luísa”, 453 | “email”: “luisa@gmail.com” 454 | }] 455 | } 456 | }“”.data(using: .utf8)! 457 | 458 | struct Response: Codable { 459 | let status: String? let statusCode: Int? let document: Document? 460 | }struct Document: Codable { 461 | let count: Int? let profiles: [Profiles]?} 462 | 463 | struct Profiles: Codable { 464 | let name: String? 465 | let email: String? 466 | } 467 | do { 468 | let response = try JSONDecoder().decode(Response.self, from: jsonData) print(response) 469 | } catch { 470 | print(error) 471 | } 472 | ``` 473 | 474 | # Any vs AnyObject 475 | 476 | Any pode representar uma instância de qualquer tipo, incluindo tipo de função e tipo opcional; 477 | AnyObject pode representar uma instância de qualquer tipo de classe. 478 | 479 | Ex: 480 | 481 | ```swift 482 | var anyArray: [Any] = [1,2, “Hello”, true] 483 | var myPerson: AnyObject = Person() 484 | ``` 485 | 486 | # Access Specifiers in Swift 487 | 488 | Open e Public: pode ser acessado a partir das entidades do módulo e de qualquer entidade do módulo que importe o módulo definidor; 489 | 490 | Public: classes e membros de classe só podem ser subclassificados e substituídos dentro do módulo de definição (destino). 491 | 492 | Open: classes e membros de classe podem ser subclassificados e sobrescrever dentro e fora do módulo de definição (destino). 493 | 494 | Internal: só pode ser acessado a partir das entidades do módulo. É o nível de acesso padrão. 495 | 496 | Fileprivate e Private: só podem ser acessados em um escopo limitado onde você os define. 497 | Fileprivate: restringe o uso da entidade em seu arquivo fonte de definição. 498 | Privado: restringe o uso da entidade à sua declaração anexa. 499 | 500 | # Generics 501 | 502 | O Generic permite escrever funções e tipos flexíveis e reutilizáveis que podem funcionar com qualquer tipo; 503 | Por exemplo, os tipos de array e dicionário do swift são coleções genéricas. Você pode criar um array que contenha valores Int, ou um array que contenha valores `String`, ou mesmo um array para qualquer outro tipo que possa ser criado no Swift. Da mesma forma, você pode criar um dicionário para armazenar valores de qualquer tipo especificado. 504 | 505 | Ex: 506 | ```swift 507 | func doNothing(x: T) { 508 | return x 509 | } 510 | doNothing(x: “Hello”) // Hello 511 | doNothing(x: 123) // 123 512 | doNothing(x: true) // true 513 | ``` 514 | 515 | # CoreData Stack 516 | 517 | Managed Object - é uma classe ou subclasse `NSManagedObject` e representa um único registro de dados baseado no modelo; 518 | 519 | Managed Object Context - é como um espaço de trabalho que contém muitos objetos gerenciados. O aplicativo pode ter muitos objetos gerenciados. Com o MOC realizamos a operação CRUD; 520 | 521 | Managed Object Model - descreve a estrutura de dados e relacionamentos, definimos usando o editor de modelo de dados no Xcode. E este modelo é salvo como `.xcdatamodelId`; 522 | 523 | Persistent Store Coordinator: mediar entre o armazenamento persistente e o modelo e contexto de dados; 524 | 525 | `ManagedObjectContext` está em armazenamento persistente. O armazenamento persistente representa o arquivo real no disco com seus dados. Você pode ter vários armazenamentos persistentes. Para gerenciar o caso em que existem vários armazenamentos persistentes, existe um coordenador de armazenamento persistente; 526 | 527 | CoreData oferece três tipos de arquivos nativos para um armazenamento persistente: binário, XML e SQLite; 528 | 529 | Data Model - cria modelo de dados com entidade e atributos. Entidade é como classe ou tabela e atributos são como campos dessa classe ou tabela. 530 | 531 | 532 | # Why to use `NSFetchedResultsController`? 533 | 534 | Um controlador de resultados buscados gerencia os resultados de uma solicitação de busca. Ele notifica seu delegado sobre quaisquer alterações que afetem os resultados dessa solicitação de busca. Ele ainda oferece a capacidade de usar um cache na memória para melhorar o desempenho; 535 | 536 | Embora a classe NSFetchResultsController tenha sido projetada com visualizações de tabela em mente, ela também funciona muito bem com visualizações de coleção. 537 | 538 | # POP: Protocol Oriented Programming 539 | 540 | Desvantagens da programação orientada a objetos. 541 | - Tem apenas uma herança. Se tivermos todas as hierarquias complicadas de herança, a classe inferior pode ter muitos estados desnecessários para manter. 542 | - usa classe que é um tipo de referência. O tipo de referência pode tornar o código inseguro. Processando a coleção de tipos de referência enquanto eles estão sendo modificados. 543 | 544 | Enquanto programação orientada a protocolos em Swift: 545 | - Pode conformar múltiplos protocolos; 546 | - Pode ser usado não apenas por classe, mas também por estruturas e enumerações; 547 | - possui extensão de protocolo que nos dá funcionalidade comum a todos os tipos que estão em conformidade com um protocolo; 548 | - Prefere usar um tipo de valor em vez de um tipo de referência 549 | 550 | # KVC & KVO 551 | 552 | KVC: Adiciona significa codificação de valor-chave. É um mecanismo pelo qual as propriedades de um objeto podem ser acessadas usando strings em tempo de execução, em vez de ter que saber estaticamente os nomes das propriedades em tempo de desenvolvimento. 553 | 554 | KVO: significa observação de valor-chave e permite que um controlador ou classe observe alterações em um valor de propriedade. No KVO, um objeto pode pedir para ser notificado de alguma propriedade específica, sempre que essa propriedade mudar de valor, o observador é automaticamente notificado das mudanças. Você pode usar KVO em Swift, mas apenas para propriedades dinâmicas da subclasse NSObject. 555 | 556 | Ex: 557 | KVC: `let robertLastName = self.value(forKey: “lastName”)` 558 | 559 | KVO: 560 | ```swift 561 | @objc class Person: NSObject { 562 | @objc dynamic var name = “Taylor Swift” 563 | } 564 | 565 | Let taylor = Person() 566 | Taylor.observe(\Person.name, options: .new) { person, change in 567 | print(“I’m now called \(person.name)”) 568 | } 569 | ```` 570 | 571 | # Push Notification 572 | 573 | Device -> APP -> Server -> APNS 574 | 575 | 1. Registre-se para notificação por push 576 | 2. Enviar solicitação ao APNS 577 | 3. Responda com o token do dispositivo 578 | 4. O dispositivo envia token para o aplicativo 579 | 5. Envia o token do dispositivo para o servidor 580 | 6. O servidor encerra a carga útil de notificação com o token do dispositivo para APNS 581 | 7. Envia notificação ao dispositivo 582 | 583 | Então a lista de verificação do APNS: 584 | - Criar appId permitido com notificação push 585 | - Criar certificado SSL com certificado válido e ID do aplicativo 586 | - Crie um perfil de provisionamento com o mesmo certificado e certifique-se de adicionar dispositivo em caso de sandboxing (provisionamento de desenvolvimento) 587 | 588 | # Content Hugging & Compression resistance 589 | 590 | Hugging - o conteúdo não quer crescer 591 | Compression Resistance - o conteúdo não quer encolher 592 | 593 | # Singleton 594 | 595 | O padrão singleton é um padrão muito útil. Há momentos em que você deseja garantir que apenas uma instância de uma classe seja instanciada e que seu aplicativo use apenas essa instância. Esse é o objetivo principal e único do padrão singleton. Objetos singleton podem ser acessados globalmente 596 | 597 | Se você já trabalhou com os frameworks da Apple, é provável que já tenha usado o padrão Singleton. 598 | 599 | Ex: 600 | ```swift 601 | let sharedURLSession = URLSession.shared 602 | let standardUserDefaults = UserDefaults.Standard 603 | 604 | class LocationManager { 605 | static let shared = LocationManager() 606 | var locationGranted: Bool? // Initializer access level change now private init() {} 607 | func requestForLocation() { 608 | locationGranted = true 609 | print(“Location granted”) 610 | } 611 | } 612 | // Access class function in a single line 613 | LocationManager.shared.requestForLocation() 614 | ``` 615 | 616 | # Why Singleton is bad? 617 | 618 | O padrão singleton tem um efeito colateral que geralmente é o verdadeiro motivo para adotar o padrão singleton, o acesso global. Muitos desenvolvedores usam o padrão singleton para ter acesso fácil ao objeto singleton de qualquer lugar em seu projeto. Embora isso seja conveniente, essa conveniência tem um preço. 619 | 620 | Desvantagens de usar Singleton: 621 | - Sacrificar a transparência por conveniência: Ao usar singletons, você quase sempre sacrifica a transparência por conveniência. Como os singletons são tão convenientes e fáceis de acessar - usá-los extensivamente geralmente leva a uma manutenção muito difícil do "código espaguete" que não possui separações claras entre os objetos. 622 | - Eles são um estado compartilhado mutável global: seu estado é compartilhado automaticamente em todo o aplicativo, e os bugs podem começar a ocorrer quando esse estado muda inesperadamente. 623 | - Gerenciar seu ciclo de vida pode ser complicado: como os singletons estão ativos durante toda a vida útil de um aplicativo, gerenciá-los pode ser muito difícil e eles geralmente precisam contar com opcionais para acompanhar os valores. 624 | 625 | # Dependency Injection 626 | 627 | A cura para resolver o singleton é a injeção de dependência. Embora a principal vantagem do padrão singleton seja a conveniência, a vantagem mais importante da injeção de dependência é a transparência. 628 | Se um objeto requer um objeto de usuário válido para fazer seu trabalho, esse objeto de usuário deve ser injetado como uma dependência. 629 | 630 | Ex: 631 | 632 | ```swift 633 | class User { 634 | var firstName = “” 635 | var lastName = “” 636 | } 637 | 638 | class NetworkController { 639 | let user: User 640 | init (user: user) { 641 | self.user = user 642 | } 643 | } 644 | ``` 645 | 646 | # What is ABI? 647 | 648 | As ABIs são importantes quando se trata de aplicativos que usam bibliotecas externas. Se um programa for criado para usar uma biblioteca específica e essa biblioteca for atualizada posteriormente, você não precisará recompilar esse aplicativo (e do ponto de vista do usuário final, talvez você não tenha o código-fonte). Se a biblioteca atualizada usar a mesma ABI, seu programa não precisará ser alterado. 649 | 650 | # What is viewDidLayoutSubviews? 651 | 652 | `viewDidLayoutSubviews` é chamado para notificar o controlador de visualização de que sua visualização acabou de apresentar suas subvisualizações. 653 | Em outras palavras, `viewDidLayoutSubviews` é chamado toda vez que a exibição é atualizada, girada ou alterada ou seus limites são alterados. A palavra-chave aqui é mudança de limites. 654 | 655 | # What is loadView? 656 | 657 | Apenas substitua este método se você criar suas visualizações manualmente (ou seja, NÃO storyboard). loadView() cria e instancia o UIView. 658 | 659 | `viewDidLoad()` é chamado quando a visualização termina de carregar, enquanto `loadView()` é chamado quando a visualização começa a ser carregada. 660 | 661 | # NSArray vs Array 662 | 663 | Array é uma struct, portanto, é um tipo de valor em Swift. NSArray é uma classe Objective C imutável, portanto, é um tipo de referência em Swift e está ligado a Array. NSMutableArray é a subclasse mutável de NSArray. 664 | 665 | # NSDictionary vs Dictionary 666 | 667 | Dicionário é uma estrutura nativa do Swift. NSDictionary é uma classe de cacau. Eles são ligados a outro (dentro dos limites usuais), como os documentos explicam de forma muito clara e completa. 668 | 669 | # Computed and Stored Properties 670 | 671 | - Propriedade Armazenada 672 | 1. Armazene valores constantes e variáveis como instância 673 | 2. Fornecido por classes e estruturas 674 | 675 | - Propriedade computada 676 | 1. Calcular um valor em vez de armazenar o valor, declarações 'let' não podem ser propriedades computadas 677 | 2. Fornecido por classes, enumerações, estruturas e extensões 678 | 679 | # Property Observer for computed properties 680 | 681 | Cada vez que os valores de propriedade são definidos, observadores de propriedade são chamados; 682 | Antes de armazenar o valor - willSet 683 | Depois de armazenar o novo valor - didSet 684 | Quando uma propriedade é definida em um inicializador, os observadores willSet e didSet não podem ser chamados. 685 | 686 | Ex: 687 | 688 | ```Swift 689 | class PropertyObserverEx { 690 | var counter: Int = 0 { 691 | willSet(newTotal) { 692 | print(“Total Counter is :\(newTotal)”) 693 | } 694 | 695 | didSet { 696 | if counter > oldValue { 697 | print(“Newly added counter \(counter - oldValue)”) 698 | } 699 | } 700 | } 701 | } 702 | 703 | let newCounter = PropertyObserverEx() 704 | newCounter.counter = 10 705 | newCounter.counter = 60 706 | 707 | Response - 708 | Total Counter is: 10 709 | Newly Added Counter 10 710 | Total Counter is: 60 711 | Newly Added Counter 50 712 | ``` 713 | 714 | # Can we use computed or stored properties in extension? 715 | 716 | Podemos usar propriedades computadas com extensão, mas propriedades armazenadas. 717 | 718 | # Can we write extension for struct/enum/protocol? 719 | 720 | Sim, podemos escrever extensão para todos eles. 721 | 722 | # Is Optional an Enum? 723 | 724 | Sim, basicamente, um Optional é um Enum com 2 casos e um dos casos tem um valor associado a ele. 725 | - .Some (Wrapped) 726 | - .None 727 | 728 | # Sync vs Async: deadlock situation 729 | 730 | Quando você invoca algo de forma síncrona, significa que o thread que iniciou essa operação aguardará a conclusão da tarefa antes de continuar. Assíncrono significa que não vai esperar. 731 | 732 | O objetivo é liberar o thread principal para que ele possa continuar respondendo à interface do usuário (em vez de congelar) 733 | 734 | Há duas partes nisso: 735 | - Pegue uma fila em segundo plano (ex: CGD) 736 | - Despache sua tarefa para essa fila de forma síncrona / assíncrona 737 | 738 | Sync Async: Deadlock Situation 739 | ```Swift 740 | let queue = DispatchQueue(label: “label”) 741 | queue.async { 742 | queue.sync { 743 | // outer block is waiting for this inner block to complete, 744 | // inner block won’t start before outer block finishes 745 | // => deadlock 746 | } 747 | // this will never be reached 748 | } 749 | ``` 750 | 751 | ``` 752 | queue.sync { 753 | queue.sync { 754 | // outer block is waiting for this inner block to complete, 755 | // inner block won’t start before outer block finishes 756 | } 757 | } 758 | ``` 759 | 760 | Sync Async: No Deadlock 761 | 762 | ```Swift 763 | queue.sync { 764 | queue.async { 765 | // outer block is waiting for this inner block to complete,
 766 | // inner block won’t start before outer block finishes
 767 | // => deadlock 768 | } 769 | // this will never be reached 770 | } 771 | ``` 772 | 773 | ```Swift 774 | queue.async { 775 | queue.async { 776 | // outer block is waiting for this inner block to complete, 777 | // inner block won’t start before outer block finishes 778 | // => deadlock 779 | } 780 | // this will never be reached 781 | } 782 | ``` 783 | 784 | # Example of Strong & Weak? 785 | 786 | - Use of Weak: 787 | 788 | 1. Delegates 789 | 2. Outlets 790 | 3. Subviews 791 | 4. Controls 792 | 793 | - Use of Strong: 794 | 795 | 1. Remaining everywhere which is not included in Weak 796 | 797 | # Semaphore 798 | 799 | Apenas um thread pode acessar um recurso por vez. Semáforos nos dá a capacidade de controlar o acesso a um recurso compartilhado por vários threads. 800 | 801 | let semaphore = DispatchSemaphore(value: 1) // apenas um thread pode acessar este recurso por vez 802 | 803 | - Chame wait() toda vez antes de usar o recurso compartilhado. Estamos basicamente perguntando ao semáforo se o recurso compartilhado está disponível ou não. Se não, vamos esperar. 804 | - Chame signal() toda vez depois de usar o recurso compartilhado. Estamos basicamente sinalizando ao semáforo que terminamos de interagir com o recurso compartilhado. 805 | 806 | Ex: Baixar 15 músicas de uma url 807 | 808 | ```Swift 809 | let queue = DispatchQueue(label: “com.gcd.myQueue”, attributes: .concurrent) 810 | let semaphore = DispatchSemaphore(value: 3) // Only 3 songs can be downloaded at a time 811 | 812 | for i in 0 ..> 15 { 813 | queue.async { 814 | let songNumber = i + 1 815 | semaphore.wait() 816 | print(“Downloading song”, songNumber) 817 | sleep(2) // Download take ~2 sec each 818 | print(“Downloaded song”, songNumber) 819 | 820 | } 821 | } 822 | ``` 823 | --------------------------------------------------------------------------------