{"id":405628,"date":"2024-06-29T18:26:56","date_gmt":"2024-06-29T18:26:56","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=405628"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=405628","title":{"rendered":"<span>\u041f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0430 \u043a \u0441\u043e\u0431\u0435\u0441\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u044e \u043d\u0430 iOS \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430 (\u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u043e \u043d\u0430 \u043d\u0430\u0447\u0430\u043b\u043e 2023 \u0433\u043e\u0434\u0430)<\/span>"},"content":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<h2>\u041d\u0435\u0431\u043e\u043b\u044c\u0448\u0430\u044f \u043f\u0440\u0435\u0434\u044b\u0441\u0442\u043e\u0440\u0438\u044f <\/h2>\n<p>\u0414\u043e\u0431\u0440\u043e\u0433\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0441\u0443\u0442\u043e\u043a. \u042f iOS-\u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a (\u0445\u043b\u043e\u043f\u043a\u0438-\u0445\u043b\u043e\u043f\u043a\u0438).<\/p>\n<p>\u0422\u0430\u043a \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u043e\u0441\u044c, \u0447\u0442\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u043b \u044f iOS-\u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u043c \u043d\u0430 \u043e\u0434\u043d\u043e\u043c \u043b\u0435\u0433\u0430\u0441\u0438-\u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u0432 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438-\u0432\u0435\u043d\u0434\u043e\u0440\u0435. \u0412 \u043e\u043a\u0442\u044f\u0431\u0440\u0435 \u043f\u0440\u043e\u0448\u043b\u043e\u0433\u043e \u0433\u043e\u0434\u0430 \u043f\u043e\u044f\u0432\u0438\u043b\u043e\u0441\u044c \u0436\u0435\u043b\u0430\u043d\u0438\u0435 \u0441\u043c\u0435\u043d\u0438\u0442\u044c \u0442\u0435\u043a\u0443\u0449\u0438\u0439 \u043f\u0440\u043e\u0435\u043a\u0442, \u0447\u0442\u043e\u0431\u044b \u043f\u0435\u0440\u0435\u0441\u0442\u0430\u0442\u044c \u0432\u043e\u043b\u043d\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043e \u043b\u0435\u0433\u0430\u0441\u0438 \u0438 \u043d\u0430\u0447\u0430\u0442\u044c \u0440\u0430\u0437\u0432\u0438\u0432\u0430\u0442\u044c\u0441\u044f. <\/p>\n<p>\u041f\u043e\u0433\u043e\u0432\u043e\u0440\u0438\u0432 \u0441 \u043d\u0430\u0447\u0430\u043b\u044c\u0441\u0442\u0432\u043e\u043c, \u043c\u043d\u0435 \u043d\u0430\u0437\u043d\u0430\u0447\u0438\u043b\u0438 \u0432\u0441\u0442\u0440\u0435\u0447\u0443 \u0441 \u043b\u0438\u0434\u043e\u043c iOS, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u0438\u0442\u044c \u043c\u0435\u043d\u044f \u043a \u043f\u0440\u0435\u0434\u0441\u0442\u043e\u044f\u0449\u0438\u043c \u0441\u043e\u0431\u0435\u0441\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u044f\u043c. \u041e\u0434\u043d\u0430\u043a\u043e, \u043f\u043e\u0441\u043b\u0435 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u0432\u043e\u043f\u0440\u043e\u0441\u043e\u0432 \u043e\u0442 \u043b\u0438\u0434\u0430 \u0432\u0435\u0440\u0434\u0438\u043a\u0442 \u0431\u044b\u043b, \u0447\u0442\u043e \u043d\u0435 \u043f\u043e\u0434\u0445\u043e\u0436\u0443 \u043d\u0430 \u0442\u0435\u043a\u0443\u0449\u0438\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u044b. \u041d\u0430 \u0432\u043e\u043f\u0440\u043e\u0441, \u043a\u0430\u043a\u0438\u0435, \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u043a\u0440\u0438\u0442\u0435\u0440\u0438\u0438 \u043e\u0446\u0435\u043d\u0438\u0432\u0430\u043d\u0438\u044f \u044f \u043f\u043e\u043b\u0443\u0447\u0438\u043b \u043e\u0442\u0432\u0435\u0442:<\/p>\n<blockquote>\n<p>&#171;\u0442\u0435\u0431\u0435 \u043d\u0438\u043a\u043e\u0433\u0434\u0430 \u043d\u0438\u043a\u0442\u043e \u043d\u0435 \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0435\u0442? \u0432 \u043d\u0430\u0448\u0435\u043c \u0434\u0435\u043b\u0435 \u0432\u0441\u0435 \u0441\u0430\u043c ?&#187;<\/p>\n<\/blockquote>\n<p>\u0421\u0430\u043c \u0442\u0430\u043a \u0441\u0430\u043c. \u042f \u043d\u0430\u0447\u0430\u043b \u0447\u0438\u0442\u0430\u0442\u044c, \u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u043a\u0443\u0440\u0441\u044b, \u0432\u0438\u0434\u0435\u043e\u0443\u0440\u043e\u043a\u0438 \u0438 \u0430\u043a\u0442\u0438\u0432\u043d\u043e \u043f\u043e\u0434\u0430\u0432\u0430\u0442\u044c\u0441\u044f \u0432 \u0440\u0430\u0437\u043d\u044b\u0435 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438 \u043a\u0430\u043a \u0432 \u0420\u043e\u0441\u0441\u0438\u0438, \u0442\u0430\u043a \u0438 \u0437\u0430 \u0440\u0443\u0431\u0435\u0436\u043e\u043c, \u0447\u0442\u043e\u0431\u044b \u0432\u044b\u044f\u0441\u043d\u0438\u0442\u044c, \u043a\u0430\u043a\u0438\u0435, \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0433\u043e\u0432\u043e\u0440\u044f, \u043a\u0440\u0438\u0442\u0435\u0440\u0438\u0438 \u043f\u0440\u043e\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u044f. \u041f\u043e\u0441\u0442\u0435\u043f\u0435\u043d\u043d\u043e \u0440\u0430\u0437 \u0437\u0430 \u0440\u0430\u0437\u043e\u043c \u0441\u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043b\u0441\u044f \u0441\u043f\u0438\u0441\u043e\u043a \u043d\u0430\u0438\u0431\u043e\u043b\u0435\u0435 \u0447\u0430\u0441\u0442\u043e \u0432\u0441\u0442\u0440\u0435\u0447\u0430\u044e\u0449\u0438\u0445\u0441\u044f \u0432\u043e\u043f\u0440\u043e\u0441\u043e\u0432 \u043d\u0430 \u0441\u043e\u0431\u0435\u0441\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u044f\u0445 iOS-\u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u044f \u0440\u0435\u0448\u0438\u043b \u043e\u043f\u0443\u0431\u043b\u0438\u043a\u043e\u0432\u0430\u0442\u044c \u0437\u0434\u0435\u0441\u044c.<\/p>\n<h2>\u0422\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0432\u043e\u043f\u0440\u043e\u0441\u044b<\/h2>\n<p>\u0422.\u043a. \u0441\u043e\u0431\u0435\u0441\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u044f \u0431\u044b\u043b\u0438 \u0432 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u043c \u043d\u0430 \u0430\u043d\u0433\u043b\u0438\u0439\u0441\u043a\u043e\u043c \u044f\u0437\u044b\u043a\u0435, \u0442\u043e \u0441 \u0432\u0430\u0448\u0435\u0433\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u0435\u043d\u0438\u044f \u043e\u0441\u0442\u0430\u0432\u043b\u044e \u0442\u0443\u0442 \u0438 \u0432\u043e\u043f\u0440\u043e\u0441\u044b \u0438 \u043e\u0442\u0432\u0435\u0442\u044b \u043d\u0430 \u0430\u043d\u0433\u043b\u0438\u0439\u0441\u043a\u043e\u043c. \u041f\u043e\u0435\u0445\u0430\u043b\u0438.<\/p>\n<h3>1. What frameworks you used in your iOS projects?<\/h3>\n<p>You can specify frameworks like: UIKit, SwiftUI, Combine, AVFramework, PushNotification, CallKit, GCD, Core Bluetooth, etc.<\/p>\n<h3>2. How the Optional is implemented in Swift?<\/h3>\n<pre><code class=\"swift\">enum Optional&lt;Wrapped> {     case none     case some(Wrapped) }<\/code><\/pre>\n<h3>3. Is there a difference between .none and nil?<\/h3>\n<p>No<\/p>\n<h3>4. Ways to unwrap optional variables<\/h3>\n<pre><code class=\"swift\">var a:Int? \/\/1 a! \/\/2 if let s = a {     print(s) } \/\/3 if let a {     print(a) } \/\/4 guard let s = a else {     print(s)     return } \/\/5 a ?? 0 \/\/5<\/code><\/pre>\n<h3>5. What&#8217;s difference between reference and value types? What reference and value types you know?<\/h3>\n<p><strong>Value types<\/strong>: structs, enums, arrays, dictionaries, strings<\/p>\n<p><strong>Reference types<\/strong>: classes, closures, NS types (NSString, for example) (because they are classes) <\/p>\n<p><strong>Two differences between value and reference types:<\/strong><\/p>\n<ol>\n<li>\n<p>Value types are stored in Stack and reference types are stored in Heap.<\/p>\n<\/li>\n<li>\n<p>If you assign one object to another for a reference type, you just copy the reference, not value:<\/p>\n<\/li>\n<\/ol>\n<pre><code class=\"swift\">\/\/ Reference type example class C { var data: Int = -1 } var x = C() var y = x\/\/ x is copied to y x.data = 42\/\/ changes the instance referred to by x (and y) println(\"\\(x.data), \\(y.data)\")\/\/ prints \"42, 42\"<\/code><\/pre>\n<p>For value types you will copy the value of the variable.<\/p>\n<h3>6. What&#8217;s difference between Class and Structure?<\/h3>\n<ul>\n<li>\n<p>Structures are value types.<\/p>\n<\/li>\n<li>\n<p>Classes are reference types.<\/p>\n<\/li>\n<li>\n<p>Structures don\u2019t support inheritance.<\/p>\n<\/li>\n<li>\n<p>classes support inheritance.<\/p>\n<\/li>\n<li>\n<p>Structures don\u2019t support de-initializers. ( deinit )<\/p>\n<\/li>\n<li>\n<p>Classes support de-initializers.<\/p>\n<\/li>\n<li>\n<p>Structures don\u2019t follow Reference Counting (<em>look at the question 19 about ARC)<\/em>.<\/p>\n<\/li>\n<li>\n<p>Classes follow Reference Counting.<\/p>\n<\/li>\n<li>\n<p>Mutating Keyword is needed to modify the property values in Structure\u2019s instance methods.<\/p>\n<\/li>\n<li>\n<p>No need of mutating keyword to modify the class variable\u2019s value.<\/p>\n<\/li>\n<\/ul>\n<h3>7. Do you know what copy-on-write means?<\/h3>\n<p>If you assign one array to another (not only array, there are other objects), then the second object will refer to the first array address until the second array is not changed.<\/p>\n<pre><code class=\"swift\">func addressOf(_ o: UnsafeRawPointer) -> String {     let addr = unsafeBitCast(o, to: Int.self)     return String(format: \"%p\", addr) } \/\/our array var array = [1, 2, 3, 4, 5] addressOf(array) \/\/ 0x600002e30ac0 \/\/here we assign one array to another var array2 = array \/\/look - the address of the second array is the same addressOf(array2) \/\/ 0x600002e30ac0 \/\/here we change the second array  array2.append(6) \/\/look again - address has changed addressOf(array2) \/\/ 0x6000026119f0<\/code><\/pre>\n<h3>8. Do you know what are SOLID principles?<\/h3>\n<p>SOLID is abbreviation.<\/p>\n<h4>S \u2013 single responsibility principle.<\/h4>\n<p>It\u2019s when a class has just one purpose. A class shouldn\u2019t contain functions that could be moved to other classes<\/p>\n<h4>O \u2013 open\/closed principle (OCP)<\/h4>\n<p>A class should be opened for extension, but closed for changes.<\/p>\n<p>Open closed principle allows to <strong>avoid this kind of code<\/strong>:<\/p>\n<pre><code class=\"swift\">protocol SomeProtocol { }  class A:SomeProtocol {     func printClassAName() {         print(\"I'm A\")     } }  class B:SomeProtocol {     func printClassBName() {         print(\"I'm B\")     } }  class Caller {     func printClassName(obj:SomeProtocol){       \/\/\/\/TO AVOID THIS KIND OF CODE!!!!!         if let unwrappeObj = obj as? A {             obj.printClassAName()         }         else if let unwrappeObj = obj as? B {             obj.printClassBName()         }     } }<\/code><\/pre>\n<p>It should be changed like that to avoid changes in Caller class in the future:<\/p>\n<pre><code class=\"swift\">protocol SomeProtocol {     func printClassName() }  class A:SomeProtocol {     func printClassName() {         print(\"I'm A\")     } }  class B:SomeProtocol{     func printClassName() {         print(\"I'm B\")     } }  class Caller {     func doSomething(obj:SomeProtocol){         print(obj.printClassName())     } }<\/code><\/pre>\n<p>This principle is similar with D (dependency inversion principle), but OCP is more general. The DIP is an extension of the OCP.<\/p>\n<h4>L \u2013 Liskov principle.<\/h4>\n<p>In simple words this principle says that you need to have a possibility to use a parent and a child classes without any difference.<\/p>\n<pre><code class=\"swift\">class A: SomeProtocol { }  class B: SomeProtocol { }  let a = A() let b = B() var a:[SomeProtocol] = [a, b]<\/code><\/pre>\n<h4>I \u2013 interface segregation.<\/h4>\n<p>Classes <strong>SHOULDN&#8217;T<\/strong> implement protocol methods they don\u2019t use. If we noticed this situation, just move these methods to a separate protocol.<\/p>\n<h4>D \u2013 dependency inversion.<\/h4>\n<p>It means that a class shouldn\u2019t depend on low-level modules \u2013 they both should depend on an Abstraction<\/p>\n<p>For example:<\/p>\n<pre><code class=\"swift\">class FileSystemManager {   func save(string: String) {     \/\/ Open a file     \/\/ Save the string in this file     \/\/ Close the file   } }  class Handler {     let fileManager = FilesystemManager()     func handle(string: String) {         fileManager.save(string: string)     } }<\/code><\/pre>\n<p>If in the future we\u2019ll need to add other methods for saving data (data base, for example), we should inherit both <code>FilesystemManager<\/code> and this new data base interactor class from some Storage protocol and use it instead of <strong>FilesystemManager<\/strong> and other possible data saving ways:<\/p>\n<pre><code class=\"swift\">class FileSystemManager:Storage {     func save(string: String) {         \/\/ Open a file         \/\/ Save the string in this file         \/\/ Close the file     } }  class DataBaseManager:Storage {     func save(string: String) {         \/\/ Open DB         \/\/ Save the data         \/\/ Close DB     } }  class Handler {     let storage:Storage     func handle(string: String) {         storage.save(string: string)     } }<\/code><\/pre>\n<p>This principle is similar with OCP is more general. The DIP is an extension of the OCP.<\/p>\n<p>Difference is that OCP is for similar functions, but DIP deals with the same input data<\/p>\n<h3>9. What is Singleton?<\/h3>\n<p>The main point of Singleton is to ensure that we initialized something only once and this &#171;something&#187; should be available from everywhere. For example, <code>UIApplication.shared<\/code><\/p>\n<p><strong>P.S.:<\/strong> ServiceLocator \u2013 is a singleton with an array of some services<\/p>\n<h3>10. How are you doing your code reviews?<\/h3>\n<p>The best practice said that the code review should depend on CI\/CD tests, a style guide, SOLID, and some linter (a syntax checker)<\/p>\n<h3>11. Application lifecycle<\/h3>\n<p>Use this:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/7dc\/f72\/232\/7dcf72232cd8782e8e284e52db4f7211.png\" alt=\"Taken from Apple documentation\" title=\"Taken from Apple documentation\" width=\"830\" height=\"889\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/7dc\/f72\/232\/7dcf72232cd8782e8e284e52db4f7211.png\"\/><\/p>\n<div><figcaption>Taken from Apple documentation<\/figcaption><\/div>\n<\/figure>\n<h3>12. ViewController lifecycle<\/h3>\n<ul>\n<li>\n<p><strong>ViewDidLoad<\/strong>\u00a0&#8212; Called when you create the class and load from xib. Great for initial setup and one-time-only work.<\/p>\n<\/li>\n<li>\n<p><strong>ViewWillAppear<\/strong>\u00a0&#8212; Called right before your view appears, good for hiding\/showing fields or any operations that you want to happen every time before the view is visible. Because you might be going back and forth between views, this will be called every time your view is about to appear on the screen.<\/p>\n<\/li>\n<li>\n<p><strong>ViewDidAppear<\/strong>\u00a0&#8212; Called after the view appears &#8212; great place to start an animations or the loading of external data from an API.<\/p>\n<\/li>\n<li>\n<p><strong>ViewWillDisappear\/DidDisappear<\/strong>\u00a0&#8212; Same idea as\u00a0ViewWillAppear\/ViewDidAppear.<\/p>\n<\/li>\n<li>\n<p><strong>ViewDidUnload\/ViewDidDispose<\/strong>\u00a0&#8212; In Objective-C, this is where you do your clean-up and release of stuff, but this is handled automatically so not much you really need to do here<\/p>\n<\/li>\n<\/ul>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/775\/4c2\/3ca\/7754c23ca9738ead299cff80d5870efb.png\" alt=\"\" title=\"\" width=\"599\" height=\"450\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/775\/4c2\/3ca\/7754c23ca9738ead299cff80d5870efb.png\"\/><\/figure>\n<h3>P.S.: Can you say what ViewController lifecycle methods are calling when you started to segue from a view (A) to another view (B), but haven&#8217;t finish it?<\/h3>\n<h3>13. What architecture patterns you used?<\/h3>\n<p>Better to mention MVC, MVVM, VIPER, Clean Architecture. I recommend to implement test samples for each of these patterns.<\/p>\n<h3>14. What is VIPER?<\/h3>\n<p>VIPER \u2013 is an architecture pattern with these parts:<\/p>\n<ul>\n<li>\n<p>R \u2013 router \u2013 an entry point<\/p>\n<\/li>\n<li>\n<p>E \u2013 entity \u2013 model (like in MVC, for example)<\/p>\n<\/li>\n<li>\n<p>P \u2013 presenter \u2013 holds the reference to interactor, to a router and to a view<\/p>\n<\/li>\n<li>\n<p>Presenter uses data, received using fetching data functions from Interactor to update View.<\/p>\n<\/li>\n<li>\n<p>V \u2013 view. But with additional protocol with updating functions to call. For example, if we want to show an alert in a view, then we should ask the presenter to do that<\/p>\n<\/li>\n<li>\n<p>I \u2013 Interactor handles business logic and data retrieval<\/p>\n<\/li>\n<\/ul>\n<h3>15. What is Clean Architecture?<\/h3>\n<p>I used this scheme<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/6fc\/d8a\/56e\/6fcd8a56e165dc9a280614ada5f0bfab.webp\" alt=\"Taken from here: https:\/\/medium.com\/@info.vikaasyadav\/flutter-clean-architecture-with-riverpod-7807e54228c4\" title=\"Taken from here: https:\/\/medium.com\/@info.vikaasyadav\/flutter-clean-architecture-with-riverpod-7807e54228c4\" width=\"786\" height=\"301\"\/><\/p>\n<div><figcaption>Taken from here: https:\/\/medium.com\/@info.vikaasyadav\/flutter-clean-architecture-with-riverpod-7807e54228c4<\/figcaption><\/div>\n<\/figure>\n<h3>16. What is MVVM?<\/h3>\n<p>MVVM &#8212; Model View ViewModel<\/p>\n<ul>\n<li>\n<p><strong>Model<\/strong>\u00a0&#8212; is the data layer.<\/p>\n<\/li>\n<li>\n<p><strong>View<\/strong>\u00a0&#8212; is a view.<\/p>\n<\/li>\n<li>\n<p><strong>ViewModel<\/strong>\u00a0&#8212; contains presentation logic (process data from Model to View, reacts on actions from the View and transfers these reactions to Model).<\/p>\n<\/li>\n<\/ul>\n<p>In the code tree there should be three different directories: Models, Views, ViewModels. Each of your classes should be represented separately there.<\/p>\n<p>Sometimes it&#8217;s wise to create an additional directory called Services, in which you can put your business logic.<\/p>\n<h4>P.S.: What is MVVM-C?<\/h4>\n<h3>17. Who is an owner of data in MVVM?<\/h3>\n<p>Model is the data itself.<\/p>\n<h3>18. MVC and MVVM differences:<\/h3>\n<p>The main difference between MVC and MVVM is the role of the controller and view model. In MVC, the Controller handles user input and updates the Model and View. In MVVM the ViewModel handles user input and updates the Model and View, and the view is responsible for displaying the data.<\/p>\n<h3>19. What NS prefix means in some Swift and Objective-C classes?<\/h3>\n<p>It means next step (the name of one company)<\/p>\n<h3>20. How memory management works in iOS? (Automatic reference counter (ARC))<\/h3>\n<p>In this question it&#8217;s better to tell about ARC and retain cycles.<\/p>\n<p>Short explanation: ARC automatically keeps track of the number of references to an object, and when that number reaches zero, it deallocates the object. Counter decreases after an object releases. Any object deallocates after the counter is 0.<\/p>\n<p>If two objects have a strong reference to each other \u2013 retain cycle. Use weak or unowned to avoid that.<\/p>\n<p>(weak variables are presented as optional if to take a look on its type) (unowned variables are presented as usual (they can\u2019t be nil))<\/p>\n<p>My advise is to watch this video from Apple:\u00a0<\/p>\n<p><a href=\"https:\/\/developer.apple.com\/videos\/play\/wwdc2021\/10216\/\" rel=\"noopener noreferrer nofollow\">https:\/\/developer.apple.com\/videos\/play\/wwdc2021\/10216\/<\/a><\/p>\n<h3>21. What is map, flatMap, compatMap, reduce. Difference between map, flatMap, compatMap<\/h3>\n<h4>Mathematically:<\/h4>\n<p><strong>map<\/strong>:<\/p>\n<pre><code class=\"swift\">var arr:[Int] = [1, 2, 3]     arr = arr.map {     return $0+1 }<\/code><\/pre>\n<p><strong>flatMap<\/strong> (is equivalent to\u00a0<code>Array(s.map(transformation).joined())<\/code>):<\/p>\n<pre><code class=\"swift\">var arr:[Int] = [[1,2,3],[4,5,6]]     arr = arr.flatMap {     return $0 }<\/code><\/pre>\n<p><strong>compatMap<\/strong> &#8212; same as map, but filters nil values<\/p>\n<h4>In Combine<\/h4>\n<p><strong>map<\/strong> is used to transform each value emitted by a publisher using a provided closure. The closure takes in a value emitted by the publisher and returns a new value.<\/p>\n<p><strong>compatMap<\/strong> is similar to map, but it also filters out any values that are nil before emitting the new values<\/p>\n<p><strong>flatMap<\/strong> returns a new publisher with an emitted value as a parameter:<\/p>\n<pre><code class=\"swift\">var imagesListSubject = PassthroughSubject&lt;String, Error>()                           imagesListSubject                           .removeDuplicates()                           .flatMap { [unowned self] day in                             self.networkService.fetchDayImagesList(day: day)                           } <\/code><\/pre>\n<h3>22. How to make a multilevel dismiss in SwiftUI? (to dismiss multiple level navigation)<\/h3>\n<ol>\n<li>\n<p>You can use <code><a class=\"mention\" href=\"\/users\/EnvironmentObject\">@EnvironmentObject<\/a><\/code>, because it&#8217;s available in all nested views<\/p>\n<\/li>\n<li>\n<p>You can transfer <code><a class=\"mention\" href=\"\/users\/Binding\">@Binding<\/a><\/code> variable from the root view to new navigation levels and if you need, just toggle this variable<\/p>\n<\/li>\n<li>\n<p>Use an architecture pattern in which you can just set a current view. Like VIPER, REDUX and Composable architecture<\/p>\n<\/li>\n<\/ol>\n<h3>23. What is a View protocol in SwiftUI?<\/h3>\n<p>In SwiftUI, the View protocol is the fundamental building block of layout and user interface. But without some content it can&#8217;t exist<\/p>\n<h3>24. Why Views are structures in SwiftUI?<\/h3>\n<ul>\n<li>\n<p>structs are simpler to work with and faster than classes<\/p>\n<\/li>\n<li>\n<p>it takes less memory (it takes only what was set, without multilevel inheritance)<\/p>\n<\/li>\n<li>\n<p>views that don\u2019t mutate over time<\/p>\n<\/li>\n<\/ul>\n<h3>25. Is there a way to use UIKit elements in SwiftUI?<\/h3>\n<p>Yes. You should create a class that conforms to UIViewRepresentable and <code>UIViewControllerRepresentable<\/code> protocols.<\/p>\n<p>But this is a long story. If you are curious in implementation, just try to find a couple of examples.<\/p>\n<h3>26. Redux in iOS (example of button tapping)<\/h3>\n<p>A simple example in which a button increments a counter.<\/p>\n<pre><code class=\"swift\">\/\/ The state of the application struct AppState {     var count: Int = 0 }  \/\/ The actions that can be dispatched to the store enum CounterAction: Action {     case increment     case decrement }  \/\/ The reducer, which handles the actions and updates the state func counterReducer(action: Action, state: AppState?) -> AppState {     var state = state ?? AppState()     switch action {     case let action as CounterAction:         switch action {         case .increment:             state.count += 1         case .decrement:             state.count -= 1         }     default:         break     }        return state }  \/\/ The store, which holds the state and handles the actions let store = Store&lt;AppState>(     reducer: counterReducer,     state: nil )  \/\/ The view, which displays the state and dispatches actions struct ContentView: View {     @ObservedObject var store: Store&lt;AppState>     var body: some View {         VStack {             Text(\"Count: \\(store.state.count)\")             Button(\"Increment\") {                 self.store.dispatch(action: CounterAction.increment)             }         }     } }<\/code><\/pre>\n<h3>27. Composable architecture<\/h3>\n<ul>\n<li>\n<p>View sends events to Action<\/p>\n<\/li>\n<li>\n<p>Action sends an action to a Reducer (keeps state of the app alive)<\/p>\n<\/li>\n<li>\n<p>Reduces mutate State, sends a call to Effect (outside world), interacts with Environment (dependencies, that are helpful for testing)<\/p>\n<\/li>\n<li>\n<p>State influence View<\/p>\n<\/li>\n<\/ul>\n<h3>28. What asynchronous functionality is available in Swift?<\/h3>\n<ul>\n<li>\n<p>DispatchQueue<\/p>\n<\/li>\n<li>\n<p>DispatchGroup<\/p>\n<\/li>\n<li>\n<p>Operation queues<\/p>\n<\/li>\n<li>\n<p>delegate events<\/p>\n<\/li>\n<li>\n<p>Timer operations<\/p>\n<\/li>\n<li>\n<p>Combine publisher that is sending data<\/p>\n<\/li>\n<li>\n<p>async\/await<\/p>\n<\/li>\n<\/ul>\n<p><strong>A note:<\/strong> you should always update interface only on main thread (<code>DispatchQueue.main<\/code>), otherwise it can just stuck<\/p>\n<h3>29. What HTTP methods you know?<\/h3>\n<ul>\n<li>\n<p><strong>POST<\/strong>: Sends data to specific server to create or update information.<\/p>\n<\/li>\n<li>\n<p><strong>PUT<\/strong>: Sends data to specific server to create or update information without the risk of creating the resource more than once.<\/p>\n<\/li>\n<li>\n<p><strong>HEADER<\/strong>: Previews what the GET request response might be without the body of the text.<\/p>\n<\/li>\n<li>\n<p><strong>OPTIONS<\/strong>: Learns the communication channels used by the target source.<\/p>\n<\/li>\n<li>\n<p><strong>GET<\/strong>: Requests information from a specific source.<\/p>\n<\/li>\n<li>\n<p><strong>DELETE<\/strong>: Removes information.<\/p>\n<\/li>\n<\/ul>\n<h3>30. How do you test network calls in Unit test?<\/h3>\n<p>There are several ways:<\/p>\n<ol>\n<li>\n<p><strong>You can mock network calls.<\/strong><\/p>\n<\/li>\n<\/ol>\n<pre><code class=\"swift\">protocol NetworkServiceProtocol {     func getDataFromServer(completion: @escaping (Result&lt;Data, Error>) -> Void) } <\/code><\/pre>\n<p>Then, create a mock implementation of the protocol that returns pre-defined data:<\/p>\n<pre><code class=\"swift\">class MockNetworkService: NetworkServiceProtocol {     func getDataFromServer(completion: @escaping (Result&lt;Data, Error>) -> Void) {         let data = Data(\"Mocked data\".utf8)         completion(.success(data))     } } <\/code><\/pre>\n<p>Now, in your test case, you can inject the mock network service into your code:<\/p>\n<pre><code class=\"swift\">func testGetDataFromServer() {     let mockService = MockNetworkService()     let viewModel = MyViewModel(networkService: mockService)     viewModel.getDataFromServer()     \/\/ Assert that the view model processed the mocked data correctly     XCTAssertEqual(viewModel.result, \"Mocked data\") } <\/code><\/pre>\n<ol start=\"2\">\n<li>\n<p><strong>You can mock not only network calls<\/strong>, you can mock entire classes using, for example, OCMock framework<\/p>\n<\/li>\n<li>\n<p><strong>Apple recommends<\/strong> to do something like this, to mock <code>URLSession<\/code> configuration<\/p>\n<\/li>\n<\/ol>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/414\/410\/7a3\/4144107a34b6504ff9ee547f41850723.png\" alt=\"https:\/\/developer.apple.com\/videos\/play\/wwdc2018\/417\/\" title=\"https:\/\/developer.apple.com\/videos\/play\/wwdc2018\/417\/\" width=\"1364\" height=\"768\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/414\/410\/7a3\/4144107a34b6504ff9ee547f41850723.png\"\/><\/p>\n<div><figcaption><a href=\"https:\/\/developer.apple.com\/videos\/play\/wwdc2018\/417\/\" rel=\"noopener noreferrer nofollow\">https:\/\/developer.apple.com\/videos\/play\/wwdc2018\/417\/<\/a><\/figcaption><\/div>\n<\/figure>\n<p>Here is the code example of mocked HTTP request using Combine:<\/p>\n<pre><code class=\"swift\">import XCTest  class MockURLProtocol: URLProtocol {     static var requestHandler: ((URLRequest) throws -> (HTTPURLResponse, Data))?          override class func canInit(with request: URLRequest) -&amp;gt; Bool {         return true     }      override class func canonicalRequest(for request: URLRequest) -&amp;gt; URLRequest {         return request     }      override func startLoading() {         guard let handler = MockURLProtocol.requestHandler else {             XCTFail(\"Received unexpected request with no handler set\")             return         }         do {             let (response, data) = try handler(request)             client?.urlProtocol(self, didReceive: response, cacheStoragePolicy: .notAllowed)             client?.urlProtocol(self, didLoad: data)             client?.urlProtocolDidFinishLoading(self)         } catch {             client?.urlProtocol(self, didFailWithError: error)         }     }      override func stopLoading() {     } }  enum ServiceError: Error, Equatable {     case invalidURL     case noInternetConnection     case requestTimeout     case networkError     case statusCodeError(code: Int?) }  final class NetworkLayerTests: XCTestCase {     var mockedUrlSession: URLSession!          override func setUpWithError() throws {         \/\/exit test if something failes         self.continueAfterFailure = false                  let configuration = URLSessionConfiguration.ephemeral                  \/\/set up a mock for url session         configuration.protocolClasses = [MockURLProtocol.self]         mockedUrlSession = URLSession(configuration: configuration)     }        struct UserProfile:Codable {         var name:String?     }      class ProfileAPI {         let url = URL(string: \"https:\/\/testURL.com\/user\")!         private var cancellable: AnyCancellable?                  \/\/ session to be used to make the API call         let session: URLSession                  \/\/ Make the session shared by default.         \/\/ In unit tests, a mock session can be injected.         init(urlSession: URLSession = .shared) {             self.session = urlSession         }                  \/\/ get user profile from backend         func getProfile(completion: @escaping (UserProfile) -&amp;gt; Void) {             cancellable = session.dataTaskPublisher(for: url)                 .mapError { error -&amp;gt; ServiceError in                     switch error.code {                     case .notConnectedToInternet:                         return .noInternetConnection                     case .timedOut:                         return .requestTimeout                     default:                         return .networkError                     }                 }                 .tryMap { data, response in                     guard let httpResponse = response as? HTTPURLResponse,                         200..&amp;lt;300 ~= httpResponse.statusCode else {                         throw ServiceError.statusCodeError(code: (response as! HTTPURLResponse).statusCode)                     }                     return data                 }                 .decode(type: UserProfile.self, decoder: JSONDecoder())                 .receive(on: RunLoop.main)                 .catch { _ in Just(UserProfile()) }                 .sink { user in                     completion(user)             }         }     }      func testCase() throws {                  let example = UserProfile(name: \"Some User\")         let mockData = try JSONEncoder().encode(example)                  \/\/set return data in mock request handler         MockURLProtocol.requestHandler = { request in             let response = HTTPURLResponse(url: URL(string: \"https:\/\/someURL.com\/test\")!,                                            statusCode: 200,                                            httpVersion: nil,                                            headerFields: [\"Content-Type\": \"application\/json\"])!             return (response, mockData)         }              \/\/this is simpler example, but without http-status mocking          \/\/        MockURLProtocol.requestHandler = { request in     \/\/            return (HTTPURLResponse(), mockData)     \/\/        }         \/\/ Set expectation. Used to test async code.         let expectation = XCTestExpectation(description: \"response\")                  \/\/ Make mock network request to get profile         \/\/ here we use the previously set mocked UrlSession         let profileAPI = ProfileAPI(urlSession: mockedUrlSession)                  profileAPI.getProfile { user in             \/\/ Test             XCTAssertEqual(user.name, \"Some User\")             expectation.fulfill()         }         wait(for: [expectation], timeout: 1)     }  }<\/code><\/pre>\n<h3>31. What is the role of the &#171;final&#187; word in the class?<\/h3>\n<p>It prevents properties and functions from overriding.<\/p>\n<h3>32. What are lazy variables?<\/h3>\n<p>They initialize after the first time they are calling.<\/p>\n<h3>33. Pros and cons of using UIKit and SwiftUI<\/h3>\n<h3>34. Is there a difference between &#171;Codable&#187; and &#171;Encodable &amp; Decodable&#187; protocol inheritance?<\/h3>\n<p>No, Codable is a type alias for Encodable &amp; Decodable<\/p>\n<h3>35. What are Encodable and Decodable protocols used for?<\/h3>\n<p><code>protocol Decodable<\/code> : allows to decode bytes to the type that inherits Decodable<\/p>\n<p><code>protocol Encodable<\/code> : allows to represent a type as data bytes<\/p>\n<p>Often they are used for interaction with JSON and plist.<\/p>\n<h4>P.S.: There could be a related question, can we rename keys during encoding\/decoding?<\/h4>\n<p>Yes, we can using CodingKey syntax<\/p>\n<pre><code class=\"swift\">struct Person: Decodable {     var personName: String     enum CodingKeys: String, CodingKey {        case personName = \"name\"     } }<\/code><\/pre>\n<h3>36. How would you explain App Transport Security (ATS) to a junior?<\/h3>\n<p>ATS blocks insecure URLSession connections. (Security criteria are shown here\u00a0<a href=\"https:\/\/developer.apple.com\/documentation\/security\/preventing_insecure_network_connections\" rel=\"noopener noreferrer nofollow\">https:\/\/developer.apple.com\/documentation\/security\/preventing_insecure_network_connections<\/a>)<\/p>\n<p>There are two ways to prevent connections blocking:<\/p>\n<ol>\n<li>\n<p>Set &#171;Allow Arbitrary Loads&#187; &#8212; it is <strong>not a good approach<\/strong>, but it looks like that:<\/p>\n<\/li>\n<\/ol>\n<pre><code class=\"xml\">&lt;key>NSAppTransportSecurity&lt;\/key> &lt;dict> &lt;key>NSAllowsArbitraryLoads&lt;\/key> &lt;true\/> &lt;\/dict><\/code><\/pre>\n<ol start=\"2\">\n<li>\n<p>You can set the exceptions. That is the <strong>good approach<\/strong>. It looks like that:<\/p>\n<\/li>\n<\/ol>\n<pre><code class=\"xml\">&lt;key>NSAppTransportSecurity&lt;\/key> &lt;dict> &lt;key>NSAllowsArbitraryLoads&lt;\/key> &lt;false\/> &lt;key>NSExceptionDomains&lt;\/key> &lt;dict> &lt;key>exception.com&lt;\/key> &lt;dict> &lt;key>NSIncludesSubdomains&lt;\/key> &lt;true\/> &lt;key>NSExceptionAllowsInsecureHTTPLoads&lt;\/key> &lt;true\/> &lt;\/dict> &lt;\/dict> &lt;\/dict><\/code><\/pre>\n<h3>37. How would you explain Dependency Injection to a junior?<\/h3>\n<p>Dependency Injection is an approach, when functionality of one entity depends on the other entity and the FIRST gets the SECOND as a parameter.<\/p>\n<p>I would provide an example of MVVM implementation, because link to ViewModel in View is a good example of Dependency Injection.<\/p>\n<h3>38. What&#8217;s difference between @escaping and non-escaping closures?<\/h3>\n<p><code><a class=\"mention\" href=\"\/users\/escaping\">@escaping<\/a><\/code> launches after the function ends, non-escaping &#8212; just after its call.<\/p>\n<h3>39. What&#8217;s difference between inout parameter of the function and a usual parameter?<\/h3>\n<pre><code class=\"swift\">func example(_ a: Int, _ b: inout Int) {}<\/code><\/pre>\n<p><code>inout<\/code> keyword allows to change the value of the parameter variable.<\/p>\n<h3>40. Do classes support multiple inheritance in Swift?<\/h3>\n<p>If to try to inherit from multiple classes, then NO. Swift classes don&#8217;t support multiple inheritance.<\/p>\n<p>But you can inherit multiple protocols.<\/p>\n<h2>\u041d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u044b\u0432\u043e\u0434\u044b \u0441 \u0441\u043e\u0431\u0435\u0441\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u0439<\/h2>\n<p>\u0413\u043b\u0430\u0432\u043d\u044b\u0435 \u0432\u0435\u0449\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u044f \u0437\u0430\u043c\u0435\u0442\u0438\u043b \u043d\u0430 \u0441\u043e\u0431\u0435\u0441\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u044f\u0445:<\/p>\n<ol>\n<li>\n<p>\u0421\u043a\u043e\u0440\u0435\u0435 \u0432\u0441\u0435\u0433\u043e \u0442\u043e, \u0447\u0442\u043e \u0432\u044b \u0434\u0435\u043b\u0430\u0435\u0442\u0435 \u043d\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u0441 \u0442\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u0442\u043e\u0447\u043a\u0438 \u0437\u0440\u0435\u043d\u0438\u044f \u043d\u0435 \u043f\u043e\u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u043e\u0439\u0442\u0438 \u0441\u043e\u0431\u0435\u0441\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u0435, \u043f\u043e\u0442\u043e\u043c\u0443 \u043a\u0430\u043a \u0432\u043e\u043f\u0440\u043e\u0441\u044b \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u0438\u0437 \u0441\u043e\u0432\u0441\u0435\u043c \u0443\u0436 \u0440\u0430\u0437\u043d\u044b\u0445 \u043e\u0431\u043b\u0430\u0441\u0442\u0435\u0439 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 iOS. \u0422\u043e \u0435\u0441\u0442\u044c, \u0433\u043e\u0442\u043e\u0432\u0438\u0442\u044c\u0441\u044f \u043f\u0440\u0438\u0434\u0451\u0442\u0441\u044f \u043f\u043e-\u043b\u044e\u0431\u043e\u043c\u0443.<\/p>\n<\/li>\n<li>\n<p>\u0421\u043a\u043e\u0440\u0435\u0435 \u0432\u0441\u0435\u0433\u043e, \u0435\u0441\u043b\u0438 \u0432\u044b \u043d\u0430 \u0441\u043e\u0431\u0435\u0441\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u0438 \u043d\u0430\u0447\u0430\u043b\u0438 \u0441\u043c\u0435\u044f\u0442\u044c\u0441\u044f \u043d\u0430\u0434 \u0447\u0435\u043c-\u0442\u043e \u0432\u043c\u0435\u0441\u0442\u0435 \u0441 \u0438\u043d\u0442\u0435\u0440\u0432\u044c\u044e\u0435\u0440\u043e\u043c, \u0442\u043e \u0432\u0430\u0441 \u0442\u043e\u0447\u043d\u043e \u043d\u0435 \u0432\u043e\u0437\u044c\u043c\u0443\u0442, \u0438\u0431\u043e, &#171;\u043d\u0435 \u0432\u0440\u0435\u043c\u044f \u0443\u043b\u044b\u0431\u0430\u0442\u044c\u0441\u044f&#187;.<\/p>\n<\/li>\n<li>\n<p>\u0415\u0441\u043b\u0438 \u0432\u044b \u0441\u0434\u0435\u043b\u0430\u043b\u0438 \u043e\u0448\u0438\u0431\u043a\u0443 \u0432\u043e \u0432\u0440\u0435\u043c\u044f life coding interview, \u0442\u043e \u0441\u0447\u0438\u0442\u0430\u0439\u0442\u0435, \u0447\u0442\u043e \u0432\u044b \u0437\u0430\u0432\u0430\u043b\u0438\u043b\u0438 \u0438\u043d\u0442\u0435\u0440\u0432\u044c\u044e: <\/p>\n<p>\u041f\u043e\u0447\u0442\u0438 \u0432\u0441\u0435 \u043d\u0430 \u0442\u0440\u0435\u043d\u0438\u043d\u0433\u0430\u0445 \u043f\u043e \u0441\u043e\u0431\u0435\u0441\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u044f\u043c \u0433\u043e\u0432\u043e\u0440\u044f\u0442, \u0447\u0442\u043e \u0435\u0441\u043b\u0438 \u0432\u044b \u043d\u0435 \u0437\u043d\u0430\u0435\u0442\u0435, \u043a\u0430\u043a \u0440\u0435\u0448\u0438\u0442\u044c \u043a\u0430\u043a\u0443\u044e-\u0442\u043e \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0443 \u0438\u043b\u0438 \u043e\u0442\u0432\u0435\u0442\u0438\u0442\u044c \u043d\u0430 \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0442\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0432\u043e\u043f\u0440\u043e\u0441, \u0442\u043e \u044d\u0442\u043e \u043d\u0435 \u0437\u043d\u0430\u0447\u0438\u0442, \u0447\u0442\u043e \u0432\u044b \u043d\u0435 \u043f\u0440\u043e\u0448\u043b\u0438 \u0438\u043d\u0442\u0435\u0440\u0432\u044c\u044e. \u041f\u043e \u0444\u0430\u043a\u0442\u0443 \u044d\u0442\u043e \u0438\u043c\u0435\u043d\u043d\u043e \u044d\u0442\u043e \u0438 \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442. \u0412\u0441\u0435\u0433\u0434\u0430 \u043d\u0430\u0439\u0434\u0451\u0442\u0441\u044f \u043a\u0442\u043e-\u0442\u043e, \u043a\u0442\u043e \u043d\u0430 \u044d\u0442\u0438 \u0432\u043e\u043f\u0440\u043e\u0441\u044b \u043e\u0442\u0432\u0435\u0442\u0438\u0442 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e. \u041e\u043d\u0438 \u044d\u0442\u043e \u043e\u0442\u0440\u0438\u0446\u0430\u044e\u0442, \u043d\u043e \u0447\u0442\u043e \u0435\u0441\u0442\u044c, \u0442\u043e \u0435\u0441\u0442\u044c. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0433\u043e\u0442\u043e\u0432\u044c\u0442\u0435\u0441\u044c \u043b\u0443\u0447\u0448\u0435, \u0431\u043e\u043b\u044c\u0448\u0435, \u0441\u0438\u043b\u044c\u043d\u0435\u0435.<\/p>\n<\/li>\n<\/ol>\n<h3>\u0420\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 \u0441 \u043d\u043e\u0432\u044b\u043c\u0438 \u0432\u043e\u043f\u0440\u043e\u0441\u0430\u043c\u0438<\/h3>\n<p>\u0427\u0442\u043e\u0431\u044b \u043d\u0435 \u0442\u0435\u0440\u044f\u0442\u044c \u043d\u0430\u0432\u044b\u043a \u044f \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0430\u044e \u043f\u0435\u0440\u0438\u043e\u0434\u0438\u0447\u0435\u0441\u043a\u0438 \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u0442\u044c \u0441\u043e\u0431\u0435\u0441\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u044f \u0438 \u0430\u043a\u0442\u0443\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u044e \u0441\u043f\u0438\u0441\u043e\u043a \u0432\u043e\u043f\u0440\u043e\u0441\u043e\u0432 \u0432 \u044d\u0442\u043e\u043c \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438:<\/p>\n<p><a href=\"https:\/\/github.com\/AlanMaxwell\/iOS_interview_questions\/blob\/main\/README.md\" rel=\"noopener noreferrer nofollow\">https:\/\/github.com\/AlanMaxwell\/iOS_interview_questions<\/a><\/p>\n<\/p>\n<\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/726388\/\"> https:\/\/habr.com\/ru\/articles\/726388\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<h2>\u041d\u0435\u0431\u043e\u043b\u044c\u0448\u0430\u044f \u043f\u0440\u0435\u0434\u044b\u0441\u0442\u043e\u0440\u0438\u044f <\/h2>\n<p>\u0414\u043e\u0431\u0440\u043e\u0433\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0441\u0443\u0442\u043e\u043a. \u042f iOS-\u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a (\u0445\u043b\u043e\u043f\u043a\u0438-\u0445\u043b\u043e\u043f\u043a\u0438).<\/p>\n<p>\u0422\u0430\u043a \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u043e\u0441\u044c, \u0447\u0442\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u043b \u044f iOS-\u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u043c \u043d\u0430 \u043e\u0434\u043d\u043e\u043c \u043b\u0435\u0433\u0430\u0441\u0438-\u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u0432 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438-\u0432\u0435\u043d\u0434\u043e\u0440\u0435. \u0412 \u043e\u043a\u0442\u044f\u0431\u0440\u0435 \u043f\u0440\u043e\u0448\u043b\u043e\u0433\u043e \u0433\u043e\u0434\u0430 \u043f\u043e\u044f\u0432\u0438\u043b\u043e\u0441\u044c \u0436\u0435\u043b\u0430\u043d\u0438\u0435 \u0441\u043c\u0435\u043d\u0438\u0442\u044c \u0442\u0435\u043a\u0443\u0449\u0438\u0439 \u043f\u0440\u043e\u0435\u043a\u0442, \u0447\u0442\u043e\u0431\u044b \u043f\u0435\u0440\u0435\u0441\u0442\u0430\u0442\u044c \u0432\u043e\u043b\u043d\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043e \u043b\u0435\u0433\u0430\u0441\u0438 \u0438 \u043d\u0430\u0447\u0430\u0442\u044c \u0440\u0430\u0437\u0432\u0438\u0432\u0430\u0442\u044c\u0441\u044f. <\/p>\n<p>\u041f\u043e\u0433\u043e\u0432\u043e\u0440\u0438\u0432 \u0441 \u043d\u0430\u0447\u0430\u043b\u044c\u0441\u0442\u0432\u043e\u043c, \u043c\u043d\u0435 \u043d\u0430\u0437\u043d\u0430\u0447\u0438\u043b\u0438 \u0432\u0441\u0442\u0440\u0435\u0447\u0443 \u0441 \u043b\u0438\u0434\u043e\u043c iOS, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u0438\u0442\u044c \u043c\u0435\u043d\u044f \u043a \u043f\u0440\u0435\u0434\u0441\u0442\u043e\u044f\u0449\u0438\u043c \u0441\u043e\u0431\u0435\u0441\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u044f\u043c. \u041e\u0434\u043d\u0430\u043a\u043e, \u043f\u043e\u0441\u043b\u0435 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u0432\u043e\u043f\u0440\u043e\u0441\u043e\u0432 \u043e\u0442 \u043b\u0438\u0434\u0430 \u0432\u0435\u0440\u0434\u0438\u043a\u0442 \u0431\u044b\u043b, \u0447\u0442\u043e \u043d\u0435 \u043f\u043e\u0434\u0445\u043e\u0436\u0443 \u043d\u0430 \u0442\u0435\u043a\u0443\u0449\u0438\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u044b. \u041d\u0430 \u0432\u043e\u043f\u0440\u043e\u0441, \u043a\u0430\u043a\u0438\u0435, \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u043a\u0440\u0438\u0442\u0435\u0440\u0438\u0438 \u043e\u0446\u0435\u043d\u0438\u0432\u0430\u043d\u0438\u044f \u044f \u043f\u043e\u043b\u0443\u0447\u0438\u043b \u043e\u0442\u0432\u0435\u0442:<\/p>\n<blockquote>\n<p>&#171;\u0442\u0435\u0431\u0435 \u043d\u0438\u043a\u043e\u0433\u0434\u0430 \u043d\u0438\u043a\u0442\u043e \u043d\u0435 \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0435\u0442? \u0432 \u043d\u0430\u0448\u0435\u043c \u0434\u0435\u043b\u0435 \u0432\u0441\u0435 \u0441\u0430\u043c ?&#187;<\/p>\n<\/blockquote>\n<p>\u0421\u0430\u043c \u0442\u0430\u043a \u0441\u0430\u043c. \u042f \u043d\u0430\u0447\u0430\u043b \u0447\u0438\u0442\u0430\u0442\u044c, \u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u043a\u0443\u0440\u0441\u044b, \u0432\u0438\u0434\u0435\u043e\u0443\u0440\u043e\u043a\u0438 \u0438 \u0430\u043a\u0442\u0438\u0432\u043d\u043e \u043f\u043e\u0434\u0430\u0432\u0430\u0442\u044c\u0441\u044f \u0432 \u0440\u0430\u0437\u043d\u044b\u0435 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438 \u043a\u0430\u043a \u0432 \u0420\u043e\u0441\u0441\u0438\u0438, \u0442\u0430\u043a \u0438 \u0437\u0430 \u0440\u0443\u0431\u0435\u0436\u043e\u043c, \u0447\u0442\u043e\u0431\u044b \u0432\u044b\u044f\u0441\u043d\u0438\u0442\u044c, \u043a\u0430\u043a\u0438\u0435, \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0433\u043e\u0432\u043e\u0440\u044f, \u043a\u0440\u0438\u0442\u0435\u0440\u0438\u0438 \u043f\u0440\u043e\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u044f. \u041f\u043e\u0441\u0442\u0435\u043f\u0435\u043d\u043d\u043e \u0440\u0430\u0437 \u0437\u0430 \u0440\u0430\u0437\u043e\u043c \u0441\u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043b\u0441\u044f \u0441\u043f\u0438\u0441\u043e\u043a \u043d\u0430\u0438\u0431\u043e\u043b\u0435\u0435 \u0447\u0430\u0441\u0442\u043e \u0432\u0441\u0442\u0440\u0435\u0447\u0430\u044e\u0449\u0438\u0445\u0441\u044f \u0432\u043e\u043f\u0440\u043e\u0441\u043e\u0432 \u043d\u0430 \u0441\u043e\u0431\u0435\u0441\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u044f\u0445 iOS-\u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u044f \u0440\u0435\u0448\u0438\u043b \u043e\u043f\u0443\u0431\u043b\u0438\u043a\u043e\u0432\u0430\u0442\u044c \u0437\u0434\u0435\u0441\u044c.<\/p>\n<h2>\u0422\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0432\u043e\u043f\u0440\u043e\u0441\u044b<\/h2>\n<p>\u0422.\u043a. \u0441\u043e\u0431\u0435\u0441\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u044f \u0431\u044b\u043b\u0438 \u0432 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u043c \u043d\u0430 \u0430\u043d\u0433\u043b\u0438\u0439\u0441\u043a\u043e\u043c \u044f\u0437\u044b\u043a\u0435, \u0442\u043e \u0441 \u0432\u0430\u0448\u0435\u0433\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u0435\u043d\u0438\u044f \u043e\u0441\u0442\u0430\u0432\u043b\u044e \u0442\u0443\u0442 \u0438 \u0432\u043e\u043f\u0440\u043e\u0441\u044b \u0438 \u043e\u0442\u0432\u0435\u0442\u044b \u043d\u0430 \u0430\u043d\u0433\u043b\u0438\u0439\u0441\u043a\u043e\u043c. \u041f\u043e\u0435\u0445\u0430\u043b\u0438.<\/p>\n<h3>1. What frameworks you used in your iOS projects?<\/h3>\n<p>You can specify frameworks like: UIKit, SwiftUI, Combine, AVFramework, PushNotification, CallKit, GCD, Core Bluetooth, etc.<\/p>\n<h3>2. How the Optional is implemented in Swift?<\/h3>\n<pre><code class=\"swift\">enum Optional&lt;Wrapped> {     case none     case some(Wrapped) }<\/code><\/pre>\n<h3>3. Is there a difference between .none and nil?<\/h3>\n<p>No<\/p>\n<h3>4. Ways to unwrap optional variables<\/h3>\n<pre><code class=\"swift\">var a:Int? \/\/1 a! \/\/2 if let s = a {     print(s) } \/\/3 if let a {     print(a) } \/\/4 guard let s = a else {     print(s)     return } \/\/5 a ?? 0 \/\/5<\/code><\/pre>\n<h3>5. What&#8217;s difference between reference and value types? What reference and value types you know?<\/h3>\n<p><strong>Value types<\/strong>: structs, enums, arrays, dictionaries, strings<\/p>\n<p><strong>Reference types<\/strong>: classes, closures, NS types (NSString, for example) (because they are classes) <\/p>\n<p><strong>Two differences between value and reference types:<\/strong><\/p>\n<ol>\n<li>\n<p>Value types are stored in Stack and reference types are stored in Heap.<\/p>\n<\/li>\n<li>\n<p>If you assign one object to another for a reference type, you just copy the reference, not value:<\/p>\n<\/li>\n<\/ol>\n<pre><code class=\"swift\">\/\/ Reference type example class C { var data: Int = -1 } var x = C() var y = x\/\/ x is copied to y x.data = 42\/\/ changes the instance referred to by x (and y) println(\"\\(x.data), \\(y.data)\")\/\/ prints \"42, 42\"<\/code><\/pre>\n<p>For value types you will copy the value of the variable.<\/p>\n<h3>6. What&#8217;s difference between Class and Structure?<\/h3>\n<ul>\n<li>\n<p>Structures are value types.<\/p>\n<\/li>\n<li>\n<p>Classes are reference types.<\/p>\n<\/li>\n<li>\n<p>Structures don\u2019t support inheritance.<\/p>\n<\/li>\n<li>\n<p>classes support inheritance.<\/p>\n<\/li>\n<li>\n<p>Structures don\u2019t support de-initializers. ( deinit )<\/p>\n<\/li>\n<li>\n<p>Classes support de-initializers.<\/p>\n<\/li>\n<li>\n<p>Structures don\u2019t follow Reference Counting (<em>look at the question 19 about ARC)<\/em>.<\/p>\n<\/li>\n<li>\n<p>Classes follow Reference Counting.<\/p>\n<\/li>\n<li>\n<p>Mutating Keyword is needed to modify the property values in Structure\u2019s instance methods.<\/p>\n<\/li>\n<li>\n<p>No need of mutating keyword to modify the class variable\u2019s value.<\/p>\n<\/li>\n<\/ul>\n<h3>7. Do you know what copy-on-write means?<\/h3>\n<p>If you assign one array to another (not only array, there are other objects), then the second object will refer to the first array address until the second array is not changed.<\/p>\n<pre><code class=\"swift\">func addressOf(_ o: UnsafeRawPointer) -> String {     let addr = unsafeBitCast(o, to: Int.self)     return String(format: \"%p\", addr) } \/\/our array var array = [1, 2, 3, 4, 5] addressOf(array) \/\/ 0x600002e30ac0 \/\/here we assign one array to another var array2 = array \/\/look - the address of the second array is the same addressOf(array2) \/\/ 0x600002e30ac0 \/\/here we change the second array  array2.append(6) \/\/look again - address has changed addressOf(array2) \/\/ 0x6000026119f0<\/code><\/pre>\n<h3>8. Do you know what are SOLID principles?<\/h3>\n<p>SOLID is abbreviation.<\/p>\n<h4>S \u2013 single responsibility principle.<\/h4>\n<p>It\u2019s when a class has just one purpose. A class shouldn\u2019t contain functions that could be moved to other classes<\/p>\n<h4>O \u2013 open\/closed principle (OCP)<\/h4>\n<p>A class should be opened for extension, but closed for changes.<\/p>\n<p>Open closed principle allows to <strong>avoid this kind of code<\/strong>:<\/p>\n<pre><code class=\"swift\">protocol SomeProtocol { }  class A:SomeProtocol {     func printClassAName() {         print(\"I'm A\")     } }  class B:SomeProtocol {     func printClassBName() {         print(\"I'm B\")     } }  class Caller {     func printClassName(obj:SomeProtocol){       \/\/\/\/TO AVOID THIS KIND OF CODE!!!!!         if let unwrappeObj = obj as? A {             obj.printClassAName()         }         else if let unwrappeObj = obj as? B {             obj.printClassBName()         }     } }<\/code><\/pre>\n<p>It should be changed like that to avoid changes in Caller class in the future:<\/p>\n<pre><code class=\"swift\">protocol SomeProtocol {     func printClassName() }  class A:SomeProtocol {     func printClassName() {         print(\"I'm A\")     } }  class B:SomeProtocol{     func printClassName() {         print(\"I'm B\")     } }  class Caller {     func doSomething(obj:SomeProtocol){         print(obj.printClassName())     } }<\/code><\/pre>\n<p>This principle is similar with D (dependency inversion principle), but OCP is more general. The DIP is an extension of the OCP.<\/p>\n<h4>L \u2013 Liskov principle.<\/h4>\n<p>In simple words this principle says that you need to have a possibility to use a parent and a child classes without any difference.<\/p>\n<pre><code class=\"swift\">class A: SomeProtocol { }  class B: SomeProtocol { }  let a = A() let b = B() var a:[SomeProtocol] = [a, b]<\/code><\/pre>\n<h4>I \u2013 interface segregation.<\/h4>\n<p>Classes <strong>SHOULDN&#8217;T<\/strong> implement protocol methods they don\u2019t use. If we noticed this situation, just move these methods to a separate protocol.<\/p>\n<h4>D \u2013 dependency inversion.<\/h4>\n<p>It means that a class shouldn\u2019t depend on low-level modules \u2013 they both should depend on an Abstraction<\/p>\n<p>For example:<\/p>\n<pre><code class=\"swift\">class FileSystemManager {   func save(string: String) {     \/\/ Open a file     \/\/ Save the string in this file     \/\/ Close the file   } }  class Handler {     let fileManager = FilesystemManager()     func handle(string: String) {         fileManager.save(string: string)     } }<\/code><\/pre>\n<p>If in the future we\u2019ll need to add other methods for saving data (data base, for example), we should inherit both <code>FilesystemManager<\/code> and this new data base interactor class from some Storage protocol and use it instead of <strong>FilesystemManager<\/strong> and other possible data saving ways:<\/p>\n<pre><code class=\"swift\">class FileSystemManager:Storage {     func save(string: String) {         \/\/ Open a file         \/\/ Save the string in this file         \/\/ Close the file     } }  class DataBaseManager:Storage {     func save(string: String) {         \/\/ Open DB         \/\/ Save the data         \/\/ Close DB     } }  class Handler {     let storage:Storage     func handle(string: String) {         storage.save(string: string)     } }<\/code><\/pre>\n<p>This principle is similar with OCP is more general. The DIP is an extension of the OCP.<\/p>\n<p>Difference is that OCP is for similar functions, but DIP deals with the same input data<\/p>\n<h3>9. What is Singleton?<\/h3>\n<p>The main point of Singleton is to ensure that we initialized something only once and this &#171;something&#187; should be available from everywhere. For example, <code>UIApplication.shared<\/code><\/p>\n<p><strong>P.S.:<\/strong> ServiceLocator \u2013 is a singleton with an array of some services<\/p>\n<h3>10. How are you doing your code reviews?<\/h3>\n<p>The best practice said that the code review should depend on CI\/CD tests, a style guide, SOLID, and some linter (a syntax checker)<\/p>\n<h3>11. Application lifecycle<\/h3>\n<p>Use this:<\/p>\n<figure class=\"full-width\">\n<div><figcaption>Taken from Apple documentation<\/figcaption><\/div>\n<\/figure>\n<h3>12. ViewController lifecycle<\/h3>\n<ul>\n<li>\n<p><strong>ViewDidLoad<\/strong>\u00a0&#8212; Called when you create the class and load from xib. Great for initial setup and one-time-only work.<\/p>\n<\/li>\n<li>\n<p><strong>ViewWillAppear<\/strong>\u00a0&#8212; Called right before your view appears, good for hiding\/showing fields or any operations that you want to happen every time before the view is visible. Because you might be going back and forth between views, this will be called every time your view is about to appear on the screen.<\/p>\n<\/li>\n<li>\n<p><strong>ViewDidAppear<\/strong>\u00a0&#8212; Called after the view appears &#8212; great place to start an animations or the loading of external data from an API.<\/p>\n<\/li>\n<li>\n<p><strong>ViewWillDisappear\/DidDisappear<\/strong>\u00a0&#8212; Same idea as\u00a0ViewWillAppear\/ViewDidAppear.<\/p>\n<\/li>\n<li>\n<p><strong>ViewDidUnload\/ViewDidDispose<\/strong>\u00a0&#8212; In Objective-C, this is where you do your clean-up and release of stuff, but this is handled automatically so not much you really need to do here<\/p>\n<\/li>\n<\/ul>\n<figure class=\"full-width\"><\/figure>\n<h3>P.S.: Can you say what ViewController lifecycle methods are calling when you started to segue from a view (A) to another view (B), but haven&#8217;t finish it?<\/h3>\n<h3>13. What architecture patterns you used?<\/h3>\n<p>Better to mention MVC, MVVM, VIPER, Clean Architecture. I recommend to implement test samples for each of these patterns.<\/p>\n<h3>14. What is VIPER?<\/h3>\n<p>VIPER \u2013 is an architecture pattern with these parts:<\/p>\n<ul>\n<li>\n<p>R \u2013 router \u2013 an entry point<\/p>\n<\/li>\n<li>\n<p>E \u2013 entity \u2013 model (like in MVC, for example)<\/p>\n<\/li>\n<li>\n<p>P \u2013 presenter \u2013 holds the reference to interactor, to a router and to a view<\/p>\n<\/li>\n<li>\n<p>Presenter uses data, received using fetching data functions from Interactor to update View.<\/p>\n<\/li>\n<li>\n<p>V \u2013 view. But with additional protocol with updating functions to call. For example, if we want to show an alert in a view, then we should ask the presenter to do that<\/p>\n<\/li>\n<li>\n<p>I \u2013 Interactor handles business logic and data retrieval<\/p>\n<\/li>\n<\/ul>\n<h3>15. What is Clean Architecture?<\/h3>\n<p>I used this scheme<\/p>\n<figure class=\"full-width\">\n<div><figcaption>Taken from here: https:\/\/medium.com\/@info.vikaasyadav\/flutter-clean-architecture-with-riverpod-7807e54228c4<\/figcaption><\/div>\n<\/figure>\n<h3>16. What is MVVM?<\/h3>\n<p>MVVM &#8212; Model View ViewModel<\/p>\n<ul>\n<li>\n<p><strong>Model<\/strong>\u00a0&#8212; is the data layer.<\/p>\n<\/li>\n<li>\n<p><strong>View<\/strong>\u00a0&#8212; is a view.<\/p>\n<\/li>\n<li>\n<p><strong>ViewModel<\/strong>\u00a0&#8212; contains presentation logic (process data from Model to View, reacts on actions from the View and transfers these reactions to Model).<\/p>\n<\/li>\n<\/ul>\n<p>In the code tree there should be three different directories: Models, Views, ViewModels. Each of your classes should be represented separately there.<\/p>\n<p>Sometimes it&#8217;s wise to create an additional directory called Services, in which you can put your business logic.<\/p>\n<h4>P.S.: What is MVVM-C?<\/h4>\n<h3>17. Who is an owner of data in MVVM?<\/h3>\n<p>Model is the data itself.<\/p>\n<h3>18. MVC and MVVM differences:<\/h3>\n<p>The main difference between MVC and MVVM is the role of the controller and view model. In MVC, the Controller handles user input and updates the Model and View. In MVVM the ViewModel handles user input and updates the Model and View, and the view is responsible for displaying the data.<\/p>\n<h3>19. What NS prefix means in some Swift and Objective-C classes?<\/h3>\n<p>It means next step (the name of one company)<\/p>\n<h3>20. How memory<\/h><\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-405628","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/405628","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=405628"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/405628\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=405628"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=405628"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=405628"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}