├── Images ├── abstract_classes.png ├── abstraction.png ├── algo_1.png ├── algo_2.png ├── algo_3.png ├── apns.png ├── app_states.png ├── app_states_2.png ├── app_states_3.png ├── array.png ├── array_performance.png ├── autolayout.png ├── autolayout_frame1.png ├── autolayout_frame2.png ├── awakefromnib.png ├── big_o_complexity.png ├── binary.png ├── binary_search.gif ├── bit_example.png ├── bit_math_1.png ├── bit_math_2.png ├── block_capturing.png ├── blocks.png ├── blocks_structure.png ├── bubble_sort.gif ├── c_array.jpg ├── c_types.png ├── cf.png ├── cfnetwork.png ├── circular_linked_list.png ├── cluster.png ├── cluster_description.png ├── communication_patterns.png ├── complexity.png ├── const_pointer.png ├── core_data_faulting.png ├── core_data_stack.jpg ├── core_text.png ├── data_structures_kinds1.png ├── data_structures_kinds2.png ├── deadlock.png ├── delegation.png ├── dequeue.png ├── dictionary_performance.png ├── doubly_linked_list.png ├── file_system.png ├── flags1.png ├── flags2.png ├── frame.png ├── gcd_functions_1.png ├── gcd_functions_2.png ├── gcd_queues_scheme.png ├── hash_table.png ├── hexadecimal.png ├── html_parsing.png ├── initializers.png ├── insertion_sort.gif ├── intrinsic.png ├── ios_guide_logo.png ├── isa.png ├── kvo.png ├── left_bitwise.png ├── lifecycle.png ├── linear_search.gif ├── lock_performance.png ├── memory_management.png ├── mutex.png ├── mvc-mvp-mvvm.png ├── nsurlconnection.png ├── nsurlsession.png ├── numeral_system.png ├── objc_collections.png ├── or_example.png ├── pointerarray.png ├── pointers.png ├── priority_inversion.png ├── quick_sort.gif ├── race_condition.png ├── red_black_tree.png ├── red_black_tree_statistics.png ├── resolutions.png ├── responder_chain.png ├── responder_chain_in_action.png ├── retain_cycle.png ├── rotate-view.jpg ├── runloop.jpg ├── selection_sort.gif ├── singly_linked_list.png ├── stack.png ├── storyboards.png ├── tableview1.png ├── tableview2.png ├── tree.png ├── uikit.png ├── uiview_frame.png ├── uiviewcontroller.png ├── view_hierarchy.png └── viper.png ├── LICENSE.md ├── Main ├── 10_memory_management.md ├── 11_runtime.md ├── 12_multithreading_concurrency.md ├── 13_networking.md ├── 14_data.md ├── 15_blocks.md ├── 16_autolayout.md ├── 17_testing.md ├── 18_swift.md ├── 19_general_questions.md ├── 1_basics.md ├── 20_tasks.md ├── 21_to_do.md ├── 2_data_structures.md ├── 3_algorithms.md ├── 4_objectivec_collections.md ├── 5_c_language.md ├── 6_oop.md ├── 7_design_patterns.md ├── 8_ios.md └── 9_objectivec.md └── README.md /Images/abstract_classes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/abstract_classes.png -------------------------------------------------------------------------------- /Images/abstraction.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/abstraction.png -------------------------------------------------------------------------------- /Images/algo_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/algo_1.png -------------------------------------------------------------------------------- /Images/algo_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/algo_2.png -------------------------------------------------------------------------------- /Images/algo_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/algo_3.png -------------------------------------------------------------------------------- /Images/apns.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/apns.png -------------------------------------------------------------------------------- /Images/app_states.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/app_states.png -------------------------------------------------------------------------------- /Images/app_states_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/app_states_2.png -------------------------------------------------------------------------------- /Images/app_states_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/app_states_3.png -------------------------------------------------------------------------------- /Images/array.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/array.png -------------------------------------------------------------------------------- /Images/array_performance.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/array_performance.png -------------------------------------------------------------------------------- /Images/autolayout.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/autolayout.png -------------------------------------------------------------------------------- /Images/autolayout_frame1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/autolayout_frame1.png -------------------------------------------------------------------------------- /Images/autolayout_frame2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/autolayout_frame2.png -------------------------------------------------------------------------------- /Images/awakefromnib.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/awakefromnib.png -------------------------------------------------------------------------------- /Images/big_o_complexity.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/big_o_complexity.png -------------------------------------------------------------------------------- /Images/binary.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/binary.png -------------------------------------------------------------------------------- /Images/binary_search.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/binary_search.gif -------------------------------------------------------------------------------- /Images/bit_example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/bit_example.png -------------------------------------------------------------------------------- /Images/bit_math_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/bit_math_1.png -------------------------------------------------------------------------------- /Images/bit_math_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/bit_math_2.png -------------------------------------------------------------------------------- /Images/block_capturing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/block_capturing.png -------------------------------------------------------------------------------- /Images/blocks.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/blocks.png -------------------------------------------------------------------------------- /Images/blocks_structure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/blocks_structure.png -------------------------------------------------------------------------------- /Images/bubble_sort.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/bubble_sort.gif -------------------------------------------------------------------------------- /Images/c_array.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/c_array.jpg -------------------------------------------------------------------------------- /Images/c_types.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/c_types.png -------------------------------------------------------------------------------- /Images/cf.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/cf.png -------------------------------------------------------------------------------- /Images/cfnetwork.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/cfnetwork.png -------------------------------------------------------------------------------- /Images/circular_linked_list.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/circular_linked_list.png -------------------------------------------------------------------------------- /Images/cluster.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/cluster.png -------------------------------------------------------------------------------- /Images/cluster_description.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/cluster_description.png -------------------------------------------------------------------------------- /Images/communication_patterns.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/communication_patterns.png -------------------------------------------------------------------------------- /Images/complexity.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/complexity.png -------------------------------------------------------------------------------- /Images/const_pointer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/const_pointer.png -------------------------------------------------------------------------------- /Images/core_data_faulting.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/core_data_faulting.png -------------------------------------------------------------------------------- /Images/core_data_stack.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/core_data_stack.jpg -------------------------------------------------------------------------------- /Images/core_text.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/core_text.png -------------------------------------------------------------------------------- /Images/data_structures_kinds1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/data_structures_kinds1.png -------------------------------------------------------------------------------- /Images/data_structures_kinds2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/data_structures_kinds2.png -------------------------------------------------------------------------------- /Images/deadlock.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/deadlock.png -------------------------------------------------------------------------------- /Images/delegation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/delegation.png -------------------------------------------------------------------------------- /Images/dequeue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/dequeue.png -------------------------------------------------------------------------------- /Images/dictionary_performance.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/dictionary_performance.png -------------------------------------------------------------------------------- /Images/doubly_linked_list.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/doubly_linked_list.png -------------------------------------------------------------------------------- /Images/file_system.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/file_system.png -------------------------------------------------------------------------------- /Images/flags1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/flags1.png -------------------------------------------------------------------------------- /Images/flags2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/flags2.png -------------------------------------------------------------------------------- /Images/frame.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/frame.png -------------------------------------------------------------------------------- /Images/gcd_functions_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/gcd_functions_1.png -------------------------------------------------------------------------------- /Images/gcd_functions_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/gcd_functions_2.png -------------------------------------------------------------------------------- /Images/gcd_queues_scheme.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/gcd_queues_scheme.png -------------------------------------------------------------------------------- /Images/hash_table.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/hash_table.png -------------------------------------------------------------------------------- /Images/hexadecimal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/hexadecimal.png -------------------------------------------------------------------------------- /Images/html_parsing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/html_parsing.png -------------------------------------------------------------------------------- /Images/initializers.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/initializers.png -------------------------------------------------------------------------------- /Images/insertion_sort.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/insertion_sort.gif -------------------------------------------------------------------------------- /Images/intrinsic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/intrinsic.png -------------------------------------------------------------------------------- /Images/ios_guide_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/ios_guide_logo.png -------------------------------------------------------------------------------- /Images/isa.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/isa.png -------------------------------------------------------------------------------- /Images/kvo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/kvo.png -------------------------------------------------------------------------------- /Images/left_bitwise.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/left_bitwise.png -------------------------------------------------------------------------------- /Images/lifecycle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/lifecycle.png -------------------------------------------------------------------------------- /Images/linear_search.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/linear_search.gif -------------------------------------------------------------------------------- /Images/lock_performance.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/lock_performance.png -------------------------------------------------------------------------------- /Images/memory_management.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/memory_management.png -------------------------------------------------------------------------------- /Images/mutex.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/mutex.png -------------------------------------------------------------------------------- /Images/mvc-mvp-mvvm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/mvc-mvp-mvvm.png -------------------------------------------------------------------------------- /Images/nsurlconnection.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/nsurlconnection.png -------------------------------------------------------------------------------- /Images/nsurlsession.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/nsurlsession.png -------------------------------------------------------------------------------- /Images/numeral_system.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/numeral_system.png -------------------------------------------------------------------------------- /Images/objc_collections.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/objc_collections.png -------------------------------------------------------------------------------- /Images/or_example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/or_example.png -------------------------------------------------------------------------------- /Images/pointerarray.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/pointerarray.png -------------------------------------------------------------------------------- /Images/pointers.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/pointers.png -------------------------------------------------------------------------------- /Images/priority_inversion.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/priority_inversion.png -------------------------------------------------------------------------------- /Images/quick_sort.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/quick_sort.gif -------------------------------------------------------------------------------- /Images/race_condition.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/race_condition.png -------------------------------------------------------------------------------- /Images/red_black_tree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/red_black_tree.png -------------------------------------------------------------------------------- /Images/red_black_tree_statistics.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/red_black_tree_statistics.png -------------------------------------------------------------------------------- /Images/resolutions.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/resolutions.png -------------------------------------------------------------------------------- /Images/responder_chain.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/responder_chain.png -------------------------------------------------------------------------------- /Images/responder_chain_in_action.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/responder_chain_in_action.png -------------------------------------------------------------------------------- /Images/retain_cycle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/retain_cycle.png -------------------------------------------------------------------------------- /Images/rotate-view.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/rotate-view.jpg -------------------------------------------------------------------------------- /Images/runloop.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/runloop.jpg -------------------------------------------------------------------------------- /Images/selection_sort.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/selection_sort.gif -------------------------------------------------------------------------------- /Images/singly_linked_list.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/singly_linked_list.png -------------------------------------------------------------------------------- /Images/stack.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/stack.png -------------------------------------------------------------------------------- /Images/storyboards.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/storyboards.png -------------------------------------------------------------------------------- /Images/tableview1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/tableview1.png -------------------------------------------------------------------------------- /Images/tableview2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/tableview2.png -------------------------------------------------------------------------------- /Images/tree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/tree.png -------------------------------------------------------------------------------- /Images/uikit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/uikit.png -------------------------------------------------------------------------------- /Images/uiview_frame.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/uiview_frame.png -------------------------------------------------------------------------------- /Images/uiviewcontroller.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/uiviewcontroller.png -------------------------------------------------------------------------------- /Images/view_hierarchy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/view_hierarchy.png -------------------------------------------------------------------------------- /Images/viper.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EgnGron/ios-guide/e09d3b3bb623d70287ae02357d5ef63f2eae363a/Images/viper.png -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Alex 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 | -------------------------------------------------------------------------------- /Main/11_runtime.md: -------------------------------------------------------------------------------- 1 | - [Runtime](#runtime) 2 | - [Что такое указатель isa? Для чего он нужен?](#isa) 3 | - [Что происходит с методом после того, как он не нашелся в объекте класса, которому его вызвали?](#метод-объекта) 4 | - [Что такое классы в Objective-C, структура классов?](#классы) 5 | - [Чем объект Objective-c отличается от структуры С, что такое структура в C?](#объект) 6 | - [Вопрос о методах isKindOfClass, isMemberOfClass](#вisKindOfClass) 7 | - [Тип id](#тип-id) 8 | - [Dynamic method resolution](#dynamic-method-resolution) 9 | 10 | 11 | # Runtime 12 | The heart of this power is the Objective-C runtime, provided by libobjc. The Objective-C runtime is a collection of functions that provides the dynamic features of Objective-C. It includes such core functions 13 | As `objc_msgSend`, which is called every time you use the `[object message];` syntax. It also includes functions to allow you to inspect and modify the class hierarchy at runtime, including creating new classes and methods. Библиотека времени выполнения. Objective-C is a runtime-oriented language. Now the question that arises is, what is a runtime language? A runtime language is a language that decides what to implement in a function and other decisions during the runtime of the applications. Is Objective-C a runtime language? NO. It is a runtime-oriented language, which means that whenever it is possible, it defers decisions from compile and link time to the time when the code in the application is actually being executed. Функции и структуры Runtime-библиотеки определены в нескольких заголовочных файлах: `NSObjCRuntime.h`, `objc.h`, `runtime.h` и `message.h`. 14 | Система вызова методов в Objective-C реализована через посылку сообщений объекту. Каждый вызов метода транслируется в соответствующий вызов функции `objc_msgSend`: 15 | ```objectivec 16 | // Вызов метода 17 | [array insertObject:foo atIndex:1]; 18 | // Соответствующий ему вызов Runtime-функции 19 | objc_msgSend(array, @selector(insertObject:atIndex:), foo, 1); 20 | ``` 21 | Вызов `objc_msgSend` инициирует процесс поиска реализации метода, соответствующего селектору, переданному в функцию. Реализация метода ищется в так называемой таблице диспетчеризации класса. Поскольку этот процесс может быть достаточно продолжительным, с каждым классом ассоциирован кеш методов. После первого вызова любого метода, результат поиска его реализации будет закеширован в классе. Если реализация метода не найдена в самом классе, дальше поиск продолжается вверх по иерархии наследования — в суперклассах данного класса. Если же и при поиске по иерархии результат не достигнут, в дело вступает механизм динамического поиска — вызывается один из специальных методов: `resolveInstanceMethod` или `resolveClassMethod` (динамическое переопределение методов). 22 | 23 | 24 | ## Что такое указатель isa? Для чего он нужен? 25 | Каждый объект Objective-C содержит в себе атрибут `isa` - указатель на class object для данного объекта. class object автоматически создается компилятором и существует как один экземпляр, на который через `isa` ссылаются все экземпляры данного класса. 26 | First there is a pointer to your class definition. Then each of your superclasses’ ivars (instance variables) are laid out as struct properties, and then your class’s ivars are laid out as struct properties. This structure is called `objc_object`, and a pointer to it is called `id`: 27 | ```objectivec 28 | typedef struct objc_object { 29 | Class isa; 30 | } *id; 31 | ``` 32 | 33 | 34 | 35 | 36 | ## Что происходит с методом после того, как он не нашелся в объекте класса, которому его вызвали? 37 | 38 | _Форвардинг_ 39 | 40 | So if you pass a `doSomething` message to an object `[object doSomething]` 41 | 1. It will first check whether it has a `doSomething` method 42 | 2. Then it will check its superclasses 43 | 3. It'll try dynamic method resolution (`resolveInstanceMethod` for instance) 44 | see [Dynamic method resolution](#dynamic-method-resolution) 45 | 4. It'll look for a forwarding target (`forwardingTargetForSelector:`) 46 | 47 | > This method gives an object a chance to redirect an unknown message sent to it before the much more expensive forwardInvocation: machinery takes over. This is useful when you simply want to redirect messages to another object and can be an order of magnitude faster than regular forwarding. It is not useful where the goal of the forwarding is to capture the NSInvocation, or manipulate the arguments or return value during the forwarding. 48 | 49 | 5. Finally, if everything else fails, it'll create an invocation (using `methodSignatureForSelector:` and put to `forwardInvocation:`. By default, `forwardInvocation:` just calls doesNotRecognizeSelector: which crashes you on iOS (or terminates the current thread on OS X). But you can override it to do something else (like they have here). 50 | 51 | The `NSInvocation` object encapsulates the original message and the arguments that were passed with it. You can implement a `forwardInvocation:` method to give a default response to the message, or to avoid the error in some other way. As its name implies, `forwardInvocation:` is commonly used to forward the message to another object. 52 | 53 | 54 | ## Что такое классы в Objective-C, структура классов? 55 | ```objectivec 56 | #import 57 | /* 58 | * Class Template 59 | */ 60 | struct objc_class { 61 | struct objc_class *isa; 62 | struct objc_class *super_class; 63 | const char *name; 64 | long version; 65 | long info; 66 | long instance_size; 67 | struct objc_ivar_list *ivars; 68 | 69 | #if defined(Release3CompatibilityBuild) 70 | struct objc_method_list *methods; 71 | #else 72 | struct objc_method_list **methodLists; 73 | #endif 74 | 75 | struct objc_cache *cache; 76 | struct objc_protocol_list *protocols; 77 | }; 78 | ``` 79 | 80 | 81 | ## Чем объект Objective-c отличается от структуры С, что такое структура в C? 82 | Структура – специальный тип данных языка C, который содержит в себе другие типы данных в одном блоке и группрует их под одним именем. 83 | ```c 84 | struct point { 85 | int x; 86 | int у; 87 | }; 88 | ``` 89 | Объекты в ObjС представляют собой структуры cо своими данными и в которых имеется ссылка isa на объект класса. 90 | 91 | 92 | ## Вопрос о методах isKindOfClass, isMemberOfClass 93 | Протокол ``, методы тестирования наследования: 94 | 95 | 1. `isKindOfClass:` 96 | 2. `isMemberOfClass:` 97 | 3. `respondsToSelector:` 98 | 4. `conformsToProtocol:` 99 | 100 | `isKindOfClass:` 101 | 102 | Возвращает логическое значение, указывающее, является ли приемник экземпляром заданного класса или экземпляром любого класса, который наследует от этого класса (обязательный): 103 | ```objectivec 104 | `- (BOOL)isKindOfClass:(Class)aClass` 105 | ``` 106 | Аргументы: 107 | 108 | `aClass` Объект класс, представляющий Objective-C класс для тестирования. 109 | 110 | Возвращаемое значение: 111 | 112 | `YES`, если получатель является экземпляром `aClass` или экземпляром любого класса, который наследует от `aClass`, в противном случае `NO`. 113 | 114 | `isMemberOfClass:` 115 | 116 | Возвращает логическое значение, указывающее, является ли приемник экземпляром заданного класса (обязательный). 117 | ```objectivec 118 | - (BOOL)isMemberOfClass:(Class)aClass 119 | ``` 120 | Аргументы: 121 | 122 | `aClass` Объект класс, представляющий Objective-C класс для тестирования. 123 | 124 | Возвращаемое значение: 125 | 126 | `YES`, если получатель является экземпляром `aClass`, в противном случае `NO`. 127 | 128 | `respondsToSelector:` 129 | 130 | Возвращает логическое значение, указывающее, что приемник реализует или наследует метод, который может реагировать на указанное сообщение. (обязательный). 131 | ```objectivec 132 | - (BOOL)respondsToSelector:(SEL)aSelector 133 | ``` 134 | Аргументы: 135 | 136 | `aSelector` Селектор, который идентифицирует сообщение. 137 | 138 | Возвращаемое значение: 139 | 140 | `YES`, если приемник реализует или наследует метод, который может реагировать на `aSelector`, в противном случае `NO`. 141 | 142 | `conformsToProtocol:` 143 | 144 | Возвращает логическое значение, указывающее, что приемник соответствует заданному протоколу. (обязательный). 145 | ```objectivec 146 | - (BOOL)conformsToProtocol:(Protocol *)aProtocol 147 | ``` 148 | Аргументы: 149 | 150 | `aProtocol` Объект протокола, который представляет определенный протокол. 151 | 152 | Возвращаемое значение: 153 | 154 | `YES`, если приемник поддерживает `aProtocol`, в противном случае `NO`. 155 | 156 | Рассмотрение: 157 | 158 | Этот метод работает идентично методу класса `conformsToProtocol`: объявленному в `NSObject`. Это сделано для удобства, так чтобы вам не нужно было получать объект класса, чтобы узнать, может ли экземпляр ответить на заданный набор сообщений. 159 | 160 | 161 | ## Тип id 162 | 163 | __id__ 164 | 165 | ```c 166 | typedef struct objc_class *Class; 167 | typedef struct objc_object { 168 | Class isa; 169 | } *id; 170 | ``` 171 | `id` is a pointer to any Objective-C object (`objc_object`). It is not just a `void` pointer and you should not treat it as so. It references an object that should have a valid `isa` pointer. The values that can be stored in `id` are also not just limited to `NSObject` and its descendants, which starts to make sense of the existence of the `NSObject` protocol as well as the `NSProxy` class which does not even inherit from `NSObject`. The compiler will allow you to assign an object referenced by type `id` to any object type, assign any object type to `id`, as well as send it any message (that the compiler has seen) without warning. 172 | 173 | Thus “id” type is polymorphic. This is very powerful as it doesn’t require a cast to use such a value: 174 | ```objectivec 175 | id data = ...; 176 | NSString *host = [data host]; // assume NSURL 177 | ``` 178 | Sure enough `id` usage can lead to bugs, because the availability of the method is determined at runtime. This is called “dynamic (or late) binding”. Nevertheless if used carefully it is very useful and lets you write parts of the code faster as if using a scripting language. 179 | 180 | Unfortunately this doesn’t work with property syntax: 181 | ```objectivec 182 | id data = ...; 183 | NSString *host = data.host; // error: "Property 'host' not found" 184 | data.host = @"dobegin.com"; // same error 185 | ``` 186 | 187 | __instancetype__ 188 | 189 | > Use the `instancetype` keyword as the return type of methods that return an instance of the class they are called on (or a subclass of that class). These methods include `alloc`, `init`, and class factory methods. Using `instancetype` instead of `id` in appropriate places improves type safety in your Objective-C code. 190 | 191 | * Что случится во время компиляции если мы посылаем сообщение объекту типа id? 192 | 193 | With a variable typed `id`, you can send it any known message and the compiler will not complain. With a variable typed `NSObject *`, you can only send it messages declared by `NSObject` (not methods of any subclass) or else it will generate a warning. 194 | 195 | * Что произойдет здесь? 196 | ```objectivec 197 | NSString *s = [NSNumber numberWithInt:3]; 198 | int i = [s intValue]; 199 | ``` 200 | Переменная типа `id` фактически является указателем на произвольный объект. Для обозначения нулевого указателя на объект используется константа `nil` (= `NULL`). При этом вместо `id` можно использовать и более привычное обозначение с явным указанием класса. В частности последнее позволяет компилятору осуществлять некоторую проверку поддержки сообщения объектами — если компилятор из типа переменной не может сделать вывод о поддержке объектом данного сообщения, то он выдаст предупреждение. Тем самым язык поддерживает проверку типов, но в нестрогой форме (то есть найденные несоответствия возвращаются как предупреждения, а не ошибки). 201 | ```objectivec 202 | MyArray *array = [MyArray arrayWithObjects:@(1), @(2), nil]; 203 | ``` 204 | Теперь вы видите, почему возвращаемый тип `arrayWithObjects:` должен быть `id`. Если бы это был `(NSArray *)`, то подклассы потребует, чтобы они были приведены к необходимому классу. 205 | 206 | * В чем разница между `void` и `void *`? 207 | 208 | The `void` type, in several programming languages derived from C and Algol68, is the type for the result of a function that returns normally, but does not provide a result value to its caller. Usually such functions are called for their side effects, such as performing some task or writing to their output parameters. 209 | C and C++ also support the pointer to `void` type (specified as `void *`), but this is an unrelated notion. Variables of this type are pointers to data of an unspecified type, so in this context (but not the others) `void *` acts roughly like a universal or top type. A program can probably convert a pointer to any type of data (except a function pointer) to a pointer to `void` and back to the original type without losing information, which makes these pointers useful for polymorphic functions. The C language standard does not guarantee that the different pointer types have the same size. 210 | 211 | In C and C++ 212 | 213 | A function with `void` result type ends either by reaching the end of the function or by executing a return statement with no returned value. The `void` type may also appear as the sole argument of a function prototype to indicate that the function takes no arguments. Note that despite the name, in all of these situations, the `void` type serves as a unit type, not as a zero or bottom type (which is sometimes confusingly is also called the "void type"), even though unlike a real unit type which is a singleton, the `void` type lacks a way to represent it's a value and the language does not provide any way to declare an object or represent a value with type `void`. 214 | 215 | * Можно ли создать структуру и привести к id? 216 | 217 | `NSValue` 218 | 219 | > A simple container for a single C or Objective-C data item. An `NSValue` object can hold any of the scalar types such as `int`, `float`, and `char`, as well as pointers, structures, and object `id` references. Use this class to work with such data types in collections (such as `NSArray` and `NSSet`), Key-value coding, and other APIs that require Objective-C objects. `NSValue` objects are always immutable. 220 | 221 | ```objectivec 222 | [NSValue valueWithBytes:&struct objCType:@encode(MyStruct)]; 223 | ``` 224 | And to get the value back out: 225 | ```objectivec 226 | MyStruct struct; 227 | [value getValue:&struct]; 228 | ``` 229 | 230 | 231 | ## Dynamic method resolution 232 | 233 | There are situations where you might want to provide an implementation of a method dynamically. For example, the Objective-C declared properties feature includes the `@dynamic` directive, which tells the compiler that the methods associated with the property will be provided dynamically. You can implement the methods `resolveInstanceMethod:` and `resolveClassMethod:` to dynamically provide an implementation for a given selector for an instance and class method respectively. 234 | 235 | An Objective-C method is simply a C function that take at least two arguments — `self` and `_cmd`. You can add a function to a class as a method using the function `class_addMethod`. Therefore, given the following function: 236 | ```c 237 | void dynamicMethodIMP(id self, SEL _cmd) { 238 | // implementation .... 239 | } 240 | ``` 241 | you can dynamically add it to a class as a method (called `resolveThisMethodDynamically`) using `resolveInstanceMethod:` like this: 242 | ```objectivec 243 | @implementation MyClass 244 | + (BOOL)resolveInstanceMethod:(SEL)aSEL { 245 | if (aSEL == @selector(resolveThisMethodDynamically)) { 246 | class_addMethod([self class], aSEL, (IMP) dynamicMethodIMP, "v@:"); 247 | return YES; 248 | } 249 | return [super resolveInstanceMethod:aSEL]; 250 | } 251 | @end 252 | ``` 253 | A class has the opportunity to dynamically resolve a method before the forwarding mechanism kicks in. If `respondsToSelector:` or `instancesRespondToSelector:` is invoked, the dynamic method resolver is given the opportunity to provide an `IMP` for the selector first. If you implement `resolveInstanceMethod:` but want particular selectors to actually be forwarded via the forwarding mechanism, you return `NO` for those selectors. 254 | 255 | __Dynamic Loading__ 256 | 257 | An Objective-C program can load and link new classes and categories while it’s running. The new code is incorporated into the program and treated identically to classes and categories loaded at the start. Dynamic loading can be used to do a lot of different things. For example, the various modules in the System Preferences application are dynamically loaded. In the Cocoa environment, dynamic loading is commonly used to allow applications to be customized. Others can write modules that your program loads at runtime—much as Interface Builder loads custom palettes and the OS X System Preferences application loads custom preference modules. The loadable modules extend what your application can do. They contribute to it in ways that you permit but could not have anticipated or defined yourself. You provide the framework, but others provide the code. 258 | -------------------------------------------------------------------------------- /Main/14_data.md: -------------------------------------------------------------------------------- 1 | - [Data](#data) 2 | - [Общие-понятия](#общие-понятия) 3 | - [Что такое Core Data? Опишите стек core data](#core-data) 4 | - [Целесообразность использования Core Data](#целесообразность-использования-core-data) 5 | - [Какие есть нюансы при использовании Core Data в разных потоках? Как синхронизировать данные между потоками?](#core-data-в-разных-потоках) 6 | - [Какие типы хранилищ поддерживает CoreData?](#типы-хранилищ) 7 | - [Что такое ленивая загрузка? Что ее связывает с Core Data? Опишите ситуация когда она может быть полезной? Что такое faulting?](#ленивая-загрузка-core-data) 8 | - [Что такое fetch result controller?](#fetch-result-controller) 9 | - [Как сделать миграцию БД?](#db-migration) 10 | 11 | 12 | # Data 13 | 14 | 15 | ## Общие понятия 16 | _Реляционная база данных_ — база данных, основанная на реляционной модели данных. Слово «реляционный» происходит от англ. relation (отношение). Для работы с реляционными БД применяют реляционные СУБД. 17 | 18 | _Реляционная модель данных (РМД)_ — логическая модель данных, прикладная теория построения баз данных, которая является приложением к задачам обработки данных таких разделов математики как теории множеств и логика первого порядка. Термин «реляционный» означает, что теория основана на математическом понятии отношение (relation). В качестве неформального синонима термину «отношение» часто встречается слово таблица. Необходимо помнить, что «таблица» есть понятие нестрогое и неформальное и часто означает не «отношение» как абстрактное понятие, а визуальное представление отношения на бумаге или экране. Некорректное и нестрогое использование термина «таблица» вместо термина «отношение» нередко приводит к недопониманию. Наиболее частая ошибка состоит в рассуждениях о том, что РМД имеет дело с «плоскими», или «двумерными» таблицами, тогда как таковыми могут быть только визуальные представления таблиц. Отношения же являются абстракциями, и не могут быть ни «плоскими», ни «неплоскими». 19 | 20 | _ORM_ – Object-relational mapping, объектно-реляционное отображение – преобразование данных между ООП и реляционными базами данных. 21 | 22 | _SQL_ – Структурированный язык запросов (Structed Query Language) – является информационно-логическим языком, предназначенным для описания, изменения и извлечения данных, хранимых в реляционных базах данных (relation, отношение). 23 | 24 | __Пример SQL:__ 25 | 26 | Create a table to store information about weather observation stations: 27 | 28 | -- No duplicate ID fields allowed 29 | ```sql 30 | CREATE TABLE STATION 31 | (ID INTEGER PRIMARY KEY, 32 | CITY CHAR(20), 33 | STATE CHAR(2), 34 | LAT_N REAL, 35 | LONG_W REAL); 36 | ``` 37 | populate the table STATION with a few rows: 38 | ```sql 39 | INSERT INTO STATION VALUES (13, 'Phoenix', 'AZ', 33, 112); 40 | INSERT INTO STATION VALUES (44, 'Denver', 'CO', 40, 105); 41 | INSERT INTO STATION VALUES (66, 'Caribou', 'ME', 47, 68); 42 | ``` 43 | query to look at table STATION in undefined order: 44 | ```sql 45 | SELECT * FROM STATION; 46 | ``` 47 | ID | CITY | STATE | LAT_N | LONG_W 48 | ---|------|-------|-------|------- 49 | 13 | Phoenix | AZ | 33 | 112 50 | 44 | Denver | CO | 40 | 105 51 | 66 | Caribou | ME | 47 | 68 52 | 53 | query to select Northern stations (Northern latitude > 39.7): 54 | 55 | -- selecting only certain rows is called a "restriction". 56 | ```sql 57 | SELECT * FROM STATION 58 | WHERE LAT_N > 39.7; 59 | ``` 60 | ID | CITY | STATE | LAT_N | LONG_W 61 | ---|------|-------|-------|------- 62 | 44 | Denver | CO | 40 | 105 63 | 66 | Caribou | ME | 47 | 68 64 | 65 | query to select only ID, CITY, and STATE columns: 66 | 67 | -- selecting only certain columns is called a "projection". 68 | ```sql 69 | SELECT ID, CITY, STATE FROM STATION; 70 | ``` 71 | ID | CITY | STATE 72 | ---|------|------ 73 | 13 | Phoenix | AZ 74 | 44 | Denver | CO 75 | 66 | Caribou | ME 76 | 77 | query to both "restrict" and "project": 78 | ```sql 79 | SELECT ID, CITY, STATE FROM STATION 80 | WHERE LAT_N > 39.7; 81 | ``` 82 | ID | CITY | STATE 83 | ---|------|------ 84 | 44 | Denver | CO 85 | 66 | Caribou | ME 86 | 87 | 88 | ## Что такое Core Data? Опишите стек core data 89 | Apple предоставляет гибкий фреймворк для работы с хранимыми на устройстве данными — Core Data. Большинство деталей по работе с хранилищем данных Core Data скрывает, позволяя вам сконцентрироваться на том, что действительно делает ваше приложение веселым, уникальным и удобным в использовании. Не смотря на то, что Core Data может хранить данные в реляционной базе данных вроде SQLite, Core Data не является СУБД (системой управления БД). По-правде, Core Data в качестве хранилища может вообще не использовать реляционные базы данных. Core Data скорее является оболочкой для работы с данными, которая позволяет работать с сущностями и их связями (отношениями к другим объектами), атрибутами, в том виде, который напоминает работы с объектным графом в обычном объектно-ориентированном программировании. 90 | 91 | A Core Data stack is composed of the following objects: one or more managed object contexts connected to a single persistent store coordinator which is in turn connected to one or more persistent stores. A stack contains all the Core Data components you need to fetch, create, and manipulate managed objects. Minimally it contains: 92 | 93 | 1. An external persistent store that contains saved records. 94 | 2. A persistent object store that maps between records in the store and objects in your application. 95 | 3. A persistent store coordinator that aggregates all the stores. 96 | 4. A managed object model that describes the entities in the stores. 97 | 5. A managed object context that provides a scratch pad for managed objects. 98 | 99 | 100 | 101 | 1. Persistent store 102 | 103 | A persistent store is a repository in which managed objects may be stored. You can think of a persistent store as a database data file where individual records each hold the last-saved values of a managed object. Core Data offers three native file types for a persistent store: binary, XML, and SQLite. You can implement your own store type if you want Core Data to interoperate with a custom file format or server. Core Data also provides an in-memory store that lasts no longer than the lifetime of a process. The entities in a store are defined by the managed object model used to create it. 104 | 105 | 2. Persistent object store 106 | 107 | A persistent object store maps between objects in your application and records in a persistent store. There are different classes of persistent object store for the different file types that Core Data supports. You can also implement your own if you want to support a custom file type. You don’t create a persistent object store directly. Instead, Core Data creates a store of the appropriate type for you when you send an `addPersistentStoreWithType:configuration:URL:options:error:` message to a persistent store coordinator. 108 | 109 | 3. Persistent store coordinator 110 | 111 | A persistent store coordinator associates persistent object stores and a managed object model, and presents a facade to managed object contexts such that a group of persistent stores appears as a single aggregate store. A persistent store coordinator is an instance of `NSPersistentStoreCoordinator`. It has a reference to a managed object model that describes the entities in the store or stores it manages. The coordinator is the central object in a Core Data stack. In many applications you just have a single store, but in complex applications there may be several, each potentially containing different entities. The persistent store coordinator’s role is __to manage these stores and present to its managed object contexts the facade of a single unified store__. When you fetch records, Core Data retrieves results from all of them, unless you specify which store you’re interested in. 112 | 113 | 4. Managed object model 114 | 115 | A managed object model is a set of objects that together form a blueprint describing the managed objects you use in your application. A model allows Core Data to map from records in a persistent store to managed objects that you use in your application. It is a collection of entity description objects (instances of `NSEntityDescription`). An entity description describes an entity (which you can think of as a table in a database) in terms of its name, the name of the class used to represent the entity in your application, and what properties (attributes and relationships) it has. During the creation of the Core Data stack, the `NSManagedObjectModel` (often referred to as the “mom”) is loaded into memory as the first step in the creation of the stack. Once the `NSManagedObjectModel` object is initialized, the `NSPersistentStoreCoordinator` object is constructed. 116 | 117 | 5. Managed object context 118 | 119 | A managed object context represents a single object space, or scratch pad, in a Core Data application. A managed object context is an instance of `NSManagedObjectContext`. Its primary responsibility is to manage a collection of managed objects. These managed objects represent an internally consistent view of one or more persistent stores. The context is a powerful object with a central role in the life-cycle of managed objects, with responsibilities from life-cycle management (including faulting) to validation, inverse relationship handling, and undo/redo. From your perspective, the context is the central object in the Core Data stack. It’s the object you use to create and fetch managed objects, and to manage undo and redo operations. Within a given context, there is at most one managed object to represent any given record in a persistent store. __When you fetch objects, the context asks its parent object store to return those objects that match the fetch request__. Changes that you make to managed objects are not committed to the parent store until you save the context. 120 | 121 | 122 | ## Целесообразность использования Core Data 123 | Core Data уменьшает количество кода, написанного для поддержки модели слоя приложения, как правило, на 50% - 70%, измеряемое в строках кода. Core Data имеет зрелый код, качество которого обеспечивается путем юнит-тестов, и используется ежедневно миллионами клиентов в широком спектре приложений. Структура была оптимизирована в течение нескольких версий. Она использует информацию, содержащуюся в модели и выполненяет функции, как правило, не работающие на уровне приложений в коде. Кроме того, в дополнение к отличной безопасности и обработке ошибок, она предлагает лучшую масштабируемость при работе с памятью, относительно любого конкурирующего решения. Другими словами: вы могли бы потратить долгое время тщательно обрабатывая Ваши собственные решения оптимизации для конкретной предметной области, вместо того, чтобы получить преимущество в производительности, которую Core Data предоставляет бесплатно для любого приложения. 124 | 125 | __Когда нецелесообразно использовать Core Data:__ 126 | * если планируется использовать очень небольшой объем данных. В этом случае проще воспользоваться для хранения Ваших данных объектами коллекций - массивами или словарями и сохранять их в .plist файлы. 127 | * если используется кросс-платформерная архитектура или требуется доступ к строго определенному формату файла с данными (хранилищу), например SQLite. 128 | * использование баз данных клиент-сервер, например MySQL или PostgreSQL. 129 | 130 | __SQLite__ 131 | * Максимальный объем хранимых данных базы SQLite составляет 2 терабайта. 132 | * Чтение из базы данных может производиться одним и более потоками, например несколько процессов могут одновременно выполнять `SELECT`. Однако запись в базу данных может осуществляться, только, если база в данный момент не занята другим процессом. 133 | * SQLite не накладывает ограничения на типы данных. Любые данные могут быть занесены в любой столбец. Ограничения по типам данных действуют только на `INTEGER PRIMARY KEY`, который может содержать только 64-битное знаковое целое. 134 | 135 | SQLite версии 3.0 и выше позволяет хранить BLOB данные в любом поле, даже если оно объявлено как поле другого типа. 136 | Обращение к SQLite базе из двух потоков одновременно неизбежно вызовет краш. Выхода два: 137 | 138 | 1. Синхронизируйте обращения при помощи директивы `@synchronized`. 139 | 2. Если задача закладывается на этапе проектирования, завести менеджер запросов на основе `NSOperationQueue`. Он страхует от ошибок автоматически, а то, что делается автоматически, часто делается без ошибок. 140 | 141 | __Пример SQLite__ 142 | 143 | ```objectivec 144 | - (int)createTable:(NSString *)filePath { 145 | sqlite3 *db = NULL; 146 | int rc = 0; 147 | 148 | rc = sqlite3_open_v2([filePath cStringUsingEncoding:NSUTF8StringEncoding], &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL); 149 | if (SQLITE_OK != rc) { 150 | sqlite3_close(db); 151 | NSLog(@"Failed to open db connection"); 152 | } else { 153 | char *query ="CREATE TABLE IF NOT EXISTS students (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, age INTEGER, marks INTEGER)"; 154 | char *errMsg; 155 | rc = sqlite3_exec(db, query, NULL, NULL, &errMsg); 156 | if (SQLITE_OK != rc) { 157 | NSLog(@"Failed to create table rc:%d, msg=%s",rc,errMsg); 158 | } 159 | sqlite3_close(db); 160 | } 161 | return rc; 162 | } 163 | 164 | - (int)insert:(NSString *)filePath withName:(NSString *)name age:(NSInteger)age marks:(NSInteger)marks { 165 | sqlite3 *db = NULL; 166 | int rc = 0; 167 | rc = sqlite3_open_v2([filePath cStringUsingEncoding:NSUTF8StringEncoding], &db, SQLITE_OPEN_READWRITE, NULL); 168 | if (SQLITE_OK != rc) { 169 | sqlite3_close(db); 170 | NSLog(@"Failed to open db connection"); 171 | } else { 172 | NSString *query = [NSString stringWithFormat:@"INSERT INTO students (name, age, marks) VALUES (\"%@\", %ld, %ld)", name, (long)age, (long)marks]; 173 | char *errMsg; 174 | rc = sqlite3_exec(db, [query UTF8String], NULL, NULL, &errMsg); 175 | if (SQLITE_OK != rc) { 176 | NSLog(@"Failed to insert record rc:%d, msg=%s",rc,errMsg); 177 | } 178 | sqlite3_close(db); 179 | } 180 | return rc; 181 | } 182 | ``` 183 | 184 | 185 | ## Какие есть нюансы при использовании Core Data в разных потоках? Как синхронизировать данные между потоками? 186 | In Core Data, the managed object context can be used with two concurrency patterns, defined by `NSMainQueueConcurrencyType` and `NSPrivateQueueConcurrencyType`. 187 | 188 | * `NSMainQueueConcurrencyType` is specifically for use with your application interface and can only be used on the main queue of an application. 189 | 190 | * The `NSPrivateQueueConcurrencyType` configuration creates its own queue upon initialization and can be used only on that queue. Because the queue is private and internal to the `NSManagedObjectContext` instance, it can only be accessed through the `performBlock:` and the `performBlockAndWait:` methods. 191 | 192 | `NSManagedObject` instances are not intended to be passed between queues. Doing so can result in corruption of the data and termination of the application. When it is necessary to hand off a managed object reference from one queue to another, it must be done through `NSManagedObjectID` instances. You retrieve the managed object ID of a managed object by calling the `objectID` method on the `NSManagedObject` instance. 193 | 194 | 195 | ## Что такое ленивая загрузка? Что ее связывает с Core Data? Опишите ситуация когда она может быть полезной? Что такое faulting? 196 | Для загрузки данных из БД в память приложения удобно пользоваться загрузкой не только данных об объекте, но и о сопряжённых с ним объектах. Это делает загрузку данных проще для разработчика: он просто использует объект, который, тем не менее вынужден загружать все данные в явном виде. Но это ведёт к случаям, когда будет загружаться огромное количество сопряжённых объектов, что плохо скажется на производительности в случаях, когда эти данные реально не нужны. Паттерн Lazy Loading (Ленивая Загрузка) подразумевает отказ от загрузки дополнительных данных, когда в этом нет необходимости. Вместо этого ставится маркер о том, что данные не загружены и их надо загрузить в случае, если они понадобятся. Как известно, если Вы ленивы, то вы выигрываете в том случае, если дело, которое вы не делали на самом деле и не надо было делать. 197 | Faulting isn't unique to Core Data. A similar technique is used in many other frameworks, such as Ember and Ruby on Rails. Faulting is a mechanism Core Data employs to reduce your application’s memory usage, only load data when it's needed. A fault is a placeholder object that represents a managed object that has not yet been fully realized, or a collection object that represents a relationship. To make faulting work, Core Data does a bit of magic under the hood by creating custom subclasses at compile time that represent the faults. 198 | 199 | 200 | 201 | 202 | ## Что такое fetch result controller? 203 | Данные сами по себе может быть и представляют какую-либо ценность, но, обычно их нужно использовать. Одним из элементов представления данных в iOS служат таблицы (объекты класса `UITableView`), которые через объект класса `NSFetchedResultsController` можно привязать к CoreData. После этого при изменении данных в CoreData будет актуализироваться информация в таблице. Так же, с помощью таблицы можно управлять данными в хранилище. 204 | `NSFetchedResultsController` — контроллер результатов выборки. Создается, обычно один экземпляр на `ViewController`, но вполне может работать и без оного, внутрь которого помещается исключительно для того, что бы было проще привязать данные к виду. 205 | 206 | 207 | ## Как сделать миграцию БД? 208 | 209 | You can only open a Core Data store using the managed object model used to create it. Changing a model will therefore make it incompatible with (and so unable to open) the stores it previously created. If you change your model, you therefore need to change the data in existing stores to new version—changing the store format is known as migration. To migrate a store, you need both the version of the model used to create it, and the current version of the model you want to migrate to. You can create a versioned model that contains more than one version of a managed object model. Within the versioned model you mark one version as being the current version. Core Data can then use this model to open persistent stores created using any of the model versions, and migrate the stores to the current version. To help Core Data perform the migration, though, you may have to provide information about how to map from one version of the model to another. This information may be in the form of hints within the versioned model itself, or in a separate mapping model file that you create. 210 | 211 | The migration process itself is in three stages. It uses a copy of the source and destination models in which the validation rules are disabled and the class of all entities is changed to `NSManagedObject`. 212 | 213 | To perform the migration, Core Data sets up two stacks, one for the source store and one for the destination store. Core Data then processes each entity mapping in the mapping model in turn. It fetches objects of the current entity into the source stack, creates the corresponding objects in the destination stack, then recreates relationships between destination objects in a second stage, before finally applying validation constraints in the final stage. 214 | 215 | Before a cycle starts, the entity migration policy responsible for the current entity is sent a `beginEntityMapping:manager:error:` message. You can override this method to perform any initialization the policy requires. The process then proceeds as follows: 216 | 217 | 1. Create destination instances based on source instances. 218 | 219 | At the beginning of this phase, the entity migration policy is sent a `createDestinationInstancesForSourceInstance:entityMapping:manager:error:` message; at the end it is sent a `endInstanceCreationForEntityMapping:manager:error:` message. In this stage, only attributes (not relationships) are set in the destination objects. Instances of the source entity are fetched. For each instance, appropriate instances of the destination entity are created (typically there is only one) and their attributes populated (for trivial cases, `name = $source.name`). A record is kept of the instances per entity mapping since this may be useful in the second stage. 220 | 221 | 2. Recreate relationships. 222 | 223 | At the beginning of this phase, the entity migration policy is sent a `createRelationshipsForDestinationInstance:entityMapping:manager:error:` message; at the end it is sent a `endRelationshipCreationForEntityMapping:manager:error:` message. For each entity mapping (in order), for each destination instance created in the first step any relationships are recreated. 224 | 225 | 3. Validate and save. 226 | 227 | In this phase, the entity migration policy is sent a `performCustomValidationForEntityMapping:manager:error:` message. Validation rules in the destination model are applied to ensure data integrity and consistency, and then the store is saved. 228 | 229 | At the end of the cycle, the entity migration policy is sent an endEntityMapping:manager:error: message. You can override this method to perform any clean-up the policy needs to do. Note that Core Data cannot simply fetch objects into the source stack and insert them into the destination stack, the objects must be re-created in the new stack. Core Data maintains “association tables” which tell it which object in the destination store is the migrated version of which object in the source store, and vice-versa. Moreover, because it doesn't have a means to flush the contexts it is working with, you may accumulate many objects in the migration manager as the migration progresses. If this presents a significant memory overhead and hence gives rise to performance problems, you can customize the process as described in Multiple Passes—Dealing With Large Datasets. 230 | 231 | __Lightweight Migration__ 232 | 233 | If you just make simple changes to your model (such as adding a new attribute to an entity), Core Data can perform automatic data migration, referred to as lightweight migration. Lightweight migration is fundamentally the same as ordinary migration, except that instead of you providing a mapping model (as described in Mapping Overview), Core Data infers one from differences between the source and destination managed object models. 234 | 235 | Lightweight migration is especially convenient during early stages of application development, when you may be changing your managed object model frequently, but you don’t want to have to keep regenerating test data. You can migrate existing data without having to create a custom mapping model for every model version used to create a store that would need to be migrated. 236 | 237 | A further advantage of using lightweight migration—beyond the fact that you don’t need to create the mapping model yourself—is that if you use an inferred model and you use the SQLite store, then Core Data can perform the migration in situ (solely by issuing SQL statements). This can represent a significant performance benefit as Core Data doesn’t have to load any of your data. Because of this, you are encouraged to use inferred migration where possible, even if the mapping model you might create yourself would be trivial. 238 | -------------------------------------------------------------------------------- /Main/16_autolayout.md: -------------------------------------------------------------------------------- 1 | - [Autolayout](#autolayout) 2 | 3 | # Autolayout 4 | 5 | _"Use Auto Layout"_ determines whether a storyboard uses the Auto Layout features introduced in iOS 6 to automatically layout your interface using constraints. 6 | 7 | _"Use Size Classes"_ enables a new Xcode 6 feature called size classes that lets you use Auto Layout to build one interface for all devices and customize constraint constants, and certain views and constraints for different interface idioms while reusing the general layout. It saves the work and repetitiveness of having to build and maintain both MainiPhone and MainiPad storyboards. 8 | 9 | __External Changes__ 10 | 11 | External changes occur when the size or shape of your superview changes. 12 | 13 | __Internal Changes__ 14 | 15 | Internal changes occur when the size of the views or controls in your user interface change. 16 | 17 | There are three main approaches to laying out a user interface. 18 | 19 | 1. you can programmatically lay out the user interface 20 | 2. you can use autoresizing masks to automate some of the responses to external change 21 | 3. you can use Auto Layout. 22 | 23 | The frame defined the view’s origin, height, and width in the superview’s coordinate system. 24 | 25 | 26 | 27 | The layout of your view hierarchy is defined as a series of linear equations. Each constraint represents a single equation. Your goal is to declare a series of equations that has one and only one possible solution. 28 | 29 | 30 | 31 | When calculating solutions, Auto Layout attempts to satisfy all the constraints in priority order from highest to lowest. If it cannot satisfy an optional constraint, that constraint is skipped and it continues on to the next constraint. 32 | 33 | Some views have a natural size given their current content. This is referred to as their _intrinsic content size_. 34 | 35 | __The content hugging__ pulls the view inward so that it fits snugly around the content. 36 | 37 | __The compression resistance__ pushes the view outward so that it does not clip the content. 38 | 39 | 40 | 41 | ``` 42 | // Compression Resistance 43 | View.height >= 0.0 * NotAnAttribute + IntrinsicHeight 44 | View.width >= 0.0 * NotAnAttribute + IntrinsicWidth 45 | 46 | // Content Hugging 47 | View.height <= 0.0 * NotAnAttribute + IntrinsicHeight 48 | View.width <= 0.0 * NotAnAttribute + IntrinsicWidth 49 | ``` 50 | These properties only take effect for views which define an intrinsic content size, otherwise there is no content size defined that could resist compression or be hugged. 51 | The top and bottom layout guides represent the upper and lower edge of the visible content area for the currently active view controller. 52 | 53 | Auto Layout does not operate on views’ frame, but on their alignment rect. It’s easy to forget the subtle difference, because in many cases they are the same. 54 | 55 | Unsatisfiable layouts occur when the system cannot find a valid solution for the current set of constraints. Two or more required constraints conflict, because they cannot all be true at the same time. 56 | When the system detects a unsatisfiable layout at runtime, it performs the following steps: 57 | 58 | 1. Auto Layout identifies the set of conflicting constraints. 59 | 2. It breaks one of the conflicting constraints and checks the layout. The system continues to break constraints until it finds a valid layout. 60 | 3. Auto Layout logs information about the conflict and the broken constraints to the console. 61 | 62 | As soon as you know about the error, the solution is typically very straightforward. Either remove one of the constraints, or change it to an optional constraint. 63 | 64 | Ambiguous layouts occur when the system of constraints has two or more valid solutions. There are two main causes: 65 | 66 | 1. The layout needs additional constraints to uniquely specify the position and location of every view. After you determine which views are ambiguous, just add constraints to uniquely specify both the view’s position and its size. 67 | 2. The layout has conflicting optional constraints with the same priority, and the system does not know which constraint it should break. 68 | 69 | Here, you need to tell the system which constraint it should break, by changing the priorities so that they are no longer equal. The system breaks the constraint having the lowest priority first. 70 | When an ambiguous layout occurs at runtime, Auto Layout chooses one of the possible solutions to use. This means the layout may or may not appear as you expect. Furthermore, there are no warnings written to the console, and there is no way to set a breakpoint for ambiguous layouts. 71 | There are a few methods you can call to help identify ambiguous layouts. All of these methods should be used only for debugging. Set a breakpoint somewhere where you can access the view hierarchy, and then call one of the following methods from the console: 72 | 73 | `hasAmbiguousLayout` Available for both iOS and OS X. Call this method on a misplaced view. It returns YES if the view’s frame is ambiguous. Otherwise, it returns NO. 74 | 75 | `exerciseAmbiguityInLayout` Available for both iOS and OS X. Call this method on a view with ambiguous layout. This will toggle the system between the possible valid solutions. 76 | 77 | `constraintsAffectingLayoutForAxis:` Available for iOS. Call this method on a view. It returns an array of all the constraints affecting that view along the specified axis. 78 | 79 | `constraintsAffectingLayoutForOrientation` Available for OS X. Call this method on a view. It returns an array of all the con-straints affecting that view along the specified orientation. 80 | 81 | `_autolayoutTrace` Available as a private method in iOS. Call this method on a view. It returns a string with diagnostic information about the entire view hierarchy containing that view. Ambiguous views are labeled, and so are views that have translatesAutoresizingMaskIntoConstraints set to YES. 82 | 83 | Four of these are the Final size classes: 84 | 85 | 1. Compact-Compact 86 | 2. Compact-Regular 87 | 3. Regular-Compact 88 | 4. Regular-Regular 89 | 90 | Base size classes: 91 | 92 | 5. Compact-Any 93 | 6. Regular-Any 94 | 7. Any-Compact 95 | 8. Any-Regular 96 | 9. Any-Any 97 | 98 | It is typically easiest to work from the most general size class to the most specific. Select the default layout for your app, and design this layout in the Any-Any size class. Then modify the other Base or Final size classes as needed. 99 | 100 | Compared to working with springs and struts, Auto Layout introduces two additional steps to the process before views can be displayed: 101 | 102 | * updating constraints 103 | * laying out views 104 | 105 | Each step is dependent on the one before; display depends on layout, and layout depends on updating constraints. 106 | 107 | The first step – updating constraints – can be considered a “measurement pass.” It happens bottom-up (from subview to super view) and prepares the information needed for the layout pass to actually set the views’ frame. You can trigger this pass by calling setNeedsUpdateConstraints. Any changes you make to the system of constraints itself will automatically trigger this. However, it is useful to notify Auto Layout about changes in custom views that could affect the layout. Speaking of custom views, you can override `updateConstraints` to add the local constraints needed for your view in this phase. 108 | 109 | The second step – layout – happens top-down (from super view to subview). This layout pass actually applies the solution of the constraint system to the views by setting their frames (on OS X) or their center and bounds (on iOS). You can trigger this pass by calling `setNeedsLayout`, which does not actually go ahead and apply the layout immediately, but takes note of your request for later. This way you don’t have to worry about calling it too often, since all the layout requests will be coalesced into one layout pass. 110 | To force the system to update the layout of a view tree immediately, you can call `layoutIfNeeded` / `layoutSubtreeIfNeeded` (on iOS and OS X respectively). This can be helpful if your next steps rely on the views’ frame being up to date. In your custom views you can override `layoutSubviews` / `layout` to gain full control over the layout pass. 111 | 112 | Finally, the display pass renders the views to screen and is independent of whether you’re using Autolayout or not. It operates top-down and can be triggered by calling `setNeedsDisplay`, which results in a deferred redraw coalescing all those calls. Overriding the familiar `drawRect:` is how you gain full control over this stage of the display process in your custom views. 113 | 114 | Since each step depends on the one before it, the display pass will trigger a layout pass if any layout changes are pending. Similarly, the layout pass will trigger updating the constraints if the constraint system has pending changes. 115 | 116 | It’s important to remember that these three steps are not a one-way street. Constraint-based layout is an iterative process. The layout pass can make changes to the constraints based on the previous layout solution, which again triggers updating the constraints following another layout pass. This can be leveraged to create advanced layouts of custom views, but you can also get stuck in an infinite loop if every call of your custom implementation of layoutSubviews results in another layout pass. 117 | -------------------------------------------------------------------------------- /Main/17_testing.md: -------------------------------------------------------------------------------- 1 | - [Тестирование](#тестирование) 2 | - [Виды тестов](#виды-тестов) 3 | - [Unit Tests](#unit-tests) 4 | - [Integration Tests](#integration-tests) 5 | - [Functional Tests](#functional-tests) 6 | - [Acceptance Tests](#acceptance-tests) 7 | - [Как тестировать асинхронные методы?](#async-testing) 8 | - [Dependency injection](#dependency-injection) 9 | 10 | 11 | # Тестирование 12 | 13 | ## Виды тестов 14 | 15 | ### Unit Tests 16 | Tests the smallest unit of functionality, typically a method/function (e.g. given a class with a particular state, calling x method on the class should cause y to happen). Unit tests should be focussed on one particular feature (e.g., calling the pop method when the stack is empty should throw an InvalidOperationException). Everything it touches should be done in memory; this means that the test code and the code under test shouldn't: 17 | 18 | 1. Call out into (non-trivial) collaborators 19 | 2. Access the network 20 | 3. Hit a database 21 | 4. Use the file system 22 | 5. Spin up a thread 23 | 24 | Any kind of dependency that is slow / hard to understand / initialise / manipulate should be stubbed / mocked / whatevered using the appropriate techniques so you can focus on what the unit of code is doing, not what its dependencies do. 25 | In short, unit tests are as simple as possible, easy to debug, reliable (due to reduced external factors), fast to execute and help to prove that the smallest building blocks of your program function as intended before they're put together. The caveat is that, although you can prove they work perfectly in isolation, the units of code may blow up when combined which brings us to ... 26 | 27 | 28 | ### Integration Tests 29 | Integration tests build on unit tests by combining the units of code and testing that the resulting combination functions correctly. This can be either the innards of one system, or combining multiple systems together to do something useful. Also, another thing that differentiates integration tests from unit tests is the environment. Integration tests can and will use threads, access the database or do whatever is required to ensure that all of the code and the different environment changes will work correctly. 30 | If you've built some serialization code and unit tested its innards without touching the disk, how do you know that it'll work when you are loading and saving to disk? Maybe you forgot to flush and dispose filestreams. Maybe your file permissions are incorrect and you've tested the innards using in memory streams. The only way to find out for sure is to test it 'for real' using an environment that is closest to production. 31 | The main advantage is that they will find bugs that unit tests can't such as wiring bugs (e.g. an instance of class A unexpectedly receives a null instance of B) and environment bugs (it runs fine on my single-CPU machine, but my colleague's 4 core machine can't pass the tests). The main disadvantage is that integration tests touch more code, are less reliable, failures are harder to diagnose and the tests are harder to maintain. 32 | Also, integration tests don't necessarily prove that a complete feature works. The user may not care about the internal details of my programs, but I do! 33 | 34 | 35 | ### Functional Tests 36 | Functional tests check a particular feature for correctness by comparing the results for a given input against the specification. Functional tests don't concern themselves with intermediate results or side-effects, just the result (they don't care that after doing x, object y has state z). They are written to test part of the specification such as, "calling function `Square(x)` with the argument of `2` returns `4`". 37 | 38 | 39 | ### Acceptance Tests 40 | Acceptance testing seems to be split into two types: 41 | Standard acceptance testing involves performing tests on the full system (e.g. using your web page via a web browser) to see whether the application's functionality satisfies the specification. E.g. "clicking a zoom icon should enlarge the document view by 25%." There is no real continuum of results, just a pass or fail outcome. 42 | The advantage is that the tests are described in plain English and ensures the software, as a whole, is feature complete. The disadvantage is that you've moved another level up the testing pyramid. Acceptance tests touch mountains of code, so tracking down a failure can be tricky. 43 | Also, in agile software development, user acceptance testing involves creating tests to mirror the user stories created by/for the software's customer during development. If the tests pass, it means the software should meet the customer's requirements and the stories can be considered complete. An acceptance test suite is basically an executable specification written in a domain specific language that describes the tests in the language used by the users of the system. 44 | 45 | 46 | ## Как тестировать асинхронные методы? 47 | 48 | We create `XCTestExpectation` instance that work like timer. Your test will never finish till one of both cases happend: 49 | * `XCTestExpectation.fulfill()` called 50 | * you got timeout defined with `waitForExpectationsWithTimeout` and therefore test will fail 51 | 52 | - Step 1 53 | 54 | Create new protocol for class under test: 55 | ```swift 56 | protocol MyCallback { 57 | func onDone(results: String) 58 | } 59 | ``` 60 | This is our callback. 61 | 62 | - Step 2 63 | 64 | In Unitest inherit this protocol: 65 | ```swift 66 | class Test_MyClass : XCTestCase, MyCallback { 67 | /* ... */ 68 | } 69 | ``` 70 | 71 | - Step 3 72 | 73 | Create `XCTestExpectation` variable: 74 | ```swift 75 | var theExpectation: XCTestExpectation? 76 | ``` 77 | and initiate onDone() method: 78 | ```swift 79 | func onDone(results: String) { 80 | theExpectation?.fulfill() // it will release our "timer" 81 | } 82 | ``` 83 | 84 | - Step 4 85 | 86 | Example of our test: 87 | ```swift 88 | func test_myFunction() { 89 | // Declare expectation 90 | theExpectation = expectationWithDescription("initialized") // dummy text 91 | var task: MyClass = MyClass() 92 | task.delegate = self // pass delegate to WmBuildGroupsTask class 93 | task.execute(); 94 | // Loop until the expectation is fulfilled in onDone method 95 | waitForExpectationsWithTimeout(500, { error in 96 | XCTAssertNil(error, "Oh, we got timeout") 97 | }) 98 | } 99 | ``` 100 | So now what left us to do is to add some stuff to WmBuildGroupsTask: 101 | 102 | - Step 5 103 | 104 | Add new variable: 105 | ```swift 106 | var delegate: MyCallback? 107 | ``` 108 | 109 | Change onPostExecute method to: 110 | ```swift 111 | func onPostExecute(transferItem:WmTransferItem) { 112 | /* .. */ 113 | delegate?.onDone("finished")// call callback 114 | } 115 | ``` 116 | 117 | 118 | ## Dependency injection 119 | 120 | Dependency injection (DI) is a popular design pattern in many languages, such as Java and C#, but it hasn’t seen wide adoption in Objective-C. The concept of dependency injection is very simple: __an object should require you to pass in any dependencies rather than creating them itself.__ Dependencies can be passed to an object via the initializer (or “constructor”), or via properties (or “setters”). These are commonly referred to as “constructor injection” and “setter injection.” 121 | 122 | Constructor Injection: 123 | ```objectivec 124 | - (instancetype)initWithDependency1:(Dependency1 *)d1 dependency2:(Dependency2 *)d2; 125 | ``` 126 | Setter Injection: 127 | ```objectivec 128 | @property (nonatomic, retain) Dependency1 *dependency1; 129 | @property (nonatomic, retain) Dependency2 *dependency2; 130 | ``` 131 | 132 | Constructor injection is preferred, and as a general rule you should only fall back to setter injection if constructor injection is not possible. With constructor injection, you’ll likely still have `@property` definitions for these dependencies, but you can make them read only to simplify your object’s API. 133 | 134 | Benefits: 135 | 136 | * Clear declaration of dependencies 137 | 138 | It becomes obvious what an object needs in order to operate, and dangerous hidden dependencies — like globals — disappear. 139 | 140 | * Composition 141 | 142 | DI encourages composition over inheritance, which improves the reusability of your code. 143 | 144 | * Easy customization 145 | 146 | When creating an object, it’s easy to customize parts of the object for specific scenarios. 147 | 148 | * Clear ownership 149 | 150 | Particularly when using constructor injection, the object ownership rules are strictly enforced — helping to build a directed acyclic object graph. 151 | 152 | * Testability 153 | 154 | More than anything else, dependency injection improves the testability of your objects. Because they can be created simply by filling in the initializer, no hidden dependencies need to be managed. Furthermore, it becomes simple to mock out the dependencies to focus your tests on the object being tested. 155 | -------------------------------------------------------------------------------- /Main/18_swift.md: -------------------------------------------------------------------------------- 1 | 2 | - [Swift](#swift) 3 | - [Сlosures and functions](#closures-and-functions) 4 | - [How Do I Declare a Closure in Swift?](#how-do-i-declare-a-closure-in-swift) 5 | - [Что такое протокол-ориентированное программирование? Как оно связано со Swift? Чем протоколы Swift отличаются от протоколов Objective-C?](#protocols) 6 | - [Difference between Array VS NSArray VS |AnyObject|](#array-nsarray-anyobject) 7 | - [Objective-C id is Swift Any or AnyObject](#id-any-anyobject) 8 | - [ValueType vs. ReferenceType](#valuetype-vs-referencetype) 9 | 10 | 11 | # Swift 12 | * Multi-paradigm: protocol-oriented, object-oriented, functional, imperative, block structured 13 | * Designed by Chris Lattner and Apple Inc. 14 | * First appeared: June 2, 2014 15 | * Stable release: 3.1.1 / April 21, 2017 16 | * Typing discipline: Static, strong, inferred 17 | * OS: Darwin, Linux, FreeBSD 18 | * Influenced by C#, CLU, D, Haskell, Objective-C, Python, Ruby, Rust 19 | 20 | Swift is a multi-paradigm, compiled programming language created by Apple Inc. for iOS, OS X, watchOS and tvOS development. Swift is designed to work with Apple's Cocoa and Cocoa Touch frameworks and the large body of existing Objective-C code written for Apple products. Swift is in-tended to be more resilient to erroneous code ("safer") than Objective-C and also more concise. It is built with the LLVM compiler framework included in Xcode 6 and later and uses the Objective-C runtime, allowing C, Objective-C, C++ and Swift code to run within a single program. 21 | Swift supports the core concepts that made Objective-C flexible, notably dynamic dispatch, wide-spread late binding, extensible programming, and similar features. These features also have well known performance and safety trade-offs, which Swift was designed to address. For safety, Swift introduced a system that helps address common programming errors like null pointers, as well as introducing syntactic sugar to avoid the pyramid of doom that can result. For performance issues, Apple has invested considerable effort in aggressive optimization that can flatten out method calls and accessors to eliminate this overhead. More fundamentally, Swift has added the concept of protocol extensibility, an extensibility system that can be applied to types, structs and classes, Apple promotes this as a real change in programming paradigms they refer to as "protocol-oriented programming". 22 | Swift was introduced at Apple's 2014 Worldwide Developers Conference (WWDC). It underwent an upgrade to version 1.2 during 2014, and a more major upgrade to Swift 2 at WWDC 2015. Initially a proprietary language, it was announced that Swift 2 would become open source later that year, sup-porting iOS, OS X and Linux. 23 | 24 | __History__ 25 | 26 | Development on Swift began in 2010 by Chris Lattner, with the eventual collaboration of many other programmers at Apple. Swift took language ideas "from Objective-C, Rust, Haskell, Ruby, Python, C#, CLU, and far too many others to list". On June 2, 2014, the Worldwide Developers Conference (WWDC) application became the first publicly released app written in Swift. A beta version of the programming language was released to registered Apple developers at the conference, but the company did not promise that the final version of Swift would be source-compatible with the test version. Apple planned to make source code converters available if needed for the full release. 27 | The Swift Programming Language, a free 500-page manual, was also released at WWDC, and is available on the iBooks Store. 28 | 29 | __Features__ 30 | 31 | Swift is an alternative for the Objective-C language that employs contemporary programming language theory concepts and strives to present a simpler syntax. During its introduction, it was described simply as "Objective-C without the C". 32 | By default, Swift does not expose pointers and other unsafe accessors, contrary to Objective-C, which uses pointers pervasively to refer to object instances. Additionally, Objective-C's use of a Smalltalk-like syntax for making method calls has been replaced with a dot-notation style and namespace system more familiar to programmers from other common object-oriented (OO) languages like Java or C#. Swift introduces true named parameters and retains key Objective-C concepts, including protocols, closures and categories, often replacing former syntax with cleaner versions and allowing these concepts to be applied to other language structures, like enums. 33 | 34 | _Generics_ 35 | 36 | Generic code enables you to write flexible, reusable functions and types that can work with any type, subject to requirements that you define. You can write code that avoids duplication and expresses its intent in a clear, abstracted manner. 37 | Generics are one of the most powerful features of Swift, and much of the Swift standard library is built with generic code. In fact, you’ve been using generics throughout the Language Guide, even if you didn’t realize it. 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, and there are no limitations on what that type can be. 38 | ```swift 39 | func swapTwoValues(inout a: T, inout _ b: T) { 40 | let temporaryA = a 41 | a = b 42 | b = temporaryA 43 | } 44 | ``` 45 | 46 | 47 | ## Сlosures and functions 48 | ```swift 49 | ()->() 50 | ``` 51 | Closures in Swift are similar to blocks in C and Objective-C. 52 | Closures are first-class objects, so that they can be nested and passed around (as do blocks in Objective-C). In Swift, functions are just a special case of closures. 53 | 54 | _Defining a function:_ 55 | 56 | You define a function with the `func` keyword. Functions can take and return none, one or multiple parameters (tuples). 57 | Return values follow the `->` sign. 58 | ```swift 59 | func jediGreet(name: String, ability: String) -> (farewell: String, mayTheForceBeWithYou: String) { 60 | return ("Good bye, \(name).", " May the \(ability) be with you.") 61 | } 62 | ``` 63 | _Calling a function:_ 64 | ```swift 65 | let retValue = jediGreet("old friend", "Force") 66 | println(retValue) 67 | println(retValue.farewell) 68 | println(retValue.mayTheForceBeWithYou) 69 | ``` 70 | _Function types_ 71 | 72 | Every function has its own function type, made up of the parameter types and the return type of the function itself. 73 | For example the following function: 74 | ```swift 75 | func sum(x: Int, y: Int) -> (result: Int) { return x + y } 76 | ``` 77 | has a function type of: 78 | ```swift 79 | (Int, Int) -> (Int) 80 | ``` 81 | Function types can thus be used as parameters types or as return types for nesting functions. 82 | 83 | _Passing and returning functions_ 84 | 85 | The following function is returning another function as its result which can be later assigned to a variable and called. 86 | ```swift 87 | func jediTrainer() -> ((String, Int) -> String) { 88 | func train(name: String, times: Int) -> (String) { 89 | return "\(name) has been trained in the Force \(times) times" 90 | } 91 | return train 92 | } 93 | let train = jediTrainer() 94 | train("Obi Wan", 3) 95 | ``` 96 | _Variadic functions_ 97 | 98 | Variadic functions are functions that have a variable number of arguments (indicated by `...` after the argument's type) that can be accessed into their body as an array. 99 | ```swift 100 | func jediBladeColor(colors: String...) -> () { 101 | for color in colors { 102 | println("\(color)") 103 | } 104 | } 105 | jediBladeColor("red","green") 106 | ``` 107 | 108 | __Closures__ 109 | ```swift 110 | {()->() in} 111 | ``` 112 | _Defining a closure:_ 113 | 114 | Closures are typically enclosed in curly braces `{ }` and are defined by a function type `() -> ()`, where `->` separates the arguments and the return type, followed by the `in` keyword which separates the closure header from its body. 115 | ```swift 116 | { (params) -> returnType in 117 | statements 118 | } 119 | ``` 120 | An example could be the map function applied to an Array: 121 | ```swift 122 | let padawans = ["Knox", "Avitla", "Mennaus"] 123 | padawans.map({(padawan: String) -> String in 124 | "\(padawan) has been trained!" 125 | }) 126 | ``` 127 | 128 | _Closures with known types:_ 129 | When the type of the closure's arguments are known, you can do as follows: 130 | ```swift 131 | func applyMutliplication(value: Int, multFunction: Int -> Int) -> Int { 132 | return multFunction(value) 133 | } 134 | 135 | applyMutliplication(2, {value in 136 | value * 3 137 | }) 138 | ``` 139 | 140 | _Closures shorthand argument names:_ 141 | 142 | Closure arguments can be references by position `($0, $1, ...)` rather than by name 143 | ```swift 144 | applyMutliplication(2, {$0 * 3}) 145 | ``` 146 | Furthermore, when a closure is the last argument of a function, parenthesis can be omitted as such: 147 | ```swift 148 | applyMutliplication(2) {$0 * 3} 149 | ``` 150 | 151 | 152 | ## How Do I Declare a Closure in Swift? 153 | _As a variable:_ 154 | ```swift 155 | var closureName: (parameterTypes) -> (returnType) 156 | ``` 157 | _As an optional variable:_ 158 | ```swift 159 | var closureName: ((parameterTypes) -> (returnType))? 160 | ``` 161 | _As a type alias:_ 162 | ```swift 163 | typealias closureType = (parameterTypes) -> (returnType) 164 | ``` 165 | _As a constant:_ 166 | ```swift 167 | let closureName: closureType = { ... } 168 | ``` 169 | _As an argument to a function call:_ 170 | ```swift 171 | func({(parameterTypes) -> (returnType) in statements}) 172 | ``` 173 | _As a function parameter:_ 174 | ```swift 175 | array.sort({ (item1: Int, item2: Int) -> Bool in return item1 < item2 }) 176 | ``` 177 | _As a function parameter with implied types:_ 178 | ```swift 179 | array.sort({ (item1, item2) -> Bool in return item1 < item2 }) 180 | ``` 181 | _As a function parameter with implied return type:_ 182 | ```swift 183 | array.sort({ (item1, item2) in return item1 < item2 }) 184 | ``` 185 | _As the last function parameter:_ 186 | ```swift 187 | array.sort { (item1, item2) in return item1 < item2 } 188 | ``` 189 | _As the last parameter, using shorthand argument names:_ 190 | ```swift 191 | array.sort { return $0 < $1 } 192 | ``` 193 | _As the last parameter, with an implied return value:_ 194 | ```swift 195 | array.sort { $0 < $1 } 196 | ``` 197 | _As the last parameter, as a reference to an existing function:_ 198 | ```swift 199 | array.sort(<) 200 | ``` 201 | _As a function parameter with explicit capture semantics:_ 202 | ```swift 203 | array.sort({ [unowned self] (item1: Int, item2: Int) -> Bool in 204 | return item1 < item2 205 | }) 206 | ``` 207 | _As a function parameter with explicit capture semantics and inferred parameters / return type:_ 208 | ```swift 209 | array.sort({ [unowned self] in return item1 < item2 }) 210 | ``` 211 | 212 | 213 | ## Что такое протокол-ориентированное программирование? Как оно связано со Swift? Чем протоколы Swift отличаются от протоколов Objective-C? 214 | 215 | Protocol-Oriented Programming is a new programming paradigm ushered in by Swift 2.0. In the Protocol-Oriented approach, we start designing our system by defining protocols. We rely on new concepts: protocol extensions, protocol inheritance, and protocol compositions. The paradigm also changes how we view semantics. In Swift, value types are preferred over classes. However, object-oriented concepts don’t work well with structs and enums: a struct cannot inherit from another struct, neither can an enum inherit from another enum. So inheritancefa - one of the fundamental object-oriented concepts - cannot be applied to value types. On the other hand, value types can inherit from protocols, even multiple protocols. Thus, with POP, value types have become first class citizens in Swift. 216 | 217 | __Protocol Extensions__ 218 | 219 | You can extend a protocol and provide default implementation for methods, computed properties, subscripts and convenience initializers. 220 | 221 | __Protocol Inheritance__ 222 | 223 | A protocol can inherit from other protocols and then add further requirements on top of the requirements it inherits. 224 | 225 | __Protocol Composition__ 226 | 227 | Swift types can adopt multiple protocols. 228 | 229 | 230 | ## Difference between Array VS NSArray VS [AnyObject] 231 | 232 | `Array` is a struct, therefore it is a value type in Swift. 233 | 234 | `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`. 235 | 236 | `[AnyObject]` is the same as `Array` 237 | 238 | 239 | ## Objective-C id is Swift Any or AnyObject 240 | 241 | `Any` can represent an instance of any type at all, including function types and optional types. 242 | 243 | `AnyObject` can represent an instance of any class type. 244 | 245 | > As part of its interoperability with Objective-C, Swift offers convenient and efficient ways of working with Cocoa frameworks. Swift automatically converts some Objective-C types to Swift types, and some Swift types to Objective-C types. Types that can be converted between Objective-C and Swift are referred to as bridged types. Anywhere you can use a bridged Objective-C reference type, you can use the Swift value type instead. This lets you take advantage of the functionality available on the reference type’s implementation in a way that is natural in Swift code. For this reason, you should almost never need to use a bridged reference type directly in your own code. In fact, when Swift code imports Objective-C APIs, the importer replaces Objective-C reference types with their corresponding value types. Likewise, when Objective-C code imports Swift APIs, the importer also replaces Swift value types with their corresponding Objective-C reference types. 246 | 247 | 248 | ## ValueType vs. ReferenceType 249 | 250 | > __Reference type__: a type that once initialized, when assigned to a variable or constant, or when passed to a function, returns a reference to the same existing instance. 251 | 252 | A typical example of a reference type is an object. Once instantiated, when we either assign it or pass it as a value, we are actually assigning or passing around the reference to the original instance (i.e. its location in memory). Reference types assignment is said to have shallow copy semantics. 253 | 254 | Mutable: The reference can be changed (mutable): you can mutate the instance itself and also change the instance reference. 255 | 256 | Immutable: The reference remains constant (immutable): you can’t change the instance reference, but you can mutate the instance itself. 257 | 258 | When to use: 259 | 260 | * Subclasses of NSObject must be class types 261 | * Comparing instance identity with === makes sense 262 | * You want to create shared, mutable state 263 | 264 | > __Value type__: a type that creates a new instance (copy) when assigned to a variable or constant, or when passed to a function. 265 | 266 | A typical example of a value type is a primitive type. Common primitive types, that are also values types, are: `Int`, `Double`, `String`, `Array`, `Dictionary`, `Set`. Once instantiated, when we either assign it or pass it as a value, we are actually getting a copy of the original instance. The most common value types in Swift are structs, enums and tuples can be value types. Value types assignment is said to have deep copy semantics. 267 | 268 | Mutable: The instance can be changed (mutable): you can change the properties of the instance. 269 | 270 | Immutable: The instance remains constant (immutable): you can’t change the properties of the instance, regardless whether a property is declared with let or var. 271 | 272 | When to use: 273 | 274 | * Comparing instance data with == makes sense (Equatable protocol) 275 | * You want copies to have independent state 276 | * The data will be used in code across multiple threads (avoid explicit synchronization) 277 | -------------------------------------------------------------------------------- /Main/1_basics.md: -------------------------------------------------------------------------------- 1 | # Основные понятия программирования 2 | 3 | ### Бит и байт 4 | Информация –– мера разрешения неопределенности. 5 | Бит (Binary digIT, bit – кусочек) выбран как мера неопределенности с двумя возможными состояниями: истина | ложь, да | нет, 1 | 0. Любые данные в компьютере представлены в виде последовательности битов. Цифровая информация хранится благодаря различию между разными величинами какой-либо физической характеристики (ток, напряжение) => чем больше велечин, которые нужно различать, тем меньше различий между смежными величинами => тем менее надежна память. В двоичной системе следует различать всего два состояния => это самый надеждный метод кодирования информации. 6 | Байт — совокупность битов, обрабатываемая компьютером одномоментно. В современных вычислительных системах байт состоит из восьми битов и, соответственно, может принимать одно из 256 (`2^8 = 256`) различных значений (состояний, кодов). 7 | ### Память 8 | Сверхоперативная, оперативная и внешняя. Некоторые регистры сверхоперативной памяти, в которые могут помещаться аргументы арифметических операций, находятся в ЦП. Также они используются для хранения текущих или следующих команд. Оперативная память служит для запоминания более постоянной информации. Каждая ячейка оперативной памяти имеет свой идентификатор (адрес) в массиве ячеек памяти. Самая маленькая ячейка имеет размер 8 бит (байт). Внешняя память служит для долговременного хранения информации, используется для хранения самих программ. 9 | ### Тип данных 10 | Тип данных характеризует одновременно: 11 | - множество допустимых значений, которые могут принимать данные, принадлежащие к этому типу; 12 | - набор операций, которые можно осуществлять над данными, принадлежащими к этому типу. 13 | 14 | Распространённые типы данных: 15 | - Логический 16 | - Целочисленный 17 | - Числа с плавающей запятой 18 | - Строковый 19 | - Указатели 20 | 21 | Тип данных указывает, как будут использоваться определенные наборы битов. Функция задает операции, выполняемые над данными. Структура служит для группировки порций информации. Указатели – для непрямой ссылки на информацию. Абстрактный тип данных – тип данных с доступом через интерфейс, реализация которого скрыта. Доступ к переменным – через операции, определенные в интерфейсе. 22 | ### Структура данных 23 | Пространственное понятие: схема организации информации в компьютере. Множество элементов данных и множество связей между ними. От выбора структуры данных зависит производительность программы. Тип структуры данных определяет: 24 | 25 | - Как хранятся данные в структуре (выделение памяти, представление данных) 26 | - Множество допустимых значений, который принимает объект в структуре данных 27 | - Множество операций, которые могут применяться к объекту 28 | 29 | Операции над структурами данных – __CRUD__: 30 | - CREATE 31 | - READ 32 | - UPDATE 33 | - DELETE 34 | 35 | Структура данных в ООП реализуется в виде классов, данные хранятся в переменных класса, системе предписаний соответстует набор методов класса. 36 | - ПРОСТЫЕ БАЗОВЫЕ (числовые, символьные, логические, перечисление, интервал, указатели) 37 | - СТАТИЧЕСКИЕ (вектор, массив, множество, запись, таблица) 38 | - ПОЛУСТАТИЧЕСКИЕ (стек, очередь, дек, строка) 39 | - ДИНАМИЧЕСКИЕ (связный список, граф, дерево) 40 | ### Алгоритмы 41 | «Рецепт расчета» – метод, разработанный для решения задачи, пригодный для реализации в компьютерной программе. Сам алгоритм является абстракцией, но его представление – конкретно и может меняться в зависимости от архитектуры компьютера, языка программирования и т. д. Представление алгоритма конструируется из блоков – примитивов. Набор примитивов и правил, как комбинировать эти примитивы для воплощения более сложных идей организуют язык программирования. Примитив состоит из синтаксической и семантической части. Описание алгоритма на низком уровне – неудобно, поэтому используются абстракции для примитивов более высокого уровня, которые состоят из примитивов низкого. Итерационная структура – выполнение набора инструкций в циклическом режиме. Рекурсивная – каждая стадия повторения цикла реализуется как подзадача предыдущей стадии. Чтобы оценить производительность нужно подсчитать количество операций. Различают временную сложность и пространственную (используемая память). 42 | 43 | `О` – (сложность в наихудшем случае), асимптотическая верхняя оценка количества операций => времени работы (худший вариант). При оценке берется количество операций, возрастающих быстрее всего. 44 | 45 | `Ω` – сложность в лучшем случае 46 | 47 | `Θ` – сложность в среднем, когда оценка `Ω = О` 48 | 49 | Наилучшая оценка алгоритма – `О(1)`, константная, когда алгоритм без циклов и рекурсии. 50 | ### Программирование 51 | Процесс создания компьютерных программ. В узком смысле (так называемое кодирование) под программированием понимается написание инструкций (программ) на конкретном языке программирования (часто по уже имеющемуся алгоритму — плану, методу решения поставленной задачи). В настоящее время активно используются интегрированные среды разработки (IDE), включающие в свой состав также редактор для ввода и редактирования текстов программ, отладчики для поиска и устранения ошибок, трансляторы с различных языков программирования, компоновщики для сборки программы из нескольких модулей и другие служебные модули. С помощью текстового редактора программист производит набор и редактирования текста создаваемой программы, который называют исходным кодом. Язык программирования определяет синтаксис и изначальную семантику исходного кода. Компилятор преобразует текст программы в машинный код, непосредственно исполняемый электронными компонентами компьютера. Интерпретатор создаёт виртуальную машину для выполнения программы, которая полностью или частично берёт на себя функции исполнения программ. 52 | Код –> препроцессор (#define, etc. – развертывание, замена) –> компилятор –> машинный код 53 | 54 | Язык программирования — формальная знаковая система, предназначенная для записи компьютерных программ. Служит для точного описания абстрактных структур данных и алгоритмов. Компилятор транслирует текст программы на языке программирования в машинный код, связывая каждый идентификатор (имя) с адресом памяти. 55 | 56 | Классы языков программирования: 57 | 58 | * Функциональные 59 | 60 | _Lisp, Erlang, Haskell, Scala_ 61 | 62 | На основе достаточно строгих абстрактных понятий и методов символьной обработки данных. Тексты программ на функциональных языках программирования описывают «как решить задачу», но не предписывают последовательность действий для решения. 63 | 64 | * Процедурные (императивные) 65 | 66 | _C, Basic, Pascal_ 67 | 68 | Последовательно выполняемые операторы можно собрать в подпрограммы, то есть более крупные целостные единицы кода, с помощью механизмов самого языка. Процедурное программирование является отражением архитектуры традиционных ЭВМ. Процедурный язык программирования предоставляет возможность программисту определять каждый шаг в процессе решения задачи. Особенность таких языков программирования состоит в том, что задачи разбиваются на шаги и решаются шаг за шагом. Используя процедурный язык, программист определяет языковые конструкции для выполнения последовательности алгоритмических шагов. 69 | 70 | * Динамические 71 | 72 | _Perl, Tcl, Python, PHP, Ruby, Smalltalk, JavaScript_ 73 | 74 | Позволяют определять типы данных и осуществлять синтаксический анализ и компиляцию «на лету», на этапе выполнения программы. Динамические языки удобны для быстрой разработки приложений. Динамическая типизация (при котором перемен-ная связывается с типом в момент присваивания значения, а не в момент объявления переменной. Таким образом, в различных участках программы одна и та же переменная мо-жет принимать значения разных типов) является основным, но не единственным критерием динамического языка программирования. 75 | 76 | * Объектно-ориентированные 77 | 78 | _C#, C++, Java. Objective-C, Perl, Python, Scala, Ruby, Smaltalk, PHP_ 79 | 80 | Язык, построенный на принципах объектно-ориентированного программирования. В основе концепции объектно-ориентированного программирования лежит понятие объекта — некой сущности, которая объединяет в себе поля (данные) и методы (выполняемые объектом действия). 81 | ### API 82 | Интерфейс программирования приложений (иногда интерфейс прикладного программирования) (application programming interface) — набор готовых классов, процедур, функций, структур и констант, предоставляемых приложением (библиотекой, сервисом) для использования во внешних программных продуктах. Используется программистами для написания всевозможных приложений. API операционных систем: Cocoa, Windows API. API не решение для системы (как фреймворк), а доступ к функциям другой системы. 83 | ### IDE 84 | Интегрированная среда разработки (integrated development environment) — система программных средств, используемая программистами для разработки программного обеспечения. 85 | Обычно, среда разработки включает в себя: 86 | 87 | * текстовый редактор 88 | * компилятор и/или интерпретатор 89 | * средства автоматизации сборки 90 | * отладчик 91 | ### Высокоуровневый язык программирования 92 | Язык программирования, разработанный для быстроты и удобства использования программистом. Основная черта высокоуровневых языков — это абстракция, то есть введение смысловых конструкций, кратко описывающих такие структуры данных и операции над ними, описания которых на машинном коде (или другом низкоуровневом языке программирования) очень длинны и сложны для понимания. 93 | ### Компиляция 94 | Трансляция программы, составленной на исходном языке высокого уровня, в эквивалентную программу на низкоуровневом языке, близком машинному коду (абсолютный код, объектный модуль, иногда на язык ассемблера). Входной информацией для компилятора (исходный код) является описание алгоритма или программа на проблемно-ориентированном языке, а на выходе компилятора — эквивалентное описание алгоритма на машинно-ориентированном языке (объектный код). Компилировать — проводить трансляцию машинной программы с проблемно-ориентированного языка на машинно-ориентированный язык. 95 | ### Программа 96 | Структуры данных и алгоритмы – это материалы, из которых строятся программы и сам компьютер. В основе работы компьютера – умение работать с двоичными данными, битами, под командами центрального процессора в виде специальных инструкций – алгоритмов. Задачи редко выражаются в виде битов: они выражаются в виде чисел, символов, строк и более сложных структур – последовательностей, списков, деревьев и т. д. Задача, которую решает программа – преобразование входных данных в выходные. 97 | ### Объект 98 | Сущность в виртуальном пространстве, которой можно посылать сообщения и которая может на них реагировать, используя свои данные, появляющаяся при создании экземпляра класса или копирования прототипа, обладающая определённым состоянием и поведением, имеющая заданные значения свойств (атрибутов) и операций над ними (методов). Как правило, при рассмотрении объектов выделяется то, что объекты принадлежат одному или нескольким классам, которые определяют поведение или роль (являются моделями) объекта. Объект, наряду с понятием класс, является важным понятием объектно-ориентированного подхода. Объекты обладают свойствами наследования, инкапсуляции и полиморфизма. 99 | ### Прототип 100 | Объект-образец, по образу и подобию которого создаются другие объекты. Объекты-копии могут сохранять связь с родительским объектом, автоматически наследуя изменения в прототипе. 101 | ### Класс 102 | Модель еще не существующей сущности (объекта). Описывает устройство объекта, является как бы чертежом объекта. 103 | ### Метод 104 | Это функция или процедура, принадлежащая какому-то классу или объекту. Методы предоставляют интерфейс, при помощи которого осуществляется доступ к данным объекта некоторого класса, тем самым, обеспечивая инкапсуляцию данных. Метод класса может использоваться для создания новых объектов и называется фабричным методом. 105 | ### Глобальная переменная 106 | Объявляется в начале программы вне любого метода, значение которой можно использовать из любого места модуля или другого файла. 107 | ### Локальная переменная 108 | Существует только во время выполнения метода и доступ к ним может выполняться только внутри метода, в котором она определена. 109 | ### Статическая переменная 110 | Сохраняет свое значение при нескольких вызовах метода, в отличие от локальной переменной. Инициализируется только один раз в начале выполнения программы. 111 | ### Переменная экземпляра, instance variable, ivar 112 | Данные, которые может содержать объект класса. Каждый раз создавая новый объект, создается и новый, причем уникальный, набор переменных экземпляра объекта. Поэтому, если у вас имеется два экземпляра объекта класса `Fraction`, к примеру, `fractionA` и `fractionB`, то каждый из них будет иметь свой собственный набор переменных. То есть, `fractionA` и `fractionB` будут иметь свои собственные `numerator` и `denominator`. 113 | ### Абстракция 114 | Смысловая конструкция, кратко описывающая структуру данных и операции над ними для упрощения понимания. Отделение объекта от его реализации (данные обрабатываются функцией высокого уровня с помощью функции низкого уровня). Существует из-за неудобства описания операций на низком уровне. 115 | ### Инкапсуляция 116 | Сокрытие методов и переменных от других объектов и частей программы. 117 | ### Наследование 118 | Процесс при котором один объект приобретает свойства и методы другого объекта. 119 | ### Полиморфизм 120 | Возможность объектов с одинаковой спецификацией иметь различную реализацию. 121 | -------------------------------------------------------------------------------- /Main/20_tasks.md: -------------------------------------------------------------------------------- 1 | - [Что произойдет если сначала нажать на кнопку 1 а потом на кнопку 2?](#string-autorelease) 2 | - [Что произойдет при исполнении следующего кода?](#что-произойдет) 3 | - [Реализуйте следующие методы: retain, release, autorelease](#retain-release-autorelease) 4 | - [Выведется ли в дебагер «Hello world»? Почему?](#hello-world) 5 | - [Что выведется в консоль?](#что-выведется-в-консоль) 6 | - [Задача про банерокрутилку](#задача-про-банерокрутилку) 7 | - [Задача на регулярное выражение](#задача-на-регулярное-выражение) 8 | - [Метод, возвращающий N наиболее часто встречающихся слов во входной строке](#наиболее-часто-встречающиеся-слова) 9 | - [Перечислите все проблемы, которые вы видите в приведенном ниже коде. Предложите, как их исправить](#проблемы-в-коде) 10 | - [Заполнить строку буквами А, чтобы не делать миллионы итераций](#заполнить-строку-буквами-a) 11 | - [Написать процедуру, инвертирующую массив символов](#инвертировать-массив-символов) 12 | - [Что не так с этим кодом?](#что-не-так-с-этим-кодом) 13 | - [Какой метод вызовется: класса A или класса B?](#какой-метод-вызовется) 14 | - [int8_t matrix 2048 2024, допустимо ли?](#int8_t-matrix) 15 | - [Одинаковую ли память занимают эти структуры и почему так?](#memory-for-structs) 16 | 17 | 18 | ## Что произойдет если сначала нажать на кнопку 1 а потом на кнопку 2? 19 | ```objectivec 20 | - (IBAction)btn1DidTouch:(id)sender { 21 | _string = [[[NSString alloc] initWithFormat:@"v=%i", rand()] autorelease]; 22 | } 23 | - (IBAction)btn2DidTouch:(id)sender { 24 | NSLog(@"_string is equal to ‘%@’", _string); 25 | } 26 | ``` 27 | Крэш, т.к utoreleasepool создается в начале обработки события и уничтожается в конце. т.е. нажали на первую кнопку — началась обработка события, нажали на вторую — кнопку — закончилась обработка первого события, очистлся autoreleasepool а вместе с ним и объект удалился, а ссылка осталась. Затем началась обработка второго события и мы обращаемся к задеалоченному объекту, результат — крэш. 28 | 29 | 30 | ## Что произойдет при исполнении следующего кода? 31 | ```objectivec 32 | Ball *ball = [[[[Ball alloc] init] autorelease] autorelease]; 33 | ``` 34 | Впоследствии это вызовет крэш. Потому что объект дважды добавляется в пул автоосвобождения, и `release` вызовется дважды. 35 | 36 | 37 | ## Реализуйте следующие методы: retain, release, autorelease 38 | ```objectivec 39 | - (id)retain { 40 | NSIncrementExtraRefCount(self); 41 | return self; 42 | } 43 | 44 | - (void)release { 45 | if (NSDecrementExtraRefCountWasZero(self)) { 46 | NSDeallocateObject(self); 47 | } 48 | } 49 | 50 | - (id)autorelease { 51 | // Add the object to the autorelease pool 52 | [NSAutoreleasePool addObject:self]; 53 | return self; 54 | } 55 | ``` 56 | 57 | 58 | ## Выведется ли в дебагер Hello world? Почему? 59 | ```objectivec 60 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 61 | dispatch_sync(dispatch_get_main_queue(), ^{ 62 | NSLog(@"Hello world"); 63 | }); 64 | /* Another implementation */ 65 | return YES; 66 | } 67 | ``` 68 | Нет. deadlock 69 | 70 | ## Что выведется в консоль? 71 | ```objectivec 72 | NSObject *object = [NSObject new]; 73 | dispatch_async(dispatch_get_main_queue(), ^ { 74 | NSLog(@"A %d", [object retainCount]); 75 | dispatch_async(dispatch_get_main_queue(), ^ { 76 | NSLog(@"B %d", [object retainCount]); 77 | }); 78 | NSLog(@"C %d", [object retainCount]); 79 | }); 80 | NSLog(@"D %d", [object retainCount]); 81 | ``` 82 | ``` 83 | D 2 84 | A 2 85 | C 3 86 | B 2 87 | ``` 88 | 89 | 90 | ## Задача про банерокрутилку 91 | Из заданного списка вывести поочередно, рандомно, а главное, без повторений, все его элементы. 92 | ```java 93 | import java.util.Random; 94 | class Banner 95 | { 96 | public static void main(String[] args) 97 | { 98 | Random r = new Random(); 99 | int[] list = new int[100];// в угоду наглядности в дебри линкедлистов лезть не будем 100 | for (int i = 0; i < 100; ++i) 101 | { 102 | list[i] = i; 103 | } 104 | /*А теперь главное - логика алгоритма*/ 105 | int index = 99; 106 | int number; 107 | while (index > 0) 108 | { 109 | number = r.nextInt(index); 110 | System.out.println(list[number]); 111 | list[number] = list[index]; 112 | --index; 113 | } 114 | } 115 | } 116 | ``` 117 | Теперь кратко и по сути, что здесь происходит. Пока в списке есть элементы, мы берем случайное число в пространстве длины массива, выводим его, потом последний элемент ставим на место только что выведенного, а индекс длины уменьшаем на единицу, пока не останется ничего. 118 | 119 | 120 | ## Задача на регулярное выражение 121 | В системе авторизации есть следующее ограничение на формат логина: он должен начинаться с латинской буквы, может состоять из латинских букв, цифр, точки и минуса и должен закан-чиваться латинской буквой или цифрой. Минимальная длина логина — 1 символ. Максимальная — 20 символов. 122 | ```objectivec 123 | BOOL loginTester(NSString* login) { 124 | NSError *error = NULL; 125 | NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"\\A[a-zA-Z](([a-zA-Z0-9\\.\\-]{0,18}[a-zA-Z0-9])|[a-zA-Z0-9]){0,1}\\z" options:NSRegularExpressionCaseInsensitive error:&error]; 126 | // Здесь надо бы проверить ошибки, но если регулярное выражение оттестированное и 127 | // не из пользовательского ввода - можно пренебречь. 128 | NSRange rangeOfFirstMatch = [regex rangeOfFirstMatchInString:login options:0 range:NSMakeRange(0, [login length])]; 129 | return (BOOL)(rangeOfFirstMatch.location!=NSNotFound); 130 | } 131 | ``` 132 | 133 | 134 | ## Метод, возвращающий N наиболее часто встречающихся слов во входной строке 135 | ```objectivec 136 | - (NSArray *)mostFrequentWordsInString:(NSString *)string count:(NSUInteger)count { 137 | // получаем массив слов. 138 | // такой подход для человеческих языков будет работать хорошо. 139 | // для языков, вроде китайского, или когда язык заранее не известен, 140 | // лучше использовать enumerateSubstringsInRange с опцией NSStringEnumerationByWords 141 | NSMutableCharacterSet *separators = [[NSCharacterSet whitespaceAndNewlineCharacterSet] mutableCopy]; 142 | [separators formUnionWithCharacterSet:[NSCharacterSet punctuationCharacterSet]]; 143 | NSArray *words = [string componentsSeparatedByCharactersInSet:separators]; 144 | NSCountedSet *set = [NSCountedSet setWithArray:words]; 145 | // тут бы пригодился enumerateByCount, но его нет. 146 | // будем строить вручную 147 | NSMutableArray *selectedWords = [NSMutableArray arrayWithCapacity:count]; 148 | NSMutableArray *countsOfSelectedWords = [NSMutableArray arrayWithCapacity:count]; 149 | for (NSString *word in set) { 150 | NSUInteger wordCount = [set countForObject:word]; 151 | NSNumber *countOfFirstSelectedWord = [countsOfSelectedWords count] ? [countsOfSelectedWords objectAtIndex:0] : nil; // в iOS 7 появился firstObject 152 | if ([selectedWords count] < count || wordCount >= [countOfFirstSelectedWord unsignedLongValue]) { 153 | NSNumber *wordCountNSNumber = [NSNumber numberWithUnsignedLong:wordCount]; 154 | NSRange range = NSMakeRange(0, [countsOfSelectedWords count]); 155 | NSUInteger indexToInsert = [countsOfSelectedWords indexOfObject:wordCountNSNumber inSortedRange:range options:NSBinarySearchingInsertionIndex usingComparator:^(NSNumber *n1, NSNumber *n2) { 156 | NSUInteger _n1 = [n1 unsignedLongValue]; 157 | NSUInteger _n2 = [n2 unsignedLongValue]; 158 | if (_n1 == _n2) 159 | return NSOrderedSame; 160 | else if (_n1 < _n2) 161 | return NSOrderedAscending; 162 | else 163 | return NSOrderedDescending; 164 | }]; 165 | [selectedWords insertObject:word atIndex:indexToInsert]; 166 | [countsOfSelectedWords insertObject:wordCountNSNumber atIndex:indexToInsert]; 167 | // если слов уже есть больше чем нужно, удаляем то что с наименьшим повторением 168 | if ([selectedWords count] > count) { 169 | [selectedWords removeObjectAtIndex:0]; 170 | [countsOfSelectedWords removeObjectAtIndex:0]; 171 | } 172 | } 173 | } 174 | return [selectedWords copy]; 175 | // можно было бы сразу вернуть selectedWords, 176 | // но возвращать вместо immutable класса его mutable сабклас нехорошо - может привести к багам 177 | } 178 | // очень интересный метод для юнитестов: правильный результат может быть разным и зависит от порядка слов в строке. 179 | ``` 180 | Я бы именно такой подход и использовал, если бы мне нужно было решить эту задачу в реальном iOS приложении, при условии, что я понимаю, откуда будут браться входные данные для поиска и предполагаю, что размеры входной строки не будут больше нескольких мегабайт. Вполне разумное допущение для iOS приложения, на мой взгляд. Иначе на входе не было бы строки, а был бы файл. При реально больших входных данных прийдется попотеть над регулярным выражением для перебора слов, чтоб избавиться от одного промежуточного массива. Такое регулярное выражение очень зависит от языка — то что сработает для русского не проканает для китайского. А вот что делать со словами дальше — кроме прямолинейного алгоритма в голову ничего не приходит. Если бы нужно было выбрать одно наиболее часто встречающееся слово — это Fast Majority Voting. Но вся красота этого алгоритма в том, что он работает для выбора одного значения. Модификаций алгоритма для выбора N значений мне не известны. Самому модифицировать не получилось. 181 | 182 | 183 | ## Перечислите все проблемы, которые вы видите в приведенном ниже коде. Предложите, как их исправить 184 | ```objectivec 185 | NSOperation *operation = [NSBlockOperation blockOperationWithBlock:^{ 186 | for (int i = 0; i < 1000; ++i) { 187 | if ([operation isCancelled]) return; 188 | process(data[i]); 189 | } 190 | }]; 191 | [queue addOperation:operation]; 192 | ``` 193 | Лично я вижу проблему в том, что переменная operation, «захваченная» блоком при создании блока, еще не проинициализирована до конца. Какое реально значение этой переменной будет в момент «захвата», зависит от того, используется ли этот код в методе класса или в простой функции. Вполне возможно, что сгенерированный код будет вполне работоспособен и так, но мне этот код не ясен. Как выйти из ситуации? Так: 194 | ```objectivec 195 | NSBlockOperation *operation = [[NSBlockOperation alloc] init]; 196 | [operation addExecutionBlock:^{ 197 | for (int i = 0; i < 1000; ++i) { 198 | if ([operation isCancelled]) return; 199 | process(data[i]); 200 | } 201 | }]; 202 | [queue addOperation:operation]; 203 | ``` 204 | Возможно, достаточно было бы просто добавить модификатор `__block` в объявление переменной operation. Но так, как в коде выше — наверняка. Некоторые даже создают `__weak` копию переменной operation и внутри блока используют ее. Хорошо подумав я решил, что в данном конкретном случае, когда известно время жизни переменной operation и блока — это излишне. Ну и я бы подумал, стоит ли использовать `NSBlockOperation` для таких сложных конструкций. Разумных доводов привести не могу — вопрос личных предпочтений. 205 | Что еще с этим кодом не так? Я не люблю разных магических констант в коде и вместо 1000 использовал бы `define`, `const`, `sizeof` или что-то в этом роде. 206 | В длинных циклах в objective-c нужно помнить об autoreleased переменных и, если такие пере-менные используются в функции или методе process, а сам этот метод или функция об этом не заботится, нужно завернуть этот вызов в `@autoreleasepool {}`. Создание нового пула при каждой итерации цикла может оказаться накладным или излишним. Если не используется ARC, можно создавать новый NSAutoreleasePool каждые, допустим, 10 итераций цикла. Если исполь-зуется ARC, такой возможности нет. Кстати, это, наверное, единственный довод не использо-вать ARC. 207 | По коду не ясно, меняются ли данные в процессе обработки, обращается ли кто-то еще к этим данным во время обработки из других потоков, какие используются структуры данных, заботится ли сам process о монопольном доступе к данным тогда когда это нужно. Может понадобиться позаботиться о блокировках. 208 | 209 | Doh. Dear future googlers: of course operation is nil when copied by the block, but it doesn't have to be copied. It can be qualified with `__block` like so: 210 | ```objectivec 211 | //THIS MIGHT LEAK! See the update below. 212 | __block NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{ 213 | while( ! [operation isCancelled]){ 214 | //do something... 215 | } 216 | }]; 217 | ``` 218 | _UPDATE:_ 219 | 220 | Upon further meditation, it occurs to me that this will create a retain cycle under ARC. In ARC, I believe `__block` storage is retained. If so, we're in trouble, because NSBlockOperation also keeps a strong references to the passed in block, which now has a strong reference to the operation, which has a strong reference to the passed in block, which… 221 | It's a little less elegant, but using an explicit weak reference should break the cycle: 222 | ```objectivec 223 | NSBlockOperation *operation = [[NSBlockOperation alloc] init]; 224 | __weak NSBlockOperation *weakOperation = operation; 225 | [operation addExecutionBlock:^{ 226 | while(![weakOperation isCancelled]){ 227 | //do something... 228 | } 229 | }]; 230 | ``` 231 | 232 | 233 | ## Заполнить строку буквами А, чтобы не делать миллионы итераций 234 | ```objectivec 235 | NSString *str = @"a"; 236 | for (int i = 0; i< 5000000; i++) { 237 | str = [str stringByAppendingString:@"a"]; 238 | } 239 | ``` 240 | _Ответ_ 241 | ```objectivec 242 | str =[@"" stringByPaddingToLength:5000000 withString:@"a" startingAtIndex:0]; 243 | ``` 244 | 245 | 246 | ## Написать процедуру, инвертирующую массив символов 247 | __Способ 1__ 248 | ```objectivec 249 | // myString is "hi" 250 | NSMutableString *reversedString = [NSMutableString string]; 251 | NSInteger charIndex = [myString length]; 252 | while (charIndex > 0) { 253 | charIndex--; 254 | NSRange subStrRange = NSMakeRange(charIndex, 1); 255 | [reversedString appendString:[myString substringWithRange:subStrRange]]; 256 | } 257 | NSLog(@"%@", reversedString); // outputs "ih" 258 | ``` 259 | __Способ 2__ 260 | ```objectivec 261 | array.reverseObjectEnumerator.allObjects; 262 | ``` 263 | __Способ 3__ 264 | ```c++ 265 | #include 266 | /* reverse: переворачивает строку s (результат в s) */ 267 | void reverse(char s[]) { 268 | int c, i, j; 269 | for (i = 0, j = strlen(s) - 1; i < j; i++, j--) { 270 | с = s[i]; 271 | s[i] = s[j]; 272 | s[j] = c; 273 | } 274 | } 275 | ``` 276 | 277 | 278 | ## Что не так с этим кодом? 279 | ```objectivec 280 | [[[SomeClass alloc] init] init]; 281 | ``` 282 | Пример: есть класс `A`, который имеет поле `NSString *b` и в ините ты делаешь `_b = @"somestring";` Стринг `b` не хранится в памяти выделенной под `A` – в этой памяти хранится лишь ссылка на `b`, а сам объект создается вовне. При повторном ините стринг просто пересоздастся, не стерев старый, и мы получаем утекший стринг. Вообще, такая ситуация есть далеко не везде, и далеко не всегда вызовет проблемы. Но кастомные повторные инициализации реально могут вызывать утечки памяти — зависит от конкретного типа объекта. Двойной инит может вызвать утечку. А может не вызвать. Каждый конкретный класс - отдельный вопрос. 283 | 284 | 285 | ## Какой метод вызовется: класса A или класса B? 286 | ```objectivec 287 | @interface A : NSObject 288 | - (void)someMethod; 289 | @end 290 | 291 | @implementation A 292 | - (void)someMethod { 293 | NSLog(@"This is class A"); 294 | } 295 | @end 296 | 297 | @interface B : A 298 | @end 299 | 300 | @implementation B 301 | - (void)someMethod { 302 | NSLog(@"This is class B"); 303 | } 304 | @end 305 | 306 | @interface C : NSObject 307 | @end 308 | 309 | @implementation C 310 | - (void)method { 311 | A *a = [B new]; 312 | [a someMethod]; 313 | } 314 | @end 315 | ``` 316 | Вызовется метод класса B. 317 | 318 | 319 | ## `int8_t matrix [2048][2024]`, допустимо ли? 320 | 321 | 2048 * 2024 = 4145152 байт, так как int8_t = 1 байт. Значит для хранения массива нужно 4.15 мегабайт памяти в стеке. На iOS размер стека ограничен 1 мегабайтом, следовательно, такая запись недопустима. 322 | 323 | 324 | ## Одинаковую ли память занимают эти структуры и почему так? 325 | 326 | ```c 327 | struct StructA { 328 | int32_t a; 329 | char b; 330 | char c; 331 | }; 332 | 333 | struct StructB { 334 | char b; 335 | int32_t a; 336 | char c; 337 | }; 338 | ``` 339 | ``` 340 | sizeof(StructA) == 8 341 | sizeof(StructB) == 12 342 | ``` 343 | [Как происходит выравнивание указателей на объекты в Objective-C?](19_general_questions.md#data-structure-alignment) 344 | -------------------------------------------------------------------------------- /Main/21_to_do.md: -------------------------------------------------------------------------------- 1 | * что такое мета-класс? 2 | * как протестировать метод, не объявленный в публичном интерфейсе 3 | * что такое assert и когда использовать? 4 | * Рефлексия и интроспекция 5 | * BDD, TDD 6 | -------------------------------------------------------------------------------- /Main/2_data_structures.md: -------------------------------------------------------------------------------- 1 | - [Структуры данных](#структуры-данных) 2 | - [Массив](#массив) 3 | - [Ассоциативный массив](#ассоциативный-массив) 4 | - [Хеш-таблица](#xеш-таблица) 5 | - [Множество](#множество) 6 | - [Список](#список) 7 | - [Связный список ](#связный-список) 8 | - [Двусвязный список ](#двусвязный-список) 9 | - [Кольцевой список ](#кольцевой-список) 10 | - [Очередь](#очередь) 11 | - [Стек ](#стек) 12 | - [Дек](#дек) 13 | - [Куча](#куча) 14 | - [Граф](#граф) 15 | - [Дерево](#дерево) 16 | - [Бинарное дерево поиска](#бинарное-дерево-поиска) 17 | - [Красно-черное дерево](#красно-черное-дерево) 18 | 19 | 20 | # Структуры данных 21 | 22 | 23 | 24 | 25 | 26 | 27 | ## Массив 28 | _array_ 29 | 30 | Фиксированный набор данных одного типа в виде непрерывного ряда. Простая базовая статическая структура данных с последовательным распределением элементов в памяти с прямым или произвольным доступом (одномерный массив – вектор, двухмерный – матрица). 31 | 32 | 33 | 34 | Операции: 35 | * Получить элемент за время `log(n)` 36 | * Записать элемент 37 | 38 | Плюсы: 39 | * Доступ за постоянное время 40 | * Память тратится только на данные 41 | 42 | Минусы: 43 | * Статичная, неизменяемая структура 44 | 45 | 46 | ### Ассоциативный массив 47 | _associative array, map, symbol table, dictionary_ 48 | 49 | An associative array, map, symbol table, or dictionary is an abstract data type composed of a collection of pairs, such that each possible key appears at most once in the collection. 50 | Operations associated with this data type allow: 51 | * the addition of pairs to the collection 52 | * the removal of pairs from the collection 53 | * the modification of the values of existing pairs 54 | * the lookup of the value associated with a particular key 55 | 56 | Ассоциативный массив еще называют нагруженным множеством (data + info), где data – ключ, а нагрузка – значение ключа. 57 | 58 | 59 | #### Хеш-таблица 60 | _hash table, hash map_ 61 | 62 | Ассоциативный массив, хранит пары в виде связанного списка (open hash, closed address) или массива пар (closed hash, open address). Индекс элемента равен хеш-функции от ключа i = hash(key). Разбиение множества на подмножества происходит с помощью хеш функции (пример: телефонная книга). 63 | 64 | 65 | 66 | 67 | ## Множество 68 | _set_ 69 | 70 | A set is an abstract data structure that can store certain values, without any particular order, and no repeated values. It is a computer implementation of the mathematical concept of a finite set. Unlike most other collection types, rather than retrieving a specific element from a set, one typically tests a value for membership in a set. Some set data structures are designed for static or frozen sets that do not change after they are constructed. Static sets allow only query operations on their elements — such as checking whether a given value is in the set, or enumerating the values in some arbitrary order. Other variants, called dynamic or mutable sets, allow also the insertion and deletion of elements from the set. 71 | 72 | 73 | ## Список 74 | _list_ 75 | 76 | Простейшая динамическая структура, упорядоченное множество с переменным числом элементов. 77 | 78 | 79 | ### Связный список 80 | _linked list_ 81 | 82 | 83 | 84 | 85 | ### Двусвязный список 86 | _doubly linked list_ 87 | 88 | 89 | 90 | 91 | ### Кольцевой список 92 | _circular Linked list_ 93 | 94 | 95 | 96 | Плюсы 97 | * Движение в обе стороны 98 | * Добавление элемента за `O(1)` время 99 | * Удаление за `O(1)` время 100 | 101 | Минусы 102 | * На указатели тратится дополнительная память 103 | * Поиск только последовательный путем перебора за `O(n)` 104 | 105 | Отличие списка от массива: 106 | 107 | Массив имеет фиксированное время перехода по индексу, но нуждается в монолитном секторе памяти, обладает нефиксированным временем вставки и удаления. 108 | Список более требователен к памяти, дольше переход по индексу, но значительно быстрее вставка и удаление за `O(1)`. В Java и в C++ явно различаются `List` и `Array`, в Objective-C `NSMutableArray` скорее список, чем массив. 109 | 110 | 111 | ## Очередь 112 | _queue_ 113 | 114 | Абстрактный тип данных с дисциплиной доступа к элементам «первый пришёл — первый вышел» (FIFO, first-in-first-out). Добавление элемента (принято обозначать словом enqueue — поставить в очередь) возможно лишь в конец очереди, выборка — только из начала очереди (что принято называть словом dequeue — убрать из очереди), при этом выбранный элемент из очереди удаляется. 115 | 116 | 117 | ### Стек 118 | _stack_ 119 | 120 | Стек – реализация очереди LIFO (last-in-first-out) и является структурированной областью памяти, в отличие от кучи. Последовательный список с переменной длинной, включение и исключение только из вершины стека. Состоит из последовательности фреймов. 121 | Пример: после вызова метода из стека выделяется запрошенная область памяти – фрейм, который хранит значения объявленных переменных. 122 | 123 | Операции: 124 | * Включение 125 | * Исключение 126 | * Определение размера 127 | * Очистка 128 | * Неразрушающее чтение 129 | 130 | Функция стека – сохранить работу, невыполненную до конца, с возможностью переключения на другую работу. 131 | 132 | 133 | 134 | 135 | ### Дек 136 | _double ended queue, dequeue_ 137 | 138 | Очередь с двумя концами, включение и исключение из любого конца (левого или правого). 139 | 140 | 141 | 142 | 143 | ## Куча 144 | _heap_ 145 | 146 | Куча как структура данных представляет собой дерево, где родитель A >= ребенка B => A – корень кучи. Max куча, Min куча. 147 | 148 | Операции: 149 | * Найти max или min 150 | * Удалить max или min 151 | * Увеличить ключи или уменьшить 152 | * Добавить 153 | * Слияние 154 | 155 | Куча как область памяти – реализация динамически распределяемой памяти, в которой хранятся все объекты (вызов `alloc` в Objective-C выделяет из кучи требуемую область памяти). 156 | 157 | 158 | ## Граф 159 | _graph_ 160 | 161 | Фигура, состоящая из вершин и ребер, соединяющих вершины. Направленный и ненаправленный. 162 | 163 | 164 | ## Дерево 165 | _tree_ 166 | 167 | Связаный граф без циклов. Выделена одна вершина – корень. Остальные – сыновья. Если нет ребенка – терминальная вершина 168 | 169 | 170 | 171 | 172 | ### Бинарное дерево поиска 173 | _binary search tree_ 174 | 175 | Состоит из узлов (записей) вида `data`, `left`, `right`, где 176 | ``` 177 | key[left[x]] < key[x] <= key[right[x]] 178 | ``` 179 | Ключ данных родительского узла больше левого сына и нестрого меньше правого. 180 | 181 | 182 | ### Красно-черное дерево 183 | _red-black tree, rb-tree_ 184 | 185 | 186 | 187 | 188 | 189 | Одно из самобалансирующихся двоичных деревьев поиска, гарантирующих логарифмический рост высоты дерева от числа узлов и быстро выполняющее основные операции дерева поиска: добавление, удаление и поиск узла. Сбалансированность достигается за счёт введения дополнительного атрибута узла дерева — «цвета». Этот атрибут может принимать одно из двух возможных значений — «чёрный» или «красный». 190 | * Узел либо красный, либо чёрный. 191 | * Корень — чёрный. (В других определениях это правило иногда опускается. Это правило слабо влияет на анализ, так как корень всегда может быть изменен с красного на чёрный, но не обязательно наоборот). 192 | * Все листья (NIL) — черные. 193 | * Оба потомка каждого красного узла — черные. 194 | * Всякий простой путь от данного узла до любого листового узла, являющегося его потомком, содержит одинаковое число черных узлов. 195 | -------------------------------------------------------------------------------- /Main/3_algorithms.md: -------------------------------------------------------------------------------- 1 | - [Алгоритмы](#алгоритмы) 2 | - [Нотация «большое О»](#нотация-большое-о) 3 | - [Последовательный поиск](последовательный-поиск) 4 | - [Бинарный поиск](#бинарный-поиск) 5 | - [Последовательный поиск](#последовательный-поиск) 6 | - [Сортировка вставками](#сортировка-вставками) 7 | - [How to merge two sorted arrays into a sorted array](#merge-arrays) 8 | - [Рекурсивная функция](#рекурсивная-функция) 9 | 10 | 11 | # Алгоритмы 12 | 13 | ## Нотация «большое О» 14 | Performance is usually described with the Big O Notation. It defines the limiting behavior of a function and is often used to characterize algorithms on their performance. O defines the upper bound of the growth rate of the function. To see just how big the difference is, see commonly used O notations and the number of operations needed. 15 | 16 | 17 | 18 | 19 | 20 | 21 | For example, if you sort an array with 50 elements, and your sorting algorithm has a complexity of `O(n^2)`, there will be 2,500 operations necessary to complete the task. Furthermore, there’s also overhead in internal management and calling that method - so it’s 2,500 operations times constant. `O(1)` is the ideal complexity, meaning constant time. Good sorting algorithms usually need `O(n log n)` time. 22 | 23 | 24 | ## Последовательный поиск 25 | _linear search_ 26 | 27 | 28 | Для неупорядоченного массива – перебор всех элементов, пока либо не найдется элемент, либо не закончится массив. 29 | 30 | ```c 31 | //O(n) 32 | int linearSearch(int array[], int size, int x) { 33 | for (int i = 0; i < size; i++) { 34 | if (x == array[i]) { 35 | return x; 36 | } 37 | } 38 | return -1; 39 | } 40 | 41 | //O(n) 42 | int linearSearchMax(int array[], int size) { 43 | int max = array[0]; 44 | for (int i = 0; i < size; i++) { 45 | if (array[i] >= max) { 46 | max = array[i]; 47 | } 48 | } 49 | return max; 50 | } 51 | ``` 52 | 53 | 54 | ## Бинарный поиск 55 | _binary search, half-interval search, logarithmic search, binary chop_ 56 | 57 | `log(n), отсортированный массив` 58 | 59 | Алгоритм двоичного поиска похож на то, как мы ищем слово в словаре. Открываем словарь посередине, смотрим в какой из половин будет нужное нам слово. Допустим, в первой. Открываем первую часть посередине, продолжаем половинить, пока не найдем нужное слово. С массивами так: есть упорядоченный массив, берем число из середины массива, сравниваем с искомым. Если оно оказалось больше, значит искомое число в первой половине массива, если меньше — во второй. Продолжаем делить оставшуюся половину, когда находим нужное число возвращаем его индекс, если не находим возвращаем `null`. 60 | 61 | ```c 62 | int binarySearch(int array[], int size, int x) { 63 | int first = 0; // Первый элемент в массиве 64 | int last = size - 1; // Последний элемент в массиве 65 | if (x < array[first] || array[last] < x) { 66 | // x лежит вне заданного массива 67 | return -1; 68 | printf("-1"); 69 | } else { 70 | while (first < last) { 71 | int mid = (first + last) / 2; 72 | if (x < array[mid]) { 73 | last = mid - 1; 74 | } else { 75 | first = mid; 76 | } 77 | } 78 | if (array[last] == x) { 79 | // Искомый элемент найден. last - искомый индекс 80 | return x; 81 | printf("%i", x); 82 | } else { 83 | // Искомый элемент не найден. 84 | return -1; 85 | printf("-1"); 86 | } 87 | } 88 | } 89 | ``` 90 | `NSArray` has come with built-in binary search since iOS 4 / Snow Leopard: 91 | ```objectivec 92 | typedef NS_OPTIONS(NSUInteger, NSBinarySearchingOptions) { 93 | NSBinarySearchingFirstEqual = (1UL << 8), 94 | NSBinarySearchingLastEqual = (1UL << 9), 95 | NSBinarySearchingInsertionIndex = (1UL << 10), 96 | }; 97 | 98 | - (NSUInteger)indexOfObject:(id)obj inSortedRange:(NSRange)range options:(NSBinarySearchingOptions)options usingComparator:(NSComparator)cmp; 99 | ``` 100 | Why would you want to use this? Methods like `containsObject:` and `indexOfObject:` start at index `0` and search every object until the match is found - they don’t require the array to be sorted but have a performance characteristic of `O(n)`. Binary search, on the other hand, requires the array to be sorted, but only needs `O(log n)` time. Thus, for one million entries, binary search requires, at most, 21 comparisons, while the naive linear search would require an average of 500,000 comparisons. 101 | 102 | __Time to search for 1000 entries within 1000000 objects.__ 103 | ``` 104 | Linear: 54130.38[ms]. 105 | Binary: 7.62[ms] 106 | ``` 107 | For comparison, the search for a specific index with `NSOrderedSet` took 0.23 ms - that’s more than 30 times faster, even compared to binary search. Keep in mind that sorting is expensive as well. Apple uses merge sort, which takes `O(n*log n)`, so if you just have to call `indexOfObject:` once, there’s no need for binary search. 108 | 109 | 110 | ## Сортировка вставками 111 | _insertion sort_ 112 | 113 | `O(n^2), частично отсортированный массив` 114 | 115 | Суть его заключается в том что, на каждом шаге алгоритма мы берем один из элементов массива, находим позицию для вставки и вставляем. Стоит отметить что массив из 1-го элемента считается отсортированным. 116 | 117 | * Устойчив 118 | * Может сортировать массив по мере его поступления 119 | ```c 120 | void insertionSort(int array[], int size) { 121 | int i, j, tmp; 122 | for (i = 1; i < size; i++) { 123 | tmp = array[i]; 124 | for (j = i - 1; j >= 0 && array[j] > tmp; j--) { 125 | array[j + 1] = array[j]; 126 | } 127 | array[j + 1] = tmp; 128 | } 129 | } 130 | ``` 131 | 132 | 133 | ## Сортировка пузырьком 134 | _bubble sort, sinking sort_ 135 | 136 | `O(n^2)` 137 | 138 | Алгоритм состоит из повторяющихся проходов по сортируемому массиву. За каждый проход элементы последовательно сравниваются попарно и, если порядок в паре неверный, выполняется обмен элементов. Проходы по массиву повторяются `N-1` раз или до тех пор, пока на очередном проходе не окажется, что обмены больше не нужны, что означает — массив отсортирован. При каждом проходе алгоритма по внутреннему циклу, очередной наибольший элемент массива ставится на своё место в конце массива рядом с предыдущим «наибольшим элементом», а наименьший элемент перемещается на одну позицию к началу массива («всплывает» до нужной позиции как пузырёк в воде, отсюда и название алгоритма). 139 | 140 | * Эффективен для небольших массивов из-за сложности 141 | ```c 142 | void bubbleSort(int array[], int size) { 143 | bool swapped = true; 144 | int i; 145 | for (i = 1; i < size; i++) { 146 | swapped = false; //this flag is to check if the array is already sorted 147 | int j; 148 | for (j = 0; j < size - i; j++) { 149 | if (array[j] > array[j + 1]) { 150 | int tmp = array[j]; 151 | array[j] = array[j + 1]; 152 | array[j + 1] = tmp; 153 | swapped = true; 154 | } 155 | } 156 | if (swapped == false) { 157 | break; //if it is sorted then stop 158 | } 159 | } 160 | } 161 | ``` 162 | 163 | 164 | ## Сортировка выбором 165 | _selection sort_ 166 | `O(n^2)` 167 | 168 | На каждом шаге алгоритма мы выбираем один из элементов входных данных и вставляем его на нужную позицию в уже отсортированном списке, до тех пор, пока набор входных данных не будет исчерпан. Метод выбора очередного элемента из исходного массива произволен; может использоваться практически любой алгоритм выбора. Обычно (и с целью получения устойчивого алгоритма сортировки), элементы вставляются по порядку их появления во входном массиве. Приведенный ниже алгоритм использует именно эту стратегию выбора. 169 | 170 | Плюсы: 171 | 172 | * эффективен на небольших наборах данных, на наборах данных до десятков элементов может оказаться лучшим; 173 | * эффективен на наборах данных, которые уже частично отсортированы; 174 | * это устойчивый алгоритм сортировки (не меняет порядок элементов, которые уже отсортированы); 175 | * может сортировать список по мере его получения; 176 | * использует `O(1)` временной памяти, включая стек. 177 | 178 | Минусы: 179 | 180 | * может быть и устойчивым, и неустойчивым 181 | ```c 182 | int selectionSort(int array[], int size) { 183 | int i, j; 184 | int tmp; 185 | int min; 186 | for (i = 0; i < size - 1; i++) { 187 | min = i; //current minimum 188 | //find the global minimum 189 | for (j = i + 1; j < size; j++) { 190 | if (array[min] > array[j]) { 191 | min = j; // new minimum 192 | } 193 | } 194 | //swap array[i] and array[min] 195 | tmp = array[i]; 196 | array[i] = array[min]; 197 | array[min] = tmp; 198 | } 199 | return 0; 200 | } 201 | ``` 202 | 203 | 204 | ## Быстрая сортировка 205 | _сортировка Хоара, quicksort, qsort_ 206 | `O(n*log(n)), разделяй и властвуй` 207 | 208 | QuickSort является существенно улучшенным вариантом алгоритма сортировки с помощью прямого обмена (его варианты известны как «Пузырьковая сортировка» и «Шейкерная сортировка»), известного, в том числе, своей низкой эффективностью. Принципиальное отличие состоит в том, что в первую очередь производятся перестановки на наибольшем возможном расстоянии и после каждого прохода элементы делятся на две независимые группы. Любопытный факт: улучшение самого неэффективного прямого метода сортировки дало в результате один из наиболее эффективных улучшенных методов. 209 | Общая идея алгоритма состоит в следующем: 210 | 211 | 1. Выбрать из массива элемент, называемый опорным. Это может быть любой из элементов массива. 212 | 2. Сравнить все остальные элементы с опорным и переставить их в массиве так, чтобы разбить массив на три непрерывных отрезка, следующие друг за другом — «меньшие опорного», «равные» и «большие». 213 | 3. Для отрезков «меньших» и «больших» значений выполнить рекурсивно ту же последовательность операций, если длина отрезка больше единицы. 214 | 215 | На практике массив обычно делят не на три, а на две части, например, «меньшие опорного» и «равные и большие». Такой подход в общем случае эффективнее, так как упрощает алгоритм разделения. 216 | 217 | 218 | Достоинства: 219 | * Один из самых быстродействующих (на практике) из алгоритмов внутренней сортировки общего назначения. 220 | * Прост в реализации. 221 | * Требует лишь `O(lg n)` дополнительной памяти для своей работы. (Не улучшенный рекурсивный алгоритм в худшем случае `O(n)` памяти) 222 | * Хорошо сочетается с механизмами кэширования и виртуальной памяти. 223 | * Допускает естественное распараллеливание (сортировка выделенных подмассивов в параллельно выполняющихся подпроцессах). 224 | * Допускает эффективную модификацию для сортировки по нескольким ключам (в частности — алгоритм Седжвика для сортировки строк): благодаря тому, что в процессе разделения автоматически выделяется отрезок элементов, равных опорному, этот отрезок можно сразу же сортировать по следующему ключу. 225 | * Работает на связных списках и других структурах с последовательным доступом, допускающих эффективный проход как от начала к концу, так и от конца к началу. 226 | 227 | Недостатки: 228 | * Сильно деградирует по скорости (до `Theta(n^2)`) в худшем или близком к нему случае, что может случиться при неудачных входных данных. 229 | * Прямая реализация в виде функции с двумя рекурсивными вызовами может привести к ошибке переполнения стека, так как в худшем случае ей может потребоваться сделать `O(n)` вложенных рекурсивных вызовов. 230 | * Неустойчив 231 | ```c 232 | int partition(int a[], int l, int r) { 233 | int pivot, i, j, t; 234 | pivot = a[l]; 235 | i = l; j = r + 1; 236 | while (1) { 237 | do ++i; while (a[i] <= pivot && i <= r ); 238 | do --j; while (a[j] > pivot ); 239 | if (i >= j ) break; 240 | t = a[i]; a[i] = a[j]; a[j] = t; 241 | } 242 | t = a[l]; a[l] = a[j]; a[j] = t; 243 | return j; 244 | } 245 | 246 | void quickSort(int a[], int l, int r) { 247 | int j; 248 | if (l < r ) { 249 | // divide and conquer 250 | j = partition(a, l, r); 251 | quickSort(a, l, j - 1); 252 | quickSort(a, j + 1, r); 253 | } 254 | } 255 | ``` 256 | 257 | 258 | ### How to merge two sorted arrays into a sorted array? 259 | ```c++ 260 | public static int[] merge(int[] a, int[] b) { 261 | int[] answer = new int[a.length + b.length]; 262 | int i = 0, j = 0, k = 0; 263 | 264 | while (i < a.length && j < b.length) { 265 | if (a[i] < b[j]) 266 | answer[k++] = a[i++]; 267 | 268 | else 269 | answer[k++] = b[j++]; 270 | } 271 | 272 | while (i < a.length) 273 | answer[k++] = a[i++]; 274 | 275 | while (j < b.length) 276 | answer[k++] = b[j++]; 277 | 278 | return answer; 279 | } 280 | ``` 281 | 282 | 283 | ### Рекурсивная функция 284 | Функция, вызывающая саму себя. Вопрос о желательности использования рекурсивных функций в программировании неоднозначен: с одной стороны, рекурсивная форма может быть структурно проще и нагляднее, в особенности, когда сам реализуемый алгоритм по сути рекурсивен. Кроме того, в некоторых декларативных или чисто функциональных языках (таких как Пролог или Haskell) просто нет синтаксических средств для организации циклов, и рекурсия в них — единственный доступный механизм организации повторяющихся вычислений. С другой стороны, обычно рекомендуется избегать рекурсивных программ, которые приводят (или в некоторых условиях могут приводить) к слишком большой глубине рекурсии. Так, широко распространённый в учебной литературе пример рекурсивного вычисления факториала является, скорее, примером того, как не надо применять рекурсию, так как приводит к достаточно большой глубине рекурсии и имеет очевидную реализацию в виде обычного циклического алгоритма. 285 | 286 | Плюсы 287 | 288 | * Наглядность 289 | * Простота 290 | 291 | Минусы 292 | 293 | * Возможна большая глубина рекурсии, из-за которой может произойти быстрое переполнение стека и нехватка памяти. 294 | 295 | __Факториал__ 296 | ```c 297 | //O(n) 298 | int factorialRecursive(int value) { 299 | if (value == 1) { 300 | return value; 301 | } else { 302 | return value * factorialRecursive(value - 1); 303 | } 304 | } 305 | 306 | //O(n) 307 | int factorialIterative(int value) { 308 | int result = 1; 309 | for (int number = 1; number <= value; number++) { 310 | result *= number; 311 | } 312 | return result; 313 | } 314 | ``` 315 | 316 | __Последовательность Фибоначчи__ 317 | ```c 318 | //O(2^n) 319 | int fibonacciRecursive(int position) { 320 | int result = 0; 321 | if (position < 2) { 322 | result = position; 323 | } else { 324 | result = fibonacciRecursive(position - 1) + fibonacciRecursive(position - 2); 325 | } 326 | return result; 327 | } 328 | 329 | //O(n) 330 | int fibonacciIterative(int position) { 331 | int a = 1; 332 | int b = 1; 333 | int c; 334 | printf("%i\n%i\n", a, b); 335 | for (int i = 3; i <= position; i++) { 336 | c = a; 337 | a = b; 338 | b = c + b; 339 | printf("%i\n", b); 340 | } 341 | return b; 342 | } 343 | ``` 344 | 345 | Хвостовая рекурсия — частный случай рекурсии, при котором любой рекурсивный вызов является последней операцией перед возвратом из функции.[1] Подобный вид рекурсии примечателен тем, что может быть легко заменён на итерацию путём формальной и гарантированно корректной перестройки кода функции. Оптимизация хвостовой рекурсии путём преобразования её в плоскую итерацию реализована во многих оптимизирующих компиляторах. В некоторых функциональных языках программирования спецификация гарантирует обязательную оптимизацию хвостовой рекурсии. 346 | 347 | Типовой механизм реализации вызова функции основан на сохранении адреса возврата, параметров и локальных переменных функции в стеке и выглядит следующим образом: 348 | 349 | В точке вызова в стек помещаются параметры, передаваемые функции, и адрес возврата. 350 | Вызываемая функция в ходе работы размещает в стеке собственные локальные переменные. 351 | По завершении вычислений функция очищает стек от своих локальных переменных, записывает результат (обычно - в один из регистров процессора). 352 | Команда возврата из функции считывает из стека адрес возврата и выполняет переход по этому адресу. Одновременно стек очищается от параметров. 353 | Таким образом, при каждом рекурсивном вызове функции создаётся новый набор её параметров и локальных переменных, который вместе с адресом возврата размещается в стеке, что ограничивает максимальную глубину рекурсии объёмом стека. В чисто функциональных или декларативных (типа Пролога) языках, где рекурсия является единственным возможным способом организации повторяющихся вычислений, это ограничение становится крайне существенным, поскольку, фактически, превращается в ограничение на число итераций в любых циклических вычислениях, при превышении которого будет происходить переполнение стека. 354 | 355 | Нетрудно видеть, что необходимость расширения стека при рекурсивных вызовах диктуется требованием восстановления состояния вызывающего экземпляра функции (то есть её параметров, локальных данных и адреса возврата) после возврата из рекурсивного вызова. Но если рекурсивный вызов является последней операцией перед выходом из вызывающей функции и результатом вызывающей функции должен стать результат, который вернёт рекурсивный вызов, сохранение контекста уже не имеет значения — ни параметры, ни локальные переменные уже использоваться не будут, а адрес возврата уже находится в стеке. Поэтому в такой ситуации вместо полноценного рекурсивного вызова функции можно просто заменить значения параметров в стеке и передать управление на точку входа. До тех пор, пока исполнение будет идти по этой рекурсивной ветви, будет, фактически, выполняться обычный цикл. Когда рекурсия завершится (то есть исполнение пройдёт по терминальной ветви и достигнет команды возврата из функции) возврат произойдёт сразу в исходную точку, откуда произошёл вызов рекурсивной функции. Таким образом, при любой глубине рекурсии стек переполнен не будет. 356 | 357 | ```c 358 | int fac_times(int n, int acc) { 359 | return (n == 0) ? acc : fac_times(n - 1, acc * n); 360 | } 361 | int factorial(int n) { 362 | return fac_times(n, 1); 363 | } 364 | ``` 365 | -------------------------------------------------------------------------------- /Main/5_c_language.md: -------------------------------------------------------------------------------- 1 | - [Язык СИ](#язык-си) 2 | - [Битовые операции](#битовые-операции) 3 | - [Примеры битовых операций](#примеры-битовых-операций) 4 | - [Что такое указатель и ссылка и в чем разница](#что-такое-указатель-и-ссылка-и-в-чем-разница) 5 | - [Почему (NSError **) использует указатель на указатель](#почему-nserror-использует-указатель-на-указатель) 6 | - [How to return 2+ values from a function](#how-to-return-2+-values-from-a-function) 7 | - [What is the difference between char* const and const char*](#what-is-the-difference-between-char-const-and-const-char) 8 | - [Что значит n&(n – 1)](#что-значит-n-n–1) 9 | 10 | 11 | # Язык СИ. 12 | 13 | * Лаконичность и быстрота (почти как Ассемблер) 14 | * Переносимость на различные архитектуры 15 | * Набор низкоуровневых средств 16 | * Прямой доступ к памяти 17 | * Операции над битами 18 | * Адресная арифметика 19 | 20 | Си – универсальный язык программирования, считается удобным для системного программирования, хотя он удобен и для написания прикладных программ. Среди преимуществ языка Си следует отметить переносимость программ на компьютеры различной архитектуры и из одной операционной системы в другую, лаконичность записи алгоритмов, логическую стройность программ, а также возможность получить программный код, сравнимый по скорости выполнения с программами, написанными на языке ассемблера. Последнее связано с тем, что хотя Си является языком высокого уровня, имеющим полный набор конструкций структурного программирования, он также обладает набором низкоуровневых средств, обеспечивающих доступ к аппаратным средствам компьютера. 21 | Программа на Cи состоит из программных единиц одного типа – функций. Аргументы могут передаваться функциям посредством копирования значений этих аргументов; при этом вызванная функция не может изменить фактический аргумент в вызывающей подпрограмме. 22 | Возможен иной вариант – передача параметра по ссылке, когда явно передается указатель, т.е. адрес, при этом функция сможет изменить объект, на который ссылается указатель. 23 | В Си предусмотрен ряд операций низкого уровня: прямой доступ к памяти, операции над битами данных и адресной арифметики. 24 | Программы на языке Си компактны и гибки. Язык Си доверяет программисту и разрешает ему практически все; из-за этого Си нельзя считать языком надежного программирования, и вся ответственность за качество программы лежит на программисте, который должен знать особенности языка и его реализации. Программа, написанная на языке Си, состоит из операторов. Каждый оператор вызывает выполнение некоторых действий на соответствующем шаге выполнения программы. 25 | При написании операторов применяются латинские прописные и строчные буквы, цифры и специальные знаки. К таким знакам, например, относятся: точка `.`, запятая `,`, двоеточие `:`, точка с запятой `;` и др. Совокупность символов, используемых в языке, называется алфавитом языка. Программы оперируют с различными данными, которые могут быть простыми и структурированными. Простые данные - это целые и вещественные числа, символы и указатели (адреса объектов в памяти). Целые числа не имеют, а вещественные имеют дробную часть. Структурированные данные - это массивы и структуры. 26 | 27 | 28 | 29 | 30 | ## Битовые операции 31 | В своих программах вы не адресуете отдельные биты, а имеете дело с группами битов - байтами. Если представить байт как 8-разрядное целое число без знака, его биты соответствуют последовательным степеням `2`. 32 | 33 | 34 | 35 | Однако компьютерам удобнее иметь дело со степенями `2`. Программисты часто используют шестнадцатеричную систему (`16 = 2^4`) - особенно при работе с отдельными разрядами целых чисел. В качестве дополнительных цифр в шестнадцатеричной системе используются буквы `а`, `b`, `с`, `d`, `е` и `f`. Таким образом, счет в шестнадцатеричной системе выглядит так: `0 1 2 3 4 5 6 7 8 9 а b с d е f 10 11 ...` Числа, записанные в шестнадцатеричной системе, обозначаются префиксом `0х`. 36 | 37 | 38 | 39 | Один байт всегда может быть представлен шестнадцатеричным числом из двух цифр (например, `3с`). По этой причине шестнадцатеричные числа удобны для работы с двоичными данными. 40 | 41 | 42 | 43 | __Побитовое `И` (`AND`, `&`)__ 44 | 45 | `2` байта можно объединить поразрядной операцией `И` для создания третьего байта. В этом случае бит третьего байта равен `1` только в том случае, если оба соответствующих бита первых двух байтов равны `1`. 46 | ``` 47 | 0011 48 | 0101 49 | ---- 50 | 0001 51 | ``` 52 | Часто используется для обнуления некоторой группы разрядов. Например: 53 | ```c 54 | n = n & 0177; 55 | ``` 56 | обнуляет в `n` все разряды, кроме младших семи. 57 | 58 | __Побитовое `ИЛИ` (`OR`, `|`)__ 59 | 60 | 61 | 62 | Программа выдает результат объединения двух байтов поразрядной операцией `ИЛИ`: 63 | ``` 64 | Hex: 03c0 | 0a90 = 0bd 65 | Decimal: 0600 | 01690 = 0189 66 | ``` 67 | ``` 68 | 0011 69 | 0101 70 | ---- 71 | 0111 72 | ``` 73 | Применяют для установки разрядов; так, 74 | ```c 75 | х = х | SET_ON; 76 | ``` 77 | устанавливает единицы в тех разрядах `х`, которым соответствуют единицы в `SET_ON`. 78 | 79 | __Побитовое исключающее `ИЛИ` (сложение по модулю два, `XOR`, `^`)__ 80 | 81 | Исключающая операция `ИЛИ` объединяет два байта и создает третий байт. Бит результата равен `1` в том случае, если ровно один из двух соответствующих битов входных байтов равен `1`. 82 | ``` 83 | 0011 84 | 0101 85 | ---- 86 | 0110 87 | ``` 88 | 89 | __Побитовое отрицание (дополнение, унарный оператор `НЕ`, `NOT`, `~`)__ 90 | 91 | Дополнением к существующему байту называется байт, биты которого находятся в противоположном состоянии: все нули заменяются единицами, а все единицы заменяются нулями. 92 | ``` 93 | 0011 94 | ---- 95 | 1100 96 | ``` 97 | Унарный оператор `~` поразрядно "обращает" целое т.е. превращает каждый единичный бит в нулевой и наоборот. Например: 98 | ```c 99 | х = х & ~077 100 | ``` 101 | обнуляет в `х` последние `6` разрядов. Заметим, что запись `х & ~077` не зависит от длины слова, и, следовательно, она лучше, чем `х & 0177700`, поскольку последняя подразумевает, что `х` занимает `16` битов. Не зависимая от машины форма записи `~077` не потребует дополнительных затрат при счете, так как `~077` — константное выражение, которое будет вычислено во время компиляции. 102 | 103 | __Сдвиг влево `<<`__ 104 | 105 | При выполнении операции сдвига влево каждый бит смещается в направлении старшего бита. Биты, выходящие за пределы числа, теряются, а возникающие справа «пустоты» заполняются нулями. 106 | 107 | 108 | 109 | __Сдвиг вправо `>>`__ 110 | 111 | __Примеры битовых операций:__ 112 | 113 | 114 | 115 | 116 | 117 | ``` 118 | 67 & 114 = 66 119 | 67 | 114 = 115 120 | 67 ^ 114 = 49 121 | ~67 = 188 122 | ``` 123 | 124 | 125 | ## Что такое указатель и ссылка и в чем разница? 126 | Есть два способа обращения к функции – вызов по значению и вызов по ссылке. При вызове по значению создается копия аргумента и передается вызываемой функции. Изменение копии не влияют на значение оригинала в операторе вызова. Один из минусов этого способа – если передается большой элемент данных, то на его копирование может уйти дополнительное время. 127 | 128 | Ссылочный параметр – это псевдоним аргумента. 129 | ```c 130 | int &count; //count является ссылкой на int. 131 | ``` 132 | В вызове функции достаточно указать имя переменной и она будет передана по ссылке, тогда упоминание в теле вызываемой функции переменной по имени ее параметра в действительности является обращением к исходной переменной в вызывающей функции и эта исходная переменная может быть изменена непосредственно вызываемой функцией. Для передачи больших объектов используется константный ссылочный параметр, чтобы обеспечить защиту параметра, как при вызове по значению, и в то же время избежать накладных расходов при передаче копии большого объекта: 133 | ```c 134 | const int &count; 135 | ``` 136 | __Ссылка__ – это псевдоним для другой переменной и все операции, выполняемые с псевдонимом (ссылкой) выполняются на самом деле с истинной переменной. Псевдоним – другое имя переменной и для него не резервируется место в памяти. 137 | Если возвращение ссылки переменной объявлено в функции, то эта переменная должна быть объявлена внутри функции как статическая, иначе ссылка адресуется автоматической переменной, которая после выполнения функции уничтожается. 138 | 139 | __Указатель__ – переменная, которая содержит в качестве значения адрес памяти переменной, которая уже в свою очередь содержит значение. Т.о. имя переменной отсылает к значению прямо, а указатель – косвенно. 140 | ```c 141 | int y = 5; 142 | int *yPtr; 143 | yPtr = &y; 144 | ``` 145 | Теперь `yPtr` указывает на `y`. 146 | Операция `*` – операция косвенной адресации или операция разыменования. 147 | 148 | Аргументы можно передавать в функцию тремя способами: 149 | 150 | 1. Вызов по значению 151 | 2. Вызов по ссылке с аргументами ссылками 152 | 3. Вызов по ссылке с аргументами указателями 153 | 154 | Указатели как и ссылки тоже можно использовать для модификации одного или более значений переменных в вызывающем операторе, или передавать указатели на большие объекты данных, чтобы избежать расходов, сопутствующих передаче объектов по значению. 155 | 156 | `const` с указателем значит, что значение переменной не изменяется. 157 | 158 | 159 | ## Почему (NSError **) использует указатель на указатель? 160 | _Explanation 1:_ 161 | if you pass a pointer to an object to your function, the function can only modify what the pointer is pointing to. 162 | if you pass a pointer to a pointer to an object then the function can modify the pointer to point to another object. 163 | In the case of `NSError`, the function might want to create a new `NSError` object and pass you back a pointer to that `NSError` object. Thus, you need double indirection so that the pointer can be modified. 164 | 165 | _Explanation 2:_ 166 | A pointer to a pointer is a form of multiple indirection, or a chain of pointers. Normally, a pointer contains the address of a variable. When we define a pointer to a pointer, the first pointer contains the address of the second pointer, which points to the location that contains the actual value as shown below. 167 | 168 | 169 | 170 | A variable that is a pointer to a pointer must be declared as such. This is done by placing an additional asterisk in front of its name. For example, the following declaration declares a pointer to a pointer of type `int`: `int **var;` 171 | When a target value is indirectly pointed to by a pointer to a pointer, accessing that value requires that the asterisk operator be applied twice, as is shown below in the example: 172 | ```c 173 | int main () { 174 | 175 | int var; 176 | int *ptr; 177 | int **pptr; 178 | 179 | var = 3000; 180 | 181 | /* take the address of var */ 182 | ptr = &var; 183 | 184 | /* take the address of ptr using address of operator & */ 185 | pptr = &ptr; 186 | 187 | /* take the value using pptr */ 188 | printf("Value of var = %d\n", var); 189 | printf("Value available at *ptr = %d\n", *ptr); 190 | printf("Value available at **pptr = %d\n", **pptr); 191 | 192 | return 0; 193 | } 194 | ``` 195 | ``` 196 | Value of var = 3000 197 | Value available at *ptr = 3000 198 | Value available at **pptr = 3000 199 | ``` 200 | with a regular parameter, say `int`, you get a local copy 201 | 202 | with a pointer parameter, say `int*`, you can modify what it points to 203 | 204 | with a double pointer parameter, say `int**`, you can modify the pointer itself, i.e. 'repoint' it 205 | 206 | ## How to return 2+ values from a function? 207 | 208 | __In C:__ 209 | 210 | * Returning the address of the first element of a local array has undefined behavior (at least dereferencing it later is). You may use output parameters, that is, pass two pointers, and set the values inside: 211 | ```c 212 | void Calculate(int x, int y, int* prod, int* quot) { 213 | *prod = x*y; 214 | *quot = x/y; 215 | } 216 | ``` 217 | Usage: 218 | ```c 219 | int x = 10, y = 2, prod, quot; 220 | Calculate(x, y, &prod, ") 221 | ``` 222 | * Another thing you could do is pack your data into a struct 223 | 224 | ```c 225 | typedef struct { 226 | int prod; 227 | int quot; 228 | } product_and_quot; 229 | 230 | product_and_quot Calculate(int x, int y) { 231 | product_and_quot p = {x*y, x/y}; 232 | return p; 233 | } 234 | ``` 235 | __in Objective-C:__ 236 | 237 | * Pointers 238 | 239 | ```objectivec 240 | - (void)convertA:(float)a B:(float)b C:(float) intoX:(float *)xOut Y:(float *)yOut Z:(float)zOut { 241 | *xOut = 3*a + b; 242 | *yOut = 2*b; 243 | *zOut = a*b + 4*c; 244 | } 245 | ``` 246 | and call it like this: 247 | ```objectivec 248 | float x, y, z; 249 | [self convertA:a B:b C:c intoX:&x Y:&y Z:&z]; 250 | ``` 251 | * Another way is to create a struct and return it: 252 | 253 | ```objectivec 254 | struct XYZ { 255 | float x, y, z; 256 | }; 257 | 258 | - (struct XYZ)xyzWithA:(float)a B:(float)b C:(float)c { 259 | struct XYZ xyz; 260 | xyz.x = 3*a + b; 261 | xyz.y = 2*b; 262 | xyz.z = a*b + 4*c; 263 | return xyz; 264 | } 265 | ``` 266 | Call it like this: 267 | ```objectivec 268 | struct XYZ output = [self xyzWithA:a B:b C:c]; 269 | ``` 270 | * Double pointers with objects 271 | 272 | If you want to return more than one new object, your function should take pointers to the object pointer, thus: 273 | ```objectivec 274 | - (void)mungeFirst:(NSString **)stringOne andSecond:(NSString **)stringTwo { 275 | *stringOne = [NSString stringWithString:@"foo"]; 276 | *stringTwo = [NSString stringWithString:@"baz"]; 277 | } 278 | ``` 279 | * Blocks 280 | 281 | You can return two values with help of block: 282 | ```objectivec 283 | - (void)getUIControlles:(void (^)(UITextField *objTextFiled, UIView *objView))completionBlock { 284 | UITextField * textFiled = nil; 285 | /* 286 | do code here for textfiled 287 | */ 288 | UIView * viewDemo = nil; 289 | 290 | /* 291 | do code here for Uiview. 292 | */ 293 | 294 | completionBlock (textFiled, viewDemo); 295 | } 296 | 297 | - (void)testMethod { 298 | // Call function with following way. 299 | [self getUIControlles:^(UITextField *objTextFiled, UIView *objView) { 300 | // objTextFiled = This is your textfiled object 301 | // objView = This is your view object 302 | }]; 303 | } 304 | ``` 305 | 306 | 307 | ## What is the difference between char * const and const char *? 308 | 309 | Существует четыре способа передачи в функцию указателя 310 | 311 | 1. Неконстантный указатель на неконстантные данные 312 | 2. Неконстнатный указатель на константные данные 313 | 3. Константный указатель на неконстантные данные 314 | 4. Константный указатель на константные данные 315 | 316 | 317 | 318 | 319 | ## Что значит n&(n – 1)? 320 | It's figuring out if `n` is either `0` or an exact power of two. 321 | It works because a binary power of two is of the form `1000...000` and subtracting one will give you `111...111`. Then, when you `AND` those together, you get zero, such as with: 322 | ``` 323 | 1000 0000 0000 0000 324 | & 111 1111 1111 1111 325 | ==== ==== ==== ==== 326 | = 0000 0000 0000 0000 327 | ``` 328 | Any non-power-of-two input value will not give you zero when you perform that operation. 329 | For example, let's try all the 3-bit combinations: 330 | ``` 331 | <----- binary ----> 332 | n n n-1 n&(n-1) 333 | --- --- --- ------- 334 | 0 000 111 000 * 335 | 1 001 000 000 * 336 | 2 010 001 000 * 337 | 3 011 010 010 338 | 4 100 011 000 * 339 | 5 101 100 100 340 | 6 110 101 100 341 | 7 111 110 110 342 | ``` 343 | You can see that only `0` and the powers of two (`1`, `2` and `4`) result in a `000-false` bit pattern, all others are non-zero or `true`. 344 | See the full Bit Twiddling Hacks document for all sorts of other wonderful (or dastardly, depending on your viewpoint) hackery. 345 | -------------------------------------------------------------------------------- /Main/6_oop.md: -------------------------------------------------------------------------------- 1 | - [ООП](#ооп) 2 | - [История ООП](#история-ооп) 3 | - [Основные понятия ООП: абстракция, инкапсуляция, наследование, полиморфизм](#основные-понятия-ооп) 4 | - [Другие понятия ООП](#другие-понятия-ооп) 5 | - [В чем плюсы и минусы ООП](#в-чем-плюсы-и-минусы-ооп) 6 | 7 | 8 | # ООП 9 | 10 | ## История ООП 11 | ООП – парадигма программирования, в которой основными концепциями являются понятия объектов и классов. В центре ООП находится понятие объекта. Объект — это сущность, которой можно посылать сообщения, и которая может на них реагировать, используя свои данные. Объект — это экземпляр класса. Данные объекта скрыты от остальной программы. Сокрытие данных называется инкапсуляцией. Наличие инкапсуляции достаточно для объектности языка программирования, но ещё не означает его объектной ориентированности — для этого требуется наличие наследования. Но даже наличие инкапсуляции и наследования не делает язык программирования в полной мере объектным с точки зрения ООП. Основные преимущества ООП проявляются только в том случае, когда в языке программирования реализован полиморфизм; то есть возможность объектов с одинаковой спецификацией иметь различную реализацию. Первым языком программирования, в котором были предложены принципы объектной ориентированности, была Симула. В момент своего появления (в 1967 году), этот язык программирования предложил поистине революционные идеи: объекты, классы, виртуальные методы и др., однако это всё не было воспринято современниками как нечто грандиозное. Тем не менее, большинство концепций были развиты Аланом Кэйем и Дэном Ингаллсом в языке Smalltalk. Именно он стал первым широко распространённым объектно-ориентированным языком программирования. (C#, C++, Java, Ruby, PHP, Perl, Python). ООП дает возможность создавать расширяемые системы (extensible systems). Это одно из самых значительных достоинств ООП и именно оно отличает данный подход от традиционных методов программирования. Расширяемость (extensibility) означает, что существующую систему можно заставить работать с новыми компонентами, причем без внесения в нее каких-либо изменений. Компоненты могут быть добавлены на этапе выполнения. Smalltalk — объектно-ориентированный язык программирования с динамической типизацией, разработанный в Xerox PARC Аланом Кэйем, Дэном Ингаллсом, Тедом Кэглером, Адель Голдберг, и другими в 1970-х годах. Язык был представлен как Smalltalk-80. Smalltalk оказал большое влияние на развитие многих других языков, таких как: Objective-C, Actor, Java, Groovy и Ruby. Многие идеи 1980-х и 1990-х по написанию программ появились в сообществе Smalltalk. К ним можно отнести рефакторинг, шаблоны проектирования (применительно к ПО), карты «класс — обязанности — взаимодействие» и экстремальное программирование в целом. Си — язык программирования, разработанный в 1969—1973 годах сотрудниками Bell Labs Кеном Томпсоном и Деннисом Ритчи как развитие языка Би. Благодаря близости по скорости выполнения программ, написанных на Си, к языку ассемблера, этот язык получил широкое применение при создании системного программного обеспечения и прикладное программное обеспечение для решения широко круга задач. Язык программирования Си оказал существенное влияние на развитие индустрии программного обеспечения, а его синтаксис стал основой для таких языков программирования как C++, C# и Java. 12 | 13 | 14 | ## Основные понятия ООП: абстракция, инкапсуляция, наследование, полиморфизм. 15 | __Абстракция__ – это придание объекту характеристик, которые чётко определяют его концептуальные границы, отличая от всех других объектов. Основная идея состоит в том, чтобы отделить способ использования составных объектов данных от деталей их реализации в виде более простых объектов, подобно тому, как функциональная абстракция разделяет способ использования функции и деталей её реализации в терминах более примитивных функций, таким образом, данные обрабатываются функцией высокого уровня с помощью вызова функций низкого уровня. (Пример: говорить о предметах, не упоминая материалы, из которых они сделаны). Абстракция позволяет задействовать концепцию, игнорируя ее некоторые детали и работая с разными деталями на разных уровнях. Имея дело с составным объектом, вы имеете дело с абстракцией. Если вы рассматриваете объект как «дом», а не как комбинацию стекла, древесины и гвоздей, вы прибегаете к абстракции. Если вы рассматриваете множество домов как «город», вы прибегаете к другой абстракции. Базовые классы представляют собой абстракции, позволяющие концентрироваться на общих атрибутах производных классов и игно-рировать детали конкретных классов при работе с базовым классом. Удачный интерфейс класса — это абстракция, позволяющая сосредоточиться на интерфейсе, не беспокоясь о внутренних механизмах работы класса. Мы используем абстракции на каждом шагу. Если б, открывая или закрывая дверь, вы должны были иметь дело с отдельными волокнами древесины, молекулами лака и стали, вы вряд ли смогли бы войти в дом или выйти из него. Абстракция — один из главных способов борьбы со сложностью реального мира. 16 | Слой абстрагирования (или уровень абстракции) — это способ уйти от деталей реализации конкретного множества функций. 17 | 18 | 19 | 20 | __Инкапсуляция__ – скрытие методов и переменных от других методов или переменных или других частей программы. Сокрытие реализации целесообразно применять в следующих целях: 21 | 22 | * При необходимости максимальной локализации предстоящих изменений, когда изменяется только работа объекта, а не программы; 23 | * При необходимости предсказания предстоящих изменений и их последствий; 24 | * При необходимости очистки глобальной области видимости. 25 | 26 | Когда абстракция нас покидает, на помощь приходит инкапсуляция. Абстракция говорит: «Вы можете рассмотреть объект с общей точки зрения». Инкапсуляция добавляет: «Более того, вы не можете рассмотреть объект с иной точки зрения». 27 | Продолжим нашу аналогию: инкапсуляция позволяет вам смотреть на дом, но не дает подойти достаточно близко, чтобы узнать, из чего сделана дверь. Инкапсуляция позволяет вам знать о существовании двери, о том, открыта она или заперта, но при этом вы не можете узнать, из чего она сделана (из дерева, стекловолокна, стали или другого материала), и уж никак не сможете рассмотреть отдельные волокна древесины. 28 | 29 | __Наследование__ – процесс, посредством которого один объект может приобретать свойства другого. Точнее, объект может наследовать основные свойства другого объекта и добавлять к ним черты, характерные только для него. Польза наследования в том, что оно дополняет идею абстракции. Абстракция позволяет представить объекты с разным уровнем детальности. Если помните, на одном уровне мы рассматривали дверь как набор определенных типов молекул, на втором — как набор волокон древесины, а на третьем — как что􏰀то, что защищает нас от воров. Древесина имеет определенные свойства — скажем, вы можете распилить ее пилой или склеить столярным клеем, — при этом и плинтусы, и подоконники имеют общие свойства древесины, но вместе с тем и некоторые специфические свойства. Наследование упрощает программирование, позволяя создать универсальные методы для выполнения всего, что основано на общих свойствах дверей, и затем написать специфические методы для выполнения специфических операций над конкретными типами дверей. Некоторые операции, такие как `Open()` или `Close()`, будут универсальными для всех дверей: внутренних, входных, стеклянных, стальных — каких угодно. Поддержка языком операций вроде `Open()` или `Close()` при отсутствии информации о конкретном типе двери вплоть до периода выполнения называется полиморфизмом. Объектно-ориентированные языки, такие как C++, Java и более поздние версии Microsoft Visual Basic, поддерживают и наследование, и полиморфизм. 30 | В объектно-ориентированном программировании под агрегированием (также называемом композицией или включением) подразумевают методику создания нового класса из уже существующих классов путём включения, называемого также делегированием. Об агрегировании также часто говорят как об «отношении принадлежности» по принципу «у машины есть корпус, колёса и двигатель». Вложенные объекты нового класса обычно объявляются закрытыми, что делает их недоступными для прикладных программистов, работающих с классом. С другой стороны, создатель класса может изменять эти объекты, не нарушая при этом работы существующего клиентского кода. Кроме того, замена вложенных объектов на стадии выполнения программы позволяет динамически изменять её поведение. Механизм наследования такой гибкостью не обладает, поскольку для производных классов устанавливаются ограничения, проверяемые на стадии компиляции. На базе агрегирования реализуется методика делегирования, когда поставленная перед внешним объектом задача перепоручается внутреннему объекту, специализирующемуся на решении задач такого рода. 31 | Агрегация (агрегирование по ссылке) — отношение «часть-целое» между двумя равноправными объектами, когда один объект (контейнер) имеет ссылку на другой объект. Оба объекта могут существовать независимо: если контейнер будет уничтожен, то его содержимое — нет. 32 | Композиция (агрегирование по значению) — более строгий вариант агрегирования, когда включаемый объект может существовать только как часть контейнера. Если контейнер будет уничтожен, то и включённый объект тоже будет уничтожен. 33 | ```objectivec 34 | @interface Unicycle : NSObject { 35 | Pedal *pedal; 36 | Tire *tire; 37 | } 38 | @end 39 | ``` 40 | 41 | (Абстрактный класс белым цветом) 42 | 43 | _Как имитировать множественное наследование?_ 44 | 45 | Композиция: 46 | ```objectivec 47 | @interface ClassA : NSObject { 48 | } 49 | - (void)methodA; 50 | @end 51 | 52 | @interface ClassB : NSObject { 53 | } 54 | 55 | - (void)methodB; 56 | @end 57 | 58 | @interface MyClass : NSObject { 59 | ClassA *a; 60 | ClassB *b; 61 | } 62 | - (id)initWithA:(ClassA *)anA b:(ClassB *)aB; 63 | - (void)methodA; 64 | - (void)methodB; 65 | @end 66 | ``` 67 | __Полиморфизм__ – возможность объектов с одинаковой спецификацией иметь различную реализацию (использование одного имени для решения двух или более схожих, но технически разных задач). Если функция описывает разные реализации (возможно, с различным поведением) для ограниченного набора явно заданных типов и их комбинаций, это называется ситуативным полиморфизмом (ad hoc polymorphism). Ситуативный полиморфизм поддерживается во многих языках посредством перегрузки функций и методов. 68 | Если же код написан отвлеченно от конкретного типа данных и потому может свободно использоваться с любыми новыми типами, имеет место параметрический полиморфизм. Некоторые языки совмещают различные формы полиморфизма, порой сложным образом, что формирует самобытную идеологию в них и влияет на применяемые методологии декомпозиции задач. Например, в Smalltalk любой класс способен принять сообщения любого типа, и либо обработать его самостоятельно (в том числе посредством интроспекции), либо ретранслировать другому классу — таким образом, несмотря на широкое использование перегрузки функций, формально любая операция является неограниченно полиморфной и может применяться к данным любого типа. 69 | 70 | 71 | ### Другие понятия ООП 72 | __Конструктор__ 73 | 74 | В объектно-ориентированном программировании конструктор класса (от англ. constructor, иногда сокращают ctor) — специальный блок инструкций, вызываемый при создании объекта. 75 | Конструктор схож с методом, но отличается от метода тем, что не имеет явным образом определённого типа возвращаемых данных, не наследуется, и обычно имеет различные правила для рассматриваемых модификаторов. Конструкторы часто выделяются наличием одинакового имени с именем класса, в котором объявляется. Их задача — инициализировать члены объекта и определить инвариант класса, сообщив в случае некорректности инварианта. Корректно написанный конструктор оставит объект в «правильном» состоянии. Неизменяемые объекты тоже должны быть проинициализированы конструктором. 76 | В большинстве языков конструктор может быть перегружен, что позволяет использовать несколько конструкторов в одном классе, причём каждый конструктор может иметь различные параметры. 77 | 78 | __Деструктор__ 79 | 80 | Вызывается при уничтожении объекта. Он обычно используется для освобождения памяти. 81 | 82 | __Виртуальный метод__ 83 | 84 | В объектно-ориентированном программировании метод (функция) класса, который может быть переопределён в классах-наследниках так, что конкретная реализация метода для вызова будет определяться во время исполнения. Таким образом, программисту необязательно знать точный тип объекта для работы с ним через виртуальные методы: достаточно лишь знать, что объект принадлежит классу или наследнику класса, в котором метод объявлен. Виртуальные методы — один из важнейших приёмов реализации полиморфизма. Они позволяют создавать общий код, который может работать как с объектами базового класса, так и с объектами любого его класса-наследника. При этом базовый класс определяет способ работы с объектами и любые его наследники могут предоставлять конкретную реализацию этого способа. В некоторых языках программирования, например в Java, нет понятия виртуального метода, данное понятие следует применять лишь для язы-ков, в которых методы родительского класса не могут быть переопределены по умолчанию, а только с помощью некоторых вспомогательных ключевых слов. В некоторых же (как, например, в Python), все методы — виртуальные. 85 | Базовый класс может и не предоставлять реализации виртуального метода, а только декларировать его существование. Такие методы без реализации называются «чистыми виртуальными» (перевод англ. pure virtual) или абстрактными. Класс, содержащий хотя бы один такой метод, тоже будет абстрактным. Объект такого класса создать нельзя (в некоторых языках допускается, но вызов абстрактного метода при-ведёт к ошибке). Наследники абстрактного класса должны предоставить реализацию для всех его абстрактных методов, иначе они, в свою очередь, будут абстрактными классами. 86 | Для каждого класса, имеющего хотя бы один виртуальный метод, создаётся таблица виртуальных методов. Каждый объект хранит указатель на таблицу своего класса. Для вызова виртуального метода используется такой механизм: из объекта берётся указатель на соответствующую таблицу виртуальных методов, а из неё, по фиксированному смещению, — указатель на реализацию метода, используемого для данного класса. При использовании множественного наследования ситуация несколько усложняется за счёт того, что таблица виртуальных методов становится нелинейной. 87 | __Принцип единственной обязанности__ (Single responsibility principle) обозначает, что каждый объект должен иметь одну обязанность и эта обязанность должна быть полностью инкапсулирована в класс. Все его сервисы должны быть направлены исключительно на обеспечение этой обязанности. 88 | 89 | 90 | ## В чем плюсы и минусы ООП? 91 | __Общие положения__ 92 | 93 | _Преимущества_ 94 | 95 | * Классы позволяют проводить конструирование из полезных компонент, обладающих простыми инструментами, что дает возможность абстрагироваться от деталей реализации. 96 | 97 | _Недостатки_ 98 | 99 | * ООП порождает огромные иерархии классов, что приводит к тому, что функциональность расползается или, как говорят, размывается по базовым и производным членам класса, и отследить логику работы того или иного метода становится сложно. 100 | 101 | __Полиморфизм__ 102 | 103 | _Преимущества_ 104 | 105 | * Можно создавать новые классы с помощью протокола, «ведущие себя» аналогично родственным, что, в свою очередь, позволяет достигнуть расширяемости и модифицируемости, что помогает снижать сложность программ, разрешая использование того же интерфейса для задания единого класса действий. "Один интерфейс, множество методов" 106 | * Возможность создавать переменные и методы с одинаковым именем, но ведущие себя по-разному в зависимости от контекста (локальные переменные и перекрытие методов) 107 | * Обработка разнородных структур данных. Программы могут работать, не утруждая себя изучением вида объектов. Новые виды могут быть добавлены в любой момент. 108 | ```objectivec 109 | for (id object in array) { 110 | NSLog(@"%@", object); 111 | } 112 | ``` 113 | * Реализация родовых компонент. Алгоритмы можно обобщать до такой степени, что они уже смогут работать более, чем с одним видом объектов. 114 | Доведение полуфабрикатов. Компоненты нет надобности подстраивать под определенное приложение. Их можно сохранять в библиотеке в виде полуфабрикатов (semifinished products) и расширять по мере необходимости до различных законченных продуктов. 115 | Расширение фреймворка. Независимые от приложения части предметной области могут быть реализованы в виде фреймворка и в дальнейшем расширены за счет добавления частей, специфичных для конкретного приложения. 116 | 117 | _Недостатки_ 118 | 119 | * На скорости выполнения программ может неблагоприятно сказаться реализация полиморфизма, которая основана на механизмах позднего связывания вызова метода с конкретной его реализацией в одном из производных классов. 120 | * Многоразовое использование требует от программиста познакомиться с большими библиотеками классов. А это может оказаться сложнее, чем даже изучение нового языка программирования. Библиотека классов фактически представляет собой виртуальный язык, который может включать в себя сотни типов и тысячи операций. 121 | * В некоторых языках все данные являются объектами, в том числе и элементарные типы, а это не может не приводить к дополнительным расходам памяти и процессорного времени. 122 | * Изменение поведения во время выполнения. На этапе выполнения один объект может быть заменен другим. Это может привести к изменению алгоритма, в котором используется данный объект. 123 | 124 | __Инкапсуляция__ 125 | 126 | _Преимущества_ 127 | 128 | * Сокрытие данных от несанкционированного доступа 129 | * Инкапсуляция повышает надежность работы программного кода, поскольку гарантирует, что определенные данные не могут быть изменены за пределами содержащего их класса. 130 | 131 | _Недостатки_ 132 | 133 | * Функции представляют собой черные ящики, которые трансформируют ввод в вывод. Если я понимаю ввод и вывод, то я понимаю функцию. Это не означает, что я могу написать эту функцию. 134 | * В то время как состояние в языках программирования является нежелательным, реальный мир богат на состояния. Я очень интересуюсь состоянием моего банковского счета. И когда я вкладываю или снимаю с него деньги, я ожидаю, что его состояние будет корректно обновлено. Выбранный ООЯП подход “спрятать состояние от программиста” является наихудшим возможным выбором. Вместо показа состояния и поиска путей для минимизации неудобств от него, они прячут его поглубже. 135 | * Очень трудно изучать классы, не имея возможности их «пощупать». Только с приобретением мало-мальского опыта можно уверенно себя почувствовать при работе с использованием ООП. Поэтому проектирование классов — задача куда более сложная, чем их использование. Проектирование класса, как и проектирование языка, требует большого опыта. Это итеративный процесс, где приходится учиться на своих же ошибках. 136 | 137 | __Наследование__ 138 | 139 | _Преимущества_ 140 | 141 | * Когда вас почти устраивает какой-то класс, вы можете создать потомка и переопределить какую-то часть его функциональности. 142 | * Лаконичность абстракции данных, созданной с помощью наследования, является преимуществом. Используя наследование, не обязательно писать весь код для доступа к функциям базового класса. По этой причине реализации с использованием наследования (как это было в нашем случае) значительно меньше по объему, если сравнить их с композицией. 143 | 144 | _Недостатки_ 145 | 146 | * Унаследовавшись от одного предка, класс уже не может наследоваться от других. Изменение предка так же становится опасным. 147 | * О степени понятности кода судить трудно. Чтобы точно знать, какие операции разрешены для новой структуры, программист должен рассмотреть объявление ис-ходной структуры. Трудность состоит в следующем: чтобы понять класс, сконструированный с помощью наследования, программист должен постоянно переключаться «взад-вперед» между двумя (или более) описаниями классов. Она известна как проблема «вверх-вниз». В сложных иерархиях классов поля и методы обычно наследуются с разных уровней. И не всегда легко определить, какие поля и методы фактически относятся к данному классу. 148 | * Наследование – уничтожение инкапсуляции. Любой класс всегда неявно объявляет свой интерфейс — то, что доступно при использовании класса извне. Если у нас есть класс Ключ и у него публичный метод Открыть, который вызывает приватные методы Вставить, Повернуть и Вынуть, то интерфейс класса Ключ состоит из метода Открыть. Когда мы унаследуем какой-то класс от класса Ключ, он унаследует этот интерфейс. Кроме этого интерфейса, у класса есть также реализация — методы Вставить, Повернуть, Вынуть и их вызов в методе Открыть. Наследники Ключа наследуют вместе с интерфейсом и реализацию. И вот здесь таятся проблемы. 149 | -------------------------------------------------------------------------------- /Main/9_objectivec.md: -------------------------------------------------------------------------------- 1 | - [Objective-C](#objective-c) 2 | - [Transparent and opaque data types](#transparent-and-opaque-data-types) 3 | - [Toll-Free Bridged Types](#toll-free-bridged-types) 4 | - [Директивы компилятора](#директивы-компилятора) 5 | 6 | 7 | # Objective-C 8 | Компилируемый язык программирования, используемый корпорацией Apple, построенный на основе языка Си и парадигм Smalltalk. В частности, объектная модель построена в стиле Smalltalk — то есть объектам посылаются сообщения. Язык Objective-C является надмножеством языка Си, поэтому Си-код полностью понятен компилятору Objective-C. Компилятор Objective-C доступен на большинстве основных платформ. Язык используется в первую очередь для Mac OS X (Cocoa) и GNUstep — реализаций объектно-ориентированного интерфейса OpenStep. Также язык используется для iOS (Cocoa Touch). Objective-C был создан Брэдом Коксом в начале 1980-х в его компании Stepstone. Он искал возможность собирать программы из готовых компонентов (объектов), подобно тому как сложные электронные устройства могут быть легко собраны из набора готовых интегральных микросхем. При этом такой язык должен быть достаточно простым и основанным на языке Си, чтобы облегчить переход разработчиков на него. Таким образом, Objective-C является именно расширением языка Си — в язык Си просто добавлены новые возможности для объектно-ориентированного программирования. При этом любая программа на Си является программой и на Objective-C. 9 | * Мультипарадигма́льный язы́к программи́рования — как правило, язык программирования, который был разработан специально как инструмент мультипарадигмального программирования, то есть изобразительные возможности которого изначально предполагалось унаследовать от нескольких, чаще всего неродственных языков. Иногда термин мультипарадигмальный язык программирования определяют как «язык, который поддерживает больше чем одну парадигму программирования». Цель разработки мультипарадигмальных языков программирования состоит, как правило, в том, чтобы позволить программистам использовать лучший инструмент для работы, признавая, что никакая парадигма не решает все проблемы самым лёгким или самым эффективным способом. 10 | * Рефлексивно-ориентированный – в информатике отражение или рефлексия (синоним интроспекция, англ. reflection) означает процесс, во время которого программа может отслеживать и модифицировать собственную структуру и поведение во время выполнения. Парадигма программирования, положенная в основу отражения, называется рефлексивным программированием. An object refers to its class to get various information about itself, particularly what code to run to handle each action. 11 | * Message-oriented – вызовы метода интерпретируются не как вызов функции (хотя к этому обычно все сводится), а именно как посылка сообщения (с именем и аргументами) объекту, подобно тому, как это происходит в Smalltalk-е. Такой подход дает целый ряд плюсов — так, любому объекту можно послать любое сообщение. Объект может вместо обработки сообщения просто переслать его другому объекту для обработки (так называемое делегирование), в частности именно так можно легко реализовать распределенные объекты (то есть объекты, находящиеся в различных адресных пространствах и даже на разных компьютерах). The receiver is an object, and the message tells it what to do. In source code, the message is simply the name of a method and any arguments that are passed to it. When a message is sent, the runtime system selects the appropriate method from the receiver’s repertoire and invokes it. Object can contain state, which in practical terms means that they can contain data and references to other objects. In implementation and use, state usually consists of member variables, instance data, or whatever terminology you use. Can receive messages sent from other objects. Can send messages to other objects. 12 | * Runtime-oriented – динамичность, целый ряд решений, обычно принимаемых на этапе компиляции, здесь откладывается непосредственно до этапа выполнения. Примеры использования библиотеки рантайма - не рефлексии напрямую - получения списка всех наследников класса, маппинг объекта в словарь, динамическое добавление свойства в объект для динамических баз данных (это уже совсем рефлексия), свиззлинг для добавления дополнительной логики для методов системных фреймворков. 13 | * Dynamic Typing – The id type is completely nonrestrictive. By itself, it yields no information about an object, except that it is an object. At some point, a program needs to find more specific information about the objects it contains—what the object’s instance variables are, what methods it can perform, and so on. Since the id type designator can’t supply this information to the compiler, each object has to be able to supply it at runtime. This is possible because every object carries with it an isa instance variable that identifies the object’s class—what kind of object it is. Objects are thus dynamically typed at runtime. Whenever it needs to, the runtime system can find the exact class that an object belongs to, just by asking the object. Dynamic typing in Objective-C serves as the foundation for dynamic binding. A crucial difference between function calls and messages is that a function and its arguments are joined together in the compiled code, but a message and a receiving object aren’t united until the program is running and the message is sent. Therefore, the exact method that’s invoked to respond to a message can only be determined at runtime, not when the code is compiled. This dynamic binding of methods to messages works hand-in-hand with polymorphism to give object-oriented programming much of its flexibility and power. Since each object can have its own version of a method, a program can achieve a variety of results, not by varying the message itself, but by varying just the object that receives the message. This can be done as the program runs; receivers can be decided “on the fly” and can be made dependent on external factors such as user actions. The compiler creates just one accessible object for each class, a class object that knows how to build new objects belonging to the class. (For this reason it’s traditionally called a “factory object.”) The class object is the compiled version of the class; the objects it builds are instances of the class. The objects that do the main work of your program are instances created by the class object at runtime. Утиная типизация – границы использования объекта определяются его текущим набором методов и свойств, в противоположность наследованию от определённого класса. То есть считается, что объект реализует интерфейс, если он содержит все методы этого интерфейса, независимо от связей в иерархии наследования и принадлежности к какому-либо конкретному классу. «Если нечто выглядит как утка, плавает как утка и крякает как утка, то это, наверное, и есть утка» 14 | 15 | 16 | ## Transparent and opaque data types 17 | In computer science, an opaque data type is a data type whose concrete data structure is not defined in an interface. This enforces information hiding, since its values can only be manipulated by calling subroutines that have access to the missing information. The concrete representation of the type is hidden from its users, and the visible implementation is incomplete. A data type whose representation is visible is called transparent. Opaque data types are frequently used to implement abstract data types. 18 | Some languages, such as C, allow the declaration of opaque records (structs), whose size and fields are hidden from the client. The only thing that the client can do with an object of such a type is to take its memory address, to produce an opaque pointer. If the information provided by the interface is sufficient to determine the type's size, then clients can declare variables, fields, and arrays of that type, assign their values, and possibly compare them for equality. This is usually the case for opaque pointers. 19 | 20 | 21 | ## Toll-Free Bridged Types 22 | There are a number of data types in the Core Foundation framework and the Foundation framework that can be used interchangeably. Data types that can be used interchangeably are also referred to as toll-free bridged data types. This means that you can use the same data structure as the argument to a Core Foundation function call or as the receiver of an Objective-C message invocation. But not all data types are toll-free bridged, even though their names might suggest that they are. Through toll-free bridging, in a method where you see for example an `NSLocale *parameter`, you can pass a `CFLocaleRef`, and in a function where you see a `CFLocaleRef` parameter, you can pass an `NSLocale` instance. You also have to provide other information for the compiler: first, you have to cast one type to the other; in addition, you may have to indicate the object lifetime semantics. The compiler understands Objective-C methods that return Core Foundation types and follow the historical Cocoa naming conventions. For example, the compiler knows that, in iOS, the `CGColor` returned by the `CGColor` method of `UIColor` is not owned. You must still use an appropriate type cast, as illustrated by this example: 23 | ```objectivec 24 | NSMutableArray *colors = [NSMutableArray arrayWithObject:(id)[[UIColor darkGrayColor] CGColor]]; 25 | [colors addObject:(id)[[UIColor lightGrayColor] CGColor]]; 26 | ``` 27 | The compiler does not automatically manage the lifetimes of Core Foundation objects. You tell the compiler about the ownership semantics of objects using either a cast (defined in `objc/runtime.h`) or a Core Foundation-style macro (defined in `NSObject.h`): 28 | * `__bridge` transfers a pointer between Objective-C and Core Foundation with no transfer of ownership 29 | * `__bridge_retained` or `CFBridgingRetain` casts an Objective-C pointer to a Core Foundation pointer and also transfers ownership to you. You are responsible for calling `CFRelease` or a related function to relinquish ownership of the object. 30 | * `__bridge_transfer` or CFBridgingRelease moves a non-Objective-C pointer to Objective-C and also transfers ownership to ARC. ARC is responsible for relinquishing ownership of the object. 31 | 32 | 33 | ## Директивы компилятора 34 | `@implementation` Определяет начало определения (реализации) класса или категории. 35 | 36 | `@class` Используется для предварительного объявления класса. При использовании этой директивы класс помечается как известный, даже без загрузки заголовочного файла. 37 | 38 | `@protocol` Используются для объявления протокола. Кроме того, протокол может адаптировать другие протоколы. 39 | 40 | `@required` (по-умолчанию) Определяет методы, которые следуют после директивы как обязательные. 41 | 42 | `@optional` Определяет методы, которые следуют после директивы как необязательные. Классы, которые поддерживают протокол, могут сами решать — реализовывать эти методы или нет. Классы, которые используют необязательные методы протокола, должны делать проверку на существование. 43 | 44 | `@public` Определяет, что переменные экземпляра, следующие за директивой будут доступны публично. Публичные переменные могут быть прочтены и изменены с помощью следующей конструкции: `someObject->aPublicVariable = 10;` 45 | 46 | `@package` Определяет, что переменные экземпляра, следующие за директивой будут публично доступны в библиотеке, которая определяет класс, но закрытыми за пределами этой библиотеки. Важное замечание, это справедливо только для 64-разрядных систем. На 32-разрядных системах имеет то же значение, что и `@public` 47 | 48 | `@protected` (по умолчанию) Определяет, что переменные экземпляра, следующие за директивой, будут доступны только для класса и его потомков. 49 | 50 | `@private` Определяет, что переменные экземпляра, следующие за директивой, будут доступны только в пределах данного класса 51 | 52 | `@property` Определяет свойство, которое может быть использовано с помощью точечной нотации. За директивой `@property` могут следовать необязательные круглые скобки, которые содержат дополнительные ключевые слова (модификаторы), которые определяют поведение свойства. 53 | 54 | `@synthesize` Дает указание компилятору, что необходимо автоматически сгенерировать сеттеры и геттеры для данных (разделенных запятой) свойств. Сеттеры и геттеры автоматически создаются согласно указанным в объявлении свойства директивам. Если переменные экземпляра называ-ются не так, как указано после директивы `@property`, вы можете соединить их с помощью знака равенства 55 | 56 | `@dynamic` Cообщает компилятору, что требуемые сеттеры и геттеры для данных свойств будут реализованы вручную или динамически во время выполнения. При доступе к таким свойствам, компилятор не будет выдавать предупреждений, даже если требуемые сеттеры и геттеры не реализованы. Вы можете использовать такие свойства, когда хотите, чтобы сеттеры и геттеры выполняли какойто специфичный для вас код. 57 | 58 | `@try` Defines a block of code that will be tested to determine if an exception should be thrown. 59 | 60 | `@catch()` Defines a block of code for handling a thrown exception. Takes an argument, typically of type `NSException`, but can be of other types. 61 | 62 | `@finally` Defines a block of code that gets executed whether an exception is thrown or not. This code will always be executed. 63 | 64 | `@throw` Throws an exception. Earlier, we mentioned that you can throw exceptions from objects other than `NSException` instances, but that you should avoid doing so. The reason is that not every Cocoa framework catches exceptions thrown by objects other than `NSException`. To ensure that Cocoa works right with your exceptions, you should throw `NSException` objects only. Think of it like the old saying that you don’t have to floss all your teeth, just the ones you want to keep. You’ll typically use `@try`, `@catch`, and `@finally` together in one structure. It goes a little something like this: 65 | ```objectivec 66 | @try { 67 | // code you want to execute that might throw an exception. 68 | } 69 | @catch (NSException *exception) 70 | { 71 | // code to execute that handles exception 72 | } 73 | @finally { 74 | // code that will always be executed. Typically for cleanup. 75 | } 76 | ``` 77 | `@synchronized` Заключает блок кода в мьютекс. Обеспечивает гарантию того, что блок кода и объект блокировки будут доступны только из одного потока в момент времени. 78 | 79 | `@autoreleasepool` В тех приложения, в которых вы используете автоматический подсчет ссылок (ARC), вы должны использовать `@autoreleasepool` как замену для `NSAutoreleasePool`. И вообще, `@autoreleasepool` примерно в 6 раз быстрее, чем `NSAutoreleasePool`, поэтому Apple рекомендует использовать его даже для не-ARC приложений. Кроме того, вы не должны определять переменную внутри блока `@autoreleasepool` и затем продолжать использовать ее после. Подобный код должен быть исключен. 80 | 81 | `@selector` Возвращает специальный тип селекторов SEL выбранного метода Objective-C. Генерирует предупреждение компилятора, если метода не объявлен или не существует. Это имя метода закодированное специальным образом, используемым Objective-C для быстрого поиска. Указание компилятору на селектор происходит при помощи директивы `@selector(methodName)` 82 | 83 | `@encode` Возвращает кодировку типа. 84 | 85 | `@compatibility_alias` Позволяет вам задать псевдоним для существующего класса. Первый параметр — имя псевдонима для имени класса, класса с таким именем не должно существовать. Второй параметр — имя существующего класса, для которого создается псевдоним. 86 | 87 | `@"some text";` Объявляет константный объект класса NSString. Для таких строк не требуется вызывать `retain` или `release`. 88 | 89 | `@import` Модуль прекомпилированных заголовков, позволяющий экономить время по сравнению с компиляцией заголовков при `#import`. Не надо линковать фреймворк. 90 | 91 | ```objectivec 92 | #import //is the same as 93 | @import Cocoa; 94 | ``` 95 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | * [Основные понятия программирования](Main/1_basics.md) 4 | * [Структуры данных](Main/2_data_structures.md) 5 | * [Алгоритмы](Main/3_algorithms.md) 6 | * [Коллекции в Objective-C](Main/4_objectivec_collections.md) 7 | * [Язык СИ](Main/5_c_language.md) 8 | * [ООП](Main/6_oop.md) 9 | * [Паттерны проектирования](Main/7_design_patterns.md) 10 | * [iOS](Main/8_ios.md) 11 | * [Objective-C](Main/9_objectivec.md) 12 | * [Memory Management](Main/10_memory_management.md) 13 | * [Runtime](Main/11_runtime.md) 14 | * [Multithreading and Concurrency](Main/12_multithreading_concurrency.md) 15 | * [Networking](Main/13_networking.md) 16 | * [Data](Main/14_data.md) 17 | * [Блоки](Main/15_blocks.md) 18 | * [Autolayout](Main/16_autolayout.md) 19 | * [Тестирование](Main/17_testing.md) 20 | * [Swift](Main/18_swift.md) 21 | * [Общие вопросы](Main/19_general_questions.md) 22 | * [Задачи](Main/20_tasks.md) 23 | * [Неотвеченные вопросы](Main/21_to_do.md) 24 | --------------------------------------------------------------------------------