{"id":306740,"date":"2020-07-10T09:00:42","date_gmt":"2020-07-10T09:00:42","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=306740"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=306740","title":{"rendered":"\u0414\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0439 MVVM \u043d\u0430 \u0445\u0430\u043a\u043d\u0443\u0442\u044b\u0445 \u044d\u043a\u0441\u0442\u0435\u043d\u0448\u0435\u043d\u0430\u0445"},"content":{"rendered":"\n<div class=\"post__text post__text-html post__text_v1\" id=\"post-content-body\" data-io-article-url=\"https:\/\/habr.com\/ru\/company\/tinkoff\/blog\/509014\/\">\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/77\/sp\/gj\/77spgjvzw0oo-bnch77pf0usvoe.png\"><\/p>\n<p>  <\/p>\n<p>\u041c\u043d\u043e\u0433\u043e \u043b\u0435\u0442 \u043f\u043e\u0434\u0440\u044f\u0434 \u044f, \u043f\u043e\u043c\u0438\u043c\u043e \u0432\u0441\u0435\u0433\u043e \u043f\u0440\u043e\u0447\u0435\u0433\u043e, \u0437\u0430\u043d\u0438\u043c\u0430\u043b\u0441\u044f \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u043e\u0439 MVVM \u0432 \u0441\u0432\u043e\u0438\u0445 \u0440\u0430\u0431\u043e\u0447\u0438\u0445 \u0438 \u043d\u0435 \u043e\u0447\u0435\u043d\u044c \u0440\u0430\u0431\u043e\u0447\u0438\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u0430\u0445. \u042f \u0443\u0432\u043b\u0435\u0447\u0435\u043d\u043d\u043e \u0434\u0435\u043b\u0430\u043b \u044d\u0442\u043e \u0432 Windows-\u043f\u0440\u043e\u0435\u043a\u0442\u0430\u0445, \u0433\u0434\u0435 \u043f\u0430\u0442\u0442\u0435\u0440\u043d \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0440\u043e\u0434\u043d\u044b\u043c. \u0421 \u044d\u043d\u0442\u0443\u0437\u0438\u0430\u0437\u043c\u043e\u043c, \u0434\u043e\u0441\u0442\u043e\u0439\u043d\u044b\u043c \u043b\u0443\u0447\u0448\u0435\u0433\u043e \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u044f, \u044f \u0434\u0435\u043b\u0430\u043b \u044d\u0442\u043e \u0432 iOS-\u043f\u0440\u043e\u0435\u043a\u0442\u0430\u0445, \u0433\u0434\u0435 MVVM \u043f\u0440\u043e\u0441\u0442\u043e \u0442\u0430\u043a \u043d\u0435 \u043f\u0440\u0438\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044f.<\/p>\n<p>  <\/p>\n<p>\u0421\u043d\u0430\u0447\u0430\u043b\u0430 \u044f \u0434\u0435\u043b\u0430\u043b \u044d\u0442\u043e \u043e\u0434\u043d\u0438\u043c \u0441\u043f\u043e\u0441\u043e\u0431\u043e\u043c, \u043f\u043e\u0442\u043e\u043c \u043f\u043e\u043d\u0438\u043c\u0430\u043b, \u0447\u0442\u043e \u0442\u0430\u043a \u0434\u0435\u043b\u0430\u0442\u044c \u043d\u0435 \u043d\u0443\u0436\u043d\u043e, \u0438 \u0432 \u0434\u0440\u0443\u0433\u043e\u0439 \u0440\u0430\u0437 \u0434\u0435\u043b\u0430\u043b \u043a\u0430\u043a-\u0442\u043e \u0438\u043d\u0430\u0447\u0435 \u043b\u0438\u0448\u044c \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u0432 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u0440\u0430\u0437 \u0441\u043d\u043e\u0432\u0430 \u0432\u0441\u0435 \u043f\u0435\u0440\u0435\u0434\u0435\u043b\u0430\u0442\u044c.<\/p>\n<p>  <\/p>\n<p>\u0421\u043e\u0432\u0435\u0442\u0443\u044e \u0437\u0430\u043f\u0430\u0441\u0442\u0438\u0441\u044c \u043f\u043e\u043f\u043a\u043e\u0440\u043d\u043e\u043c \u0438 \u043a\u043e\u043a\u0430-\u043a\u043e\u043b\u043e\u0439\u00a0\u2014 \u044d\u0442\u043e \u0432\u0435\u0447\u0435\u0440\u043d\u0435\u0435 \u0448\u043e\u0443 \u043e \u0442\u043e\u043c, \u043a\u0430\u043a \u044f \u043d\u0438 \u0432 \u0447\u0435\u043c \u0441\u0435\u0431\u0435 \u043d\u0435 \u043e\u0442\u043a\u0430\u0437\u044b\u0432\u0430\u043b, \u0432 \u043e\u0447\u0435\u0440\u0435\u0434\u043d\u043e\u0439 \u0440\u0430\u0437 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044f MVVM \u0432 \u043e\u0434\u043d\u043e\u043c \u0438\u0437 \u0441\u0432\u043e\u0438\u0445 \u0434\u043e\u043c\u0430\u0448\u043d\u0438\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432. \u0421\u0435\u0433\u043e\u0434\u043d\u044f \u0432\u0442\u043e\u0440\u0430\u044f \u0441\u0435\u0440\u0438\u044f: \u043f\u0440\u043e \u0442\u043e, \u043a\u0430\u043a \u0438\u0437 MVC \u0441\u0434\u0435\u043b\u0430\u0442\u044c MVVM \u0438 \u043d\u0435 \u043d\u0430\u0441\u0442\u0443\u043f\u0438\u0442\u044c \u0432 \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u0449\u0438\u043d\u0443.<\/p>\n<p><a name=\"habracut\"><\/a>  <\/p>\n<h2 id=\"1.1\">\u0412\u0432\u0435\u0434\u0435\u043d\u0438\u0435<\/h2>\n<p>  <\/p>\n<p>\u041a\u0430\u043a \u044f \u0443\u0436\u0435 \u0433\u043e\u0432\u043e\u0440\u0438\u043b \u0432 <a href=\"https:\/\/habr.com\/ru\/company\/tinkoff\/blog\/508452\/\">\u043f\u0440\u043e\u0448\u043b\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435<\/a>, MVVM \u0443\u0441\u043f\u0435\u0448\u043d\u043e\u0433\u043e \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0441\u0442\u0430 \u0434\u043e\u043b\u0436\u0435\u043d \u0432\u043a\u043b\u044e\u0447\u0430\u0442\u044c \u0432 \u0441\u0435\u0431\u044f, \u043f\u043e\u043c\u0438\u043c\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0441\u0430\u043c\u043e\u0433\u043e \u043f\u0430\u0442\u0442\u0435\u0440\u043d\u0430, \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044f\u043c\u0438 \u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u0440\u043e\u0443\u0442\u0438\u043d\u0433\u0430. \u041f\u0440\u043e \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044f\u043c\u0438 \u043c\u044b \u0443\u0436\u0435 \u043f\u043e\u0433\u043e\u0432\u043e\u0440\u0438\u043b\u0438 \u0438 \u0441\u0435\u0439\u0447\u0430\u0441 \u043f\u0435\u0440\u0435\u0439\u0434\u0435\u043c \u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u043a \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 MVVM. \u0412 \u044f\u0431\u043b\u043e\u0447\u043d\u043e\u043c \u043c\u0438\u0440\u0435 \u043f\u0430\u0442\u0442\u0435\u0440\u043d, \u043f\u0440\u0438\u0434\u0443\u043c\u0430\u043d\u043d\u044b\u0439 \u0432 Microsoft, \u0447\u0443\u0432\u0441\u0442\u0432\u0443\u0435\u0442 \u0441\u0435\u0431\u044f \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0438\u043d\u043e\u0441\u0442\u0440\u0430\u043d\u0446\u0435\u043c, \u0438 \u0435\u0433\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u043e\u0442 \u043d\u0430\u0441 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0443\u0441\u0438\u043b\u0438\u0439. \u042d\u0442\u0438 \u0443\u0441\u0438\u043b\u0438\u044f \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u043f\u0440\u0438\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u0442\u044c \u043a \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u043c\u0443 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044e, \u043d\u0430 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0432\u0441\u0435 \u0442\u043e\u043d\u043a\u043e\u0441\u0442\u0438 \u0438 \u043f\u043e\u0434\u0432\u043e\u0434\u043d\u044b\u0435 \u043a\u0430\u043c\u043d\u0438. \u0422\u0430\u043a \u043a\u0430\u043a \u0441 \u0438\u0434\u0435\u044f\u043c\u0438 \u0443 \u043c\u0435\u043d\u044f \u0442\u0440\u0430\u0434\u0438\u0446\u0438\u043e\u043d\u043d\u043e \u043d\u0435 \u043e\u0447\u0435\u043d\u044c, \u044d\u0442\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0441\u0442\u043e\u044f\u0442\u044c \u0438\u0437 \u043e\u0434\u043d\u043e\u0433\u043e-\u0435\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0433\u043e \u044d\u043a\u0440\u0430\u043d\u0430, \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u044e\u0449\u0435\u0433\u043e \u0441\u043f\u0438\u0441\u043e\u043a \u0437\u0430\u043a\u0430\u0437\u043e\u0432. <\/p>\n<p>  <\/p>\n<p>\u041d\u0430\u043f\u043e\u043c\u043d\u044e \u0442\u0430\u043a\u0436\u0435, \u0447\u0442\u043e \u0432 \u043a\u043e\u0434\u0435 \u044f \u0441\u0442\u0430\u0440\u0430\u044e\u0441\u044c \u0441 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u043c \u0443\u0441\u043f\u0435\u0445\u043e\u043c \u043f\u0440\u0438\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0442\u044c\u0441\u044f \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u043f\u0440\u043e\u0441\u0442\u044b\u0445 \u043f\u0440\u0430\u0432\u0438\u043b, \u043e \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0443\u0436\u0435 \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u044b\u0432\u0430\u043b:<\/p>\n<p>  <\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">\u041d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u043f\u0440\u043e\u0441\u0442\u044b\u0445 \u043f\u0440\u0430\u0432\u0438\u043b, \u043e \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0443\u0436\u0435 \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u044b\u0432\u0430\u043b<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<ol>\n<li>\u041d\u0435 \u0432\u044b\u043f\u0435\u043d\u0434\u0440\u0438\u0432\u0430\u0439\u0441\u044f. \u0422\u0443\u043f\u043e\u0439 \u0438 \u043f\u043e\u043d\u044f\u0442\u043d\u044b\u0439 \u043a\u043e\u0434 \u0432 \u0431\u043e\u043b\u044c\u0448\u0438\u043d\u0441\u0442\u0432\u0435 \u0441\u043b\u0443\u0447\u0430\u0435\u0432 \u043b\u0443\u0447\u0448\u0435 \u0443\u043c\u043d\u043e\u0433\u043e \u0438 \u043d\u0435\u043f\u043e\u043d\u044f\u0442\u043d\u043e\u0433\u043e.<\/li>\n<li>\u0411\u0443\u0434\u044c \u043a\u0440\u0430\u0442\u043e\u043a. \u041a\u043e\u0434\u0430 \u0434\u043e\u043b\u0436\u043d\u043e \u0431\u044b\u0442\u044c \u043d\u0430\u0441\u0442\u043e\u043b\u044c\u043a\u043e \u043c\u0430\u043b\u043e, \u0447\u0442\u043e\u0431\u044b \u0435\u0433\u043e \u043d\u0435 \u0436\u0430\u043b\u043a\u043e \u0431\u044b\u043b\u043e \u0432 \u043b\u044e\u0431\u043e\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u0432\u044b\u043a\u0438\u043d\u0443\u0442\u044c \u0438 \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0437\u0430\u043d\u043e\u0432\u043e \u0437\u0430 \u043e\u0434\u0438\u043d \u0434\u0435\u043d\u044c.<\/li>\n<li>\u0423\u0434\u043e\u0431\u0441\u0442\u0432\u043e \u043f\u0440\u0435\u0432\u044b\u0448\u0435 \u043f\u0440\u0430\u0432\u0438\u043b. \u0415\u0441\u043b\u0438 \u043c\u043e\u0436\u043d\u043e \u043e\u0431\u043b\u0435\u0433\u0447\u0438\u0442\u044c \u0441\u0435\u0431\u0435 \u0436\u0438\u0437\u043d\u044c, \u043f\u043e\u0436\u0435\u0440\u0442\u0432\u043e\u0432\u0430\u0432 \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u0430\u043c\u0438 SOLID, \u043f\u043e\u0436\u0435\u0440\u0442\u0432\u0443\u0439 \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u0430\u043c\u0438 SOLID.<\/li>\n<li>\u041f\u043e\u043b\u0443\u0447\u0430\u0439 \u0443\u0434\u043e\u0432\u043e\u043b\u044c\u0441\u0442\u0432\u0438\u0435. \u0415\u0441\u043b\u0438 \u0435\u0441\u0442\u044c \u0440\u0430\u0437\u043d\u044b\u0435 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u044b \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b, \u0432\u044b\u0431\u0438\u0440\u0430\u0439 \u0431\u043e\u043b\u0435\u0435 \u0432\u0435\u0441\u0435\u043b\u044b\u0439.<\/li>\n<\/ol>\n<\/div><\/div>\n<p>  <\/p>\n<p>\u0414\u043b\u044f \u0442\u0435\u0445, \u043a\u0442\u043e \u043d\u0435 \u043f\u0440\u0438\u0435\u043c\u043b\u0435\u0442 \u043d\u0435\u043e\u0436\u0438\u0434\u0430\u043d\u043d\u043e\u0441\u0442\u0435\u0439, \u0432\u043e\u0442 \u043f\u043e\u043b\u043d\u043e\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435 \u0441\u0442\u0430\u0442\u044c\u0438.<\/p>\n<p>  <\/p>\n<h3 id=\"polnoe-soderzhanie\">\u041f\u043e\u043b\u043d\u043e\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435<\/h3>\n<p>  <\/p>\n<ul>\n<li>\u0421\u0442\u0430\u0442\u044c\u044f 1. <a href=\"https:\/\/habr.com\/ru\/company\/tinkoff\/blog\/508452\/\">\u0411\u044e\u0434\u0436\u0435\u0442\u043d\u044b\u0439 DI \u043d\u0430 \u0430\u043d\u0442\u0438\u043f\u0430\u0442\u0442\u0435\u0440\u043d\u0430\u0445<\/a><\/li>\n<li>\u0421\u0442\u0430\u0442\u044c\u044f 2. \u0414\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0439 MVVM \u043d\u0430 \u0445\u0430\u043a\u043d\u0443\u0442\u044b\u0445 \u044d\u043a\u0441\u0442\u0435\u043d\u0448\u0435\u043d\u0430\u0445<br \/> \n<ul>\n<li><a href=\"#1.1\">\u0412\u0432\u0435\u0434\u0435\u043d\u0438\u0435<\/a> <strong>&lt;= \u0432\u044b \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0435\u0441\u044c \u0437\u0434\u0435\u0441\u044c<\/strong><\/li>\n<li><a href=\"#1.2\">\u0414\u0435\u0439\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u043b\u0438\u0446\u0430<\/a><\/li>\n<li><a href=\"#1.3\">\u0417\u043d\u0430\u043a\u043e\u043c\u0438\u043c \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0441 \u0435\u0433\u043e \u043c\u043e\u0434\u0435\u043b\u044c\u044e<\/a><\/li>\n<li><a href=\"#1.4\">\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u0447\u0435\u0440\u0435\u0437 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0430<\/a><\/li>\n<li><a href=\"#1.5\">\u041e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0441\u043f\u0438\u0441\u043a\u0430 \u0437\u0430\u043a\u0430\u0437\u043e\u0432 (\u043d\u0430 \u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435 \u043d\u0435\u0442)<\/a><\/li>\n<li><a href=\"#1.6\">\u0423\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0435 \u043e\u0431 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0438 \u043c\u043e\u0434\u0435\u043b\u0438 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f<\/a><\/li>\n<li><a href=\"#1.7\">\u0417\u0430\u043d\u043e\u0432\u043e \u0438\u0437\u043e\u0431\u0440\u0435\u0442\u0430\u0435\u043c \u0441\u043e\u0431\u044b\u0442\u0438\u044f<\/a><\/li>\n<li><a href=\"#1.8\">\u041e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0441\u043f\u0438\u0441\u043a\u0430 \u0437\u0430\u043a\u0430\u0437\u043e\u0432<\/a><\/li>\n<li><a href=\"#1.9\">\u041f\u043e\u0434\u043f\u0438\u0441\u043a\u0430 \u043d\u0430 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0445 \u0441\u0432\u043e\u0439\u0441\u0442\u0432 \u043c\u043e\u0434\u0435\u043b\u0438 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0447\u0435\u0440\u0435\u0437 \u043e\u0431\u0435\u0440\u0442\u043a\u0438 \u0441\u0432\u043e\u0439\u0441\u0442\u0432<\/a><\/li>\n<li><a href=\"#1.10\">\u0417\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435<\/a> <\/li>\n<\/ul>\n<\/li>\n<li>\u0421\u0442\u0430\u0442\u044c\u044f 3. \u041b\u0435\u0433\u043a\u043e\u0432\u0435\u0441\u043d\u044b\u0439 \u0440\u043e\u0443\u0442\u0438\u043d\u0433 \u043d\u0430 \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u0430\u0445<\/li>\n<\/ul>\n<p>  <\/p>\n<h2 id=\"1.2\">\u0414\u0435\u0439\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u043b\u0438\u0446\u0430<\/h2>\n<p>  <\/p>\n<p>\u042f \u043d\u0435 \u043f\u043b\u0430\u043d\u0438\u0440\u0443\u044e \u0440\u0430\u0441\u0448\u0438\u0444\u0440\u043e\u0432\u044b\u0432\u0430\u0442\u044c \u043a\u0430\u0436\u0434\u0443\u044e \u0431\u0443\u043a\u0432\u0443 \u0430\u0431\u0431\u0440\u0435\u0432\u0438\u0430\u0442\u0443\u0440\u044b MVVM \u0438 \u043e\u0431\u044a\u044f\u0441\u043d\u044f\u0442\u044c, \u043a\u0430\u043a \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043f\u0430\u0442\u0442\u0435\u0440\u043d \u0438 \u0437\u0430\u0447\u0435\u043c \u043e\u043d \u0432\u043e\u043e\u0431\u0449\u0435 \u043d\u0443\u0436\u0435\u043d. \u0423\u0432\u0435\u0440\u0435\u043d, \u0432\u0441\u0435 \u044d\u0442\u043e \u0432\u044b \u0438 \u0431\u0435\u0437 \u043c\u0435\u043d\u044f \u0437\u043d\u0430\u0435\u0442\u0435. \u0415\u0441\u043b\u0438 \u043f\u043e \u043a\u0430\u043a\u043e\u0439-\u0442\u043e \u043f\u0440\u0438\u0447\u0438\u043d\u0435 MVVM \u0434\u043b\u044f \u0432\u0430\u0441 \u0432 \u043d\u043e\u0432\u0438\u043d\u043a\u0443, \u0441\u043e\u0432\u0435\u0442\u0443\u044e \u043f\u0435\u0440\u0435\u0441\u0442\u0430\u0442\u044c \u0447\u0438\u0442\u0430\u0442\u044c \u044d\u0442\u0443 \u0441\u0442\u0430\u0442\u044c\u044e \u0438 \u043f\u043e\u0441\u043a\u043e\u0440\u0435\u0435 \u0437\u0430\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u043f\u0440\u043e\u0431\u0435\u043b \u0432 \u0437\u043d\u0430\u043d\u0438\u044f\u0445. \u041d\u0435\u0432\u0435\u0440\u043e\u044f\u0442\u043d\u043e \u0441\u043a\u0443\u0447\u043d\u0430\u044f, \u043d\u043e \u043f\u043e\u0437\u043d\u0430\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u0430\u044f <a href=\"https:\/\/en.wikipedia.org\/wiki\/Model%E2%80%93view%E2%80%93viewmodel\">\u0441\u0442\u0430\u0442\u044c\u044f \u0438\u0437 \u00ab\u0412\u0438\u043a\u0438\u043f\u0435\u0434\u0438\u0438\u00bb<\/a> \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u0441\u043b\u0443\u0436\u0438\u0442\u044c \u043d\u0435\u043f\u043b\u043e\u0445\u0438\u043c \u0441\u0442\u0430\u0440\u0442\u043e\u043c.<\/p>\n<p>  <\/p>\n<p>\u0412\u043c\u0435\u0441\u0442\u043e \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0442\u043d\u044b\u0445 \u0440\u0430\u0437\u0433\u043e\u0432\u043e\u0440\u043e\u0432 \u043f\u0440\u043e \u043f\u0430\u0442\u0442\u0435\u0440\u043d \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0437\u0430\u043d\u0438\u043c\u0430\u0442\u044c\u0441\u044f \u0442\u0435\u043c, \u0447\u0435\u043c \u0437\u0430\u043d\u0438\u043c\u0430\u0435\u043c\u0441\u044f \u043a\u0430\u0436\u0434\u044b\u0439 \u0434\u0435\u043d\u044c\u00a0\u2014 \u043f\u0438\u0441\u0430\u0442\u044c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435. \u0422\u0430\u043a \u043a\u0430\u043a \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043c\u044b \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u043c\u0441\u044f \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c, \u0434\u043e \u043d\u0435\u043f\u0440\u0438\u043b\u0438\u0447\u0438\u044f \u043f\u0440\u043e\u0441\u0442\u043e\u0435, \u043f\u043e\u0437\u0432\u043e\u043b\u044c\u0442\u0435 \u0431\u0435\u0437 \u043f\u0440\u0435\u0434\u0432\u0430\u0440\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0440\u0430\u0441\u0448\u0430\u0440\u043a\u0438\u0432\u0430\u043d\u0438\u0439 \u0432\u044b\u0432\u0430\u043b\u0438\u0442\u044c \u043d\u0430 \u0432\u0430\u0441 \u0441\u0440\u0430\u0437\u0443 \u0432\u0435\u0441\u044c \u0441\u043f\u0438\u0441\u043e\u043a \u0434\u0435\u0439\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0445 \u043b\u0438\u0446 \u044d\u0442\u043e\u0439 \u0443\u0432\u043b\u0435\u043a\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0439 \u0438\u0441\u0442\u043e\u0440\u0438\u0438.<\/p>\n<p>  <\/p>\n<div class=\"scrollable-table\">\n<table>\n<tr>\n<td><b>OrdersVC<\/b><\/td>\n<td>\u0412\u044c\u044e-\u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440 \u044d\u043a\u0440\u0430\u043d\u0430 \u0437\u0430\u043a\u0430\u0437\u043e\u0432. \u0411\u0435\u0437 \u043d\u0435\u0433\u043e \u043d\u0438\u043a\u0430\u043a, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e iOS\u00a0\u2014 \u044d\u0442\u043e \u0432\u044c\u044e-\u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u044b. \u042f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u043e\u043c \u0441\u043e\u0431\u044b\u0442\u0438\u0439 \u0436\u0438\u0437\u043d\u0435\u043d\u043d\u043e\u0433\u043e \u0446\u0438\u043a\u043b\u0430 \u044d\u043a\u0440\u0430\u043d\u0430 \u0438 \u0437\u0430\u043d\u0438\u043c\u0430\u0435\u0442\u0441\u044f \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435\u043c \u0434\u0430\u043d\u043d\u044b\u0445, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u0440\u0438\u0445\u043e\u0434\u044f\u0442 \u0438\u0437 \u0432\u044c\u044e-\u043c\u043e\u0434\u0435\u043b\u0438. \u0412 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043e\u043d \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u0442\u0430\u0431\u043b\u0438\u0446\u0443 \u0434\u043b\u044f \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0441\u043f\u0438\u0441\u043a\u0430 \u0437\u0430\u043a\u0430\u0437\u043e\u0432<\/td>\n<\/tr>\n<tr>\n<td><b>OrdersView<\/b><\/td>\n<td>\u0412\u044c\u044e\u0445\u0430 \u0434\u043b\u044f \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430 OrdersVC. \u0425\u043e\u0440\u043e\u0448\u0430\u044f \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0430\u00a0\u2014 \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e VC \u0437\u0430\u0432\u043e\u0434\u0438\u0442\u044c \u0441\u0432\u043e\u044e \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u0443\u044e View \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u043c \u043a\u043b\u0430\u0441\u0441\u043e\u043c, \u043d\u043e \u0432 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u0434\u043b\u044f \u0443\u043f\u0440\u043e\u0449\u0435\u043d\u0438\u044f \u043c\u044b \u0442\u0430\u043a \u0434\u0435\u043b\u0430\u0442\u044c \u043d\u0435 \u0431\u0443\u0434\u0435\u043c. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 OrdersView\u00a0\u2014 \u044d\u0442\u043e \u0442\u0430\u043a\u0430\u044f \u0432\u044c\u044e\u0445\u0430, \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043d\u0435\u0442, \u043d\u043e \u043d\u0443\u0436\u043d\u043e \u043f\u043e\u043c\u043d\u0438\u0442\u044c, \u0447\u0442\u043e \u043e\u043d\u0430 \u043e\u0447\u0435\u043d\u044c \u0434\u0430\u0436\u0435 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c<\/td>\n<\/tr>\n<tr>\n<td><b>OrdersVM<\/b><\/td>\n<td>\u041c\u043e\u0434\u0435\u043b\u044c \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0434\u043b\u044f OrdersVC, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0434\u043b\u044f \u0435\u0433\u043e \u0432\u044c\u044e\u0445\u0438, \u0435\u0441\u043b\u0438 \u0431\u044b \u043e\u043d\u0430 \u0443 \u043d\u0435\u0433\u043e \u0431\u044b\u043b\u0430. \u0421 \u043f\u043e\u043c\u043e\u0449\u044c\u044e OrdersProvider \u0432\u044c\u044e-\u043c\u043e\u0434\u0435\u043b\u044c \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u0437\u0430\u043a\u0430\u0437\u044b \u0438 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u0443\u0435\u0442 \u0438\u0445 \u0432 \u043f\u0440\u0438\u0433\u043e\u0434\u043d\u044b\u0439 \u0434\u043b\u044f \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0432\u0438\u0434<\/td>\n<\/tr>\n<tr>\n<td><b>Order<\/b><\/td>\n<td>\u041d\u0438\u0447\u0435\u0433\u043e \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0433\u043e, \u0442\u0438\u043f\u0438\u0447\u043d\u0430\u044f \u043c\u043e\u0434\u0435\u043b\u044c, \u043a\u0430\u043a\u0438\u0445 \u043c\u043d\u043e\u0433\u043e. \u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u043e\u0431\u043e\u0439 \u0437\u0430\u043a\u0430\u0437<\/td>\n<\/tr>\n<tr>\n<td><b>OrderCell<\/b><\/td>\n<td>\u042f\u0447\u0435\u0439\u043a\u0430 UITableView, \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u044e\u0449\u0430\u044f \u0437\u0430\u043a\u0430\u0437<\/td>\n<\/tr>\n<tr>\n<td><b>OrderVM<\/b><\/td>\n<td>\u041c\u043e\u0434\u0435\u043b\u044c \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0434\u043b\u044f \u044f\u0447\u0435\u0439\u043a\u0438 OrderCell. \u042d\u0442\u043e \u0442\u043e\u0442 \u0436\u0435 Order, \u043d\u043e \u043f\u0440\u0438\u0433\u043e\u0434\u043d\u044b\u0439 \u0434\u043b\u044f \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f<\/td>\n<\/tr>\n<tr>\n<td><b>OrdersProvider<\/b><\/td>\n<td>\u0421\u0435\u0440\u0432\u0438\u0441, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c \u0437\u0430\u043a\u0430\u0437\u044b\u00a0\u2014 \u0438\u0437 \u0431\u0430\u0437\u044b \u0434\u0430\u043d\u043d\u044b\u0445, \u0438\u0437 \u0444\u0430\u0439\u043b\u0430, \u0441 \u0431\u044d\u043a\u044d\u043d\u0434\u0430\u00a0\u2014 \u043d\u0435\u0432\u0430\u0436\u043d\u043e \u043e\u0442\u043a\u0443\u0434\u0430. \u0414\u043b\u044f \u043d\u0430\u0448\u0435\u0433\u043e \u043e\u0431\u0443\u0447\u0430\u044e\u0449\u0435\u0433\u043e \u043f\u0440\u0438\u043c\u0435\u0440\u0430 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0433\u0440\u0443\u0437\u0438\u0442\u044c \u0437\u0430\u043a\u0430\u0437\u044b \u0438\u0437 \u0431\u0435\u0437\u0434\u043e\u043d\u043d\u043e\u0439 \u043f\u0443\u0441\u0442\u043e\u0442\u044b \u043d\u0435\u0431\u044b\u0442\u0438\u044f<\/td>\n<\/tr>\n<\/table>\n<\/div>\n<p>  <\/p>\n<p>\u0412\u043e\u0442 \u0442\u0430\u043a \u0432\u0441\u0435 \u044d\u0442\u0438 \u0440\u0435\u0431\u044f\u0442\u0430 \u0443\u0436\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u0432\u043c\u0435\u0441\u0442\u0435 \u043d\u0430 \u0434\u0438\u0430\u0433\u0440\u0430\u043c\u043c\u0435 \u043a\u043b\u0430\u0441\u0441\u043e\u0432.<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/v0\/bp\/si\/v0bpsiwxgxpxhadfibhvsi322xc.png\" width=\"90%\"><\/p>\n<p>  <\/p>\n<p>\u0421\u0442\u043e\u0438\u0442 \u043e\u0442\u043c\u0435\u0442\u0438\u0442\u044c, \u0447\u0442\u043e \u0432 \u043c\u0438\u0440\u0435 MVVM \u043d\u0435\u0442 \u0442\u0430\u043a\u043e\u0433\u043e \u043f\u043e\u043d\u044f\u0442\u0438\u044f, \u043a\u0430\u043a \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440, \u0432 \u0442\u043e \u0432\u0440\u0435\u043c\u044f \u043a\u0430\u043a \u0432 iOS, \u0433\u0434\u0435 \u0431\u0435\u0437\u0440\u0430\u0437\u0434\u0435\u043b\u044c\u043d\u043e \u0432\u043b\u0430\u0441\u0442\u0432\u0443\u0435\u0442 MVC, \u0431\u0435\u0437 \u0432\u044c\u044e-\u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u043e\u0432 \u043d\u0438\u043a\u0443\u0434\u0430. \u0427\u0442\u043e\u0431\u044b \u0440\u0430\u0437\u0440\u0435\u0448\u0438\u0442\u044c \u044d\u0442\u043e \u043f\u0440\u043e\u0442\u0438\u0432\u043e\u0440\u0435\u0447\u0438\u0435, \u0437\u0434\u0435\u0441\u044c \u0438 \u0434\u0430\u043b\u0435\u0435 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0441\u0447\u0438\u0442\u0430\u0442\u044c, \u0447\u0442\u043e \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u00a0\u2014 \u044d\u0442\u043e \u043f\u0440\u043e\u0441\u0442\u043e View, \u0442\u0435\u043c \u0431\u043e\u043b\u0435\u0435 \u0447\u0442\u043e \u0432 iOS \u044d\u0442\u0438 \u0434\u0432\u0435 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438 \u0442\u0440\u0430\u0434\u0438\u0446\u0438\u043e\u043d\u043d\u043e \u043e\u0447\u0435\u043d\u044c \u0442\u0435\u0441\u043d\u043e \u0441\u0432\u044f\u0437\u0430\u043d\u044b.<\/p>\n<p>  <\/p>\n<p><strong>\u0417\u0430\u043f\u043e\u043c\u043d\u0438\u0442\u0435:<\/strong> \u0432\u0441\u0435, \u0447\u0442\u043e \u044f \u0433\u043e\u0432\u043e\u0440\u044e \u0432 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043e View, \u043c\u043e\u0436\u043d\u043e \u0432 \u0440\u0430\u0432\u043d\u043e\u0439 \u0441\u0442\u0435\u043f\u0435\u043d\u0438 \u043e\u0442\u043d\u0435\u0441\u0442\u0438 \u043a \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0443, \u0438 \u043d\u0430\u043e\u0431\u043e\u0440\u043e\u0442. <\/p>\n<p>  <\/p>\n<p>\u041d\u0430\u0447\u0438\u043d\u0430\u044f \u043e\u0442\u0441\u044e\u0434\u0430 \u0438 \u0434\u043e \u043a\u043e\u043d\u0446\u0430 \u0441\u0442\u0430\u0442\u044c\u0438 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0437\u0430\u043d\u0438\u043c\u0430\u0442\u044c\u0441\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0435\u0439 \u044d\u0442\u043e\u0439 \u043a\u0430\u0440\u0442\u0438\u043d\u043a\u0438 \u0432 \u043a\u043e\u0434\u0435.<\/p>\n<p>  <\/p>\n<h2 id=\"1.3\">\u0417\u043d\u0430\u043a\u043e\u043c\u0438\u043c \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0441 \u0435\u0433\u043e \u043c\u043e\u0434\u0435\u043b\u044c\u044e<\/h2>\n<p>  <\/p>\n<p>\u0421\u043f\u043b\u043e\u0448\u043d\u0430\u044f \u0441\u0442\u0440\u0435\u043b\u043e\u0447\u043a\u0430, \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043d\u0430\u044f \u043e\u0442 View \u043a ViewModel, \u0441\u0438\u043c\u0432\u043e\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u0442 \u0438\u0445 \u0430\u0431\u044c\u044e\u0437\u0438\u0432\u043d\u044b\u0435 \u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u044f: \u0432\u044c\u044e\u0445\u0430 \u0432\u043b\u0430\u0434\u0435\u0435\u0442 \u0432\u044c\u044e-\u043c\u043e\u0434\u0435\u043b\u044c\u044e, \u0434\u0435\u0440\u0436\u0438\u0442 \u0435\u0435 \u0441\u0438\u043b\u044c\u043d\u043e\u0439 \u0441\u0441\u044b\u043b\u043a\u043e\u0439 \u0438 \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442 \u0435\u0435 \u043c\u0435\u0442\u043e\u0434\u044b. \u0423\u0437\u0430\u043a\u043e\u043d\u0438\u043c \u044d\u0442\u0438 \u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u044f \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0430. \u041c\u043e\u0436\u0435\u0442 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0443\u0433\u043e\u0434\u043d\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0439 MVVM, \u043d\u043e \u043e\u0434\u043d\u0430 \u0448\u0442\u0443\u043a\u0430 \u0432 \u043d\u0438\u0445 \u0431\u0443\u0434\u0435\u0442 \u043d\u0435\u0438\u0437\u043c\u0435\u043d\u043d\u043e\u0439: \u0443 View \u0434\u043e\u043b\u0436\u043d\u043e \u043f\u043e\u044f\u0432\u0438\u0442\u044c\u0441\u044f \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e <code>viewModel<\/code>:<\/p>\n<p>  <\/p>\n<pre><code class=\"swift\">protocol IHaveViewModel: AnyObject {     associatedtype ViewModel      var viewModel: ViewModel? { get set }     func viewModelChanged(_ viewModel: ViewModel) }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0411\u0443\u043a\u0432\u0430 I \u0432 \u043d\u0430\u0447\u0430\u043b\u0435 \u0438\u043c\u0435\u043d\u0438 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0430 \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442 interface. \u0412 \u043f\u0440\u0435\u0434\u0441\u043a\u0430\u0437\u0443\u0435\u043c\u043e\u043c \u043c\u0438\u0440\u0435 \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u0442\u0438\u043f\u0438\u0437\u0430\u0446\u0438\u0438 \u0443 \u0440\u0430\u0437\u043d\u044b\u0445 \u0432\u044c\u044e\u0445 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u044b \u0432\u044c\u044e-\u043c\u043e\u0434\u0435\u043b\u0435\u0439, \u0441\u043a\u043e\u0440\u0435\u0435 \u0432\u0441\u0435\u0433\u043e, \u0431\u0443\u0434\u0443\u0442 \u043f\u0440\u0438\u043d\u0430\u0434\u043b\u0435\u0436\u0430\u0442\u044c \u0440\u0430\u0437\u043d\u044b\u043c \u043a\u043b\u0430\u0441\u0441\u0430\u043c. \u0427\u0442\u043e\u0431\u044b \u0432\u044b\u0440\u0430\u0437\u0438\u0442\u044c \u044d\u0442\u043e \u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0430\u043c\u0438 \u044f\u0437\u044b\u043a\u0430, \u043d\u0430\u043c \u043f\u0440\u0438\u0433\u043e\u0434\u0438\u043b\u0441\u044f \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b \u0441 <del>\u0434\u0436\u0435\u043d\u0435\u0440\u0438\u043a\u043e\u043c<\/del> \u0430\u0441\u0441\u043e\u0446\u0438\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u043c \u0442\u0438\u043f\u043e\u043c.<\/p>\n<p>  <\/p>\n<p>\u0417\u0430\u043c\u0435\u0442\u0438\u043c, \u0447\u0442\u043e \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e <code>viewModel<\/code> \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e \u0434\u043b\u044f \u0437\u0430\u043f\u0438\u0441\u0438 \u0438\u0437\u0432\u043d\u0435. \u0412 \u043a\u0430\u043a\u043e\u0439-\u0442\u043e \u043c\u043e\u043c\u0435\u043d\u0442 \u043e\u043d\u043e \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u0441\u044f, \u0447\u0442\u043e \u043d\u0435\u0438\u0437\u0431\u0435\u0436\u043d\u043e \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u0442 \u043a \u0432\u044b\u0437\u043e\u0432\u0443 \u043c\u0435\u0442\u043e\u0434\u0430 <code>viewModelChanged(_:)<\/code>, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0432\u044c\u044e\u0445\u0430 \u043e\u0431\u044f\u0437\u0443\u0435\u0442\u0441\u044f \u043f\u0440\u043e\u0434\u0435\u043b\u0430\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u0443 \u043f\u043e \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u0438 \u0441\u0432\u043e\u0435\u0433\u043e \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u0432 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0438\u0438 \u0441\u043e \u0441\u0432\u043e\u0435\u0439 \u043c\u043e\u0434\u0435\u043b\u044c\u044e \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f. \u041d\u0435\u0445\u0438\u0442\u0440\u0430\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0430 <code>IHaveViewModel<\/code> \u043d\u0430 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u0441\u0432\u044f\u0437\u043a\u0438 <code>OrderCell\u00a0\u2014 OrderVM<\/code> \u043c\u043e\u0433\u043b\u0430 \u0431\u044b \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0432\u043e\u0442 \u0442\u0430\u043a:<\/p>\n<p>  <\/p>\n<pre><code class=\"swift\">final class OrderCell: UITableViewCell, IHaveViewModel {     var viewModel: OrderVM? {         didSet {             guard let viewModel = viewModel else { return }             viewModelChanged(viewModel)         }     }      func viewModelChanged(_ viewModel: OrderVM) {         textLabel?.text = viewModel.name     } }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0417\u0430\u043c\u0435\u0447\u0443, \u0447\u0442\u043e \u0434\u043b\u044f \u043f\u0440\u043e\u0441\u0442\u043e\u0442\u044b \u043c\u044b \u0432\u0437\u044f\u043b\u0438 \u044f\u0447\u0435\u0439\u043a\u0443 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0433\u043e \u043b\u0430\u0439\u0430\u0443\u0442\u0430, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u0441\u044f \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e\u043c <code>textLabel<\/code> \u0434\u043b\u044f \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0442\u0435\u043a\u0441\u0442\u0430. \u041c\u043e\u0434\u0435\u043b\u044c \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0437\u0430\u043a\u0430\u0437\u0430 \u043d\u0430\u043c \u043d\u0435 \u043e\u0447\u0435\u043d\u044c \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u0430, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0441\u0434\u0435\u043b\u0430\u0435\u043c \u0435\u0435 \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e \u043d\u0435\u0443\u043c\u043d\u043e\u0439:<\/p>\n<p>  <\/p>\n<pre><code class=\"swift\">final class OrderVM {     let order: Order     var name: String {         return &quot;\\(order.name) #\\(order.id)&quot;     }     init(order: Order) {         self.order = order     } }<\/code><\/pre>\n<p>  <\/p>\n<p>\u041d\u0435\u0442\u0435\u0440\u043f\u0435\u043b\u0438\u0432\u044b\u0439 \u0447\u0438\u0442\u0430\u0442\u0435\u043b\u044c \u043c\u043e\u0436\u0435\u0442 \u0437\u0430\u0434\u0430\u0442\u044c\u0441\u044f \u0432\u043e\u043f\u0440\u043e\u0441\u043e\u043c, \u043a\u0442\u043e \u0436\u0435 \u043f\u0440\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e <code>viewModel<\/code> \u0443 \u044f\u0447\u0435\u0439\u043a\u0438 \u0438, \u0447\u0442\u043e \u0431\u043e\u043b\u0435\u0435 \u0432\u0430\u0436\u043d\u043e, \u043a\u0430\u043a \u0438\u043c\u0435\u043d\u043d\u043e \u044d\u0442\u043e \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442. \u041d\u0430 \u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435 \u0442\u0438\u043f\u0438\u0447\u043d\u0430\u044f <code>OrderCell<\/code> \u043d\u0435 \u043e\u0447\u0435\u043d\u044c \u043e\u0442\u043b\u0438\u0447\u0430\u0435\u0442\u0441\u044f \u043e\u0442 \u0441\u0432\u043e\u0438\u0445 \u0441\u043e\u0431\u0440\u0430\u0442\u044c\u0435\u0432, \u0438 \u0435\u0435 \u0436\u0438\u0437\u043d\u0435\u043d\u043d\u044b\u0439 \u0446\u0438\u043a\u043b \u043f\u0440\u043e\u0442\u0435\u043a\u0430\u0435\u0442 \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u043e\u0431\u044b\u0447\u043d\u044b\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<\/p>\n<p>  <\/p>\n<ol>\n<li>\u0412 \u043c\u0435\u0442\u043e\u0434\u0435 \u0434\u0435\u043b\u0435\u0433\u0430\u0442\u0430 \u0442\u0430\u0431\u043b\u0438\u0446\u044b <code>tableView(_:cellForRowAt:)<\/code> \u0438\u0437\u0432\u043b\u0435\u043a\u0430\u0435\u043c \u044f\u0447\u0435\u0439\u043a\u0443 \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 \u0432\u044b\u0437\u043e\u0432\u0430 <code>dequeueReusableCell(withIdentifier:for:)<\/code> \u0438 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \u043a\u043b\u0430\u0441\u0441\u0430 <code>UITableViewCell<\/code>.<\/li>\n<li>\u041e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0435\u043c \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u0442\u0438\u043f\u0430 \u043a \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0443 <code>IHaveViewModel<\/code>, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0443 <code>viewModel<\/code> \u0438 \u0437\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0442\u0443\u0434\u0430 \u0432\u044c\u044e-\u043c\u043e\u0434\u0435\u043b\u044c.<\/li>\n<li>\u0413\u0440\u0443\u0441\u0442\u0438\u043c \u043e\u0442\u0442\u043e\u0433\u043e, \u0447\u0442\u043e \u043a\u043e\u0434, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u044b \u043d\u0430\u043f\u0438\u0441\u0430\u043b\u0438 \u043d\u0430 \u0448\u0430\u0433\u0435 2, \u043d\u0435 \u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u0443\u0435\u0442\u0441\u044f.<\/li>\n<li>\u0413\u0443\u0433\u043b\u0438\u043c \u043e\u0448\u0438\u0431\u043a\u0443 <em>Protocol &#8216;IHaveViewModel&#8217; can only be used as a generic constraint because it has Self or associated type requirements.<\/em><\/li>\n<\/ol>\n<p>  <\/p>\n<p>\u0427\u0442\u043e\u0431\u044b \u0441\u043f\u0440\u0430\u0432\u0438\u0442\u044c\u0441\u044f \u0441 \u0442\u0430\u043a\u043e\u0439 \u043e\u0448\u0438\u0431\u043a\u043e\u0439, \u043d\u0430\u043c \u043f\u0440\u0438\u0434\u0435\u0442\u0441\u044f \u043f\u0440\u0438\u043c\u0435\u043d\u0438\u0442\u044c \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u0443\u044e \u0442\u0435\u0445\u043d\u0438\u043a\u0443 \u0441 \u0437\u0430\u0433\u0430\u0434\u043e\u0447\u043d\u044b\u043c \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435\u043c \u0441\u0442\u0438\u0440\u0430\u043d\u0438\u0435 \u0442\u0438\u043f\u043e\u0432 (type erasure). \u041d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0430\u0432\u0442\u043e\u0440\u044b \u0432\u044b\u0434\u0435\u043b\u044f\u044e\u0442 <a href=\"https:\/\/medium.com\/@bobgodwinx\/swift-associated-type-design-patterns-6c56c5b0a73a\">\u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0440\u0430\u0437\u043d\u043e\u0432\u0438\u0434\u043d\u043e\u0441\u0442\u0435\u0439 \u0441\u0442\u0438\u0440\u0430\u043d\u0438\u044f \u0442\u0438\u043f\u043e\u0432.<\/a> \u0414\u043b\u044f \u043d\u0430\u0448\u0435\u0433\u043e \u0441\u043b\u0443\u0447\u0430\u044f \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u0442 \u0432\u0430\u0440\u0438\u0430\u043d\u0442, \u043f\u043e\u0445\u043e\u0436\u0438\u0439 \u043d\u0430 \u0441\u0435\u043a\u0440\u0435\u0442\u043d\u0443\u044e \u0442\u0435\u0445\u043d\u0438\u043a\u0443 \u043d\u0438\u043d\u0434\u0437\u044f\u00a0\u2014 \u0442\u0435\u043d\u0435\u0432\u043e\u0435 \u0441\u0442\u0438\u0440\u0430\u043d\u0438\u0435 \u0442\u0438\u043f\u043e\u0432 (shadow type erasure). \u041a\u0442\u043e \u043f\u0440\u0438\u0434\u0443\u043c\u044b\u0432\u0430\u0435\u0442 \u044d\u0442\u0438 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u044f? \u041d\u0430 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0435 \u0432\u0435\u0441\u044c \u043f\u0430\u0444\u043e\u0441 \u0441\u0432\u043e\u0434\u0438\u0442\u0441\u044f \u043a \u0442\u043e\u043c\u0443, \u0447\u0442\u043e \u043d\u0430\u0434\u043e \u043f\u0440\u043e\u0441\u0442\u043e \u0437\u0430\u0432\u0435\u0441\u0442\u0438 \u0435\u0449\u0435 \u043e\u0434\u0438\u043d \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b:<\/p>\n<p>  <\/p>\n<pre><code class=\"swift\">protocol IHaveAnyViewModel: AnyObject {     var anyViewModel: Any? { get set } }<\/code><\/pre>\n<p>  <\/p>\n<p>\u042d\u0442\u043e\u0442 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b \u043d\u0435 \u043e\u0431\u0440\u0435\u043c\u0435\u043d\u0435\u043d \u0430\u0441\u0441\u043e\u0446\u0438\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u043c \u0442\u0438\u043f\u043e\u043c, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043a \u043d\u0435\u043c\u0443 \u043c\u043e\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u043a\u0430\u0441\u0442\u0438\u0442\u044c \u043b\u044e\u0431\u044b\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u044b. \u041f\u0440\u043e\u0442\u043e\u043a\u043e\u043b <code>IHaveViewModel<\/code> \u043f\u043e\u0447\u0442\u0438 \u043d\u0435 \u0438\u0437\u043c\u0435\u043d\u0438\u043b\u0441\u044f, \u043d\u0430\u0439\u0434\u0438\u0442\u0435 \u043e\u0434\u043d\u043e \u043e\u0442\u043b\u0438\u0447\u0438\u0435:<\/p>\n<p>  <\/p>\n<pre><code class=\"swift\">protocol IHaveViewModel: IHaveAnyViewModel {     associatedtype ViewModel      var viewModel: ViewModel? { get set }     func viewModelChanged(_ viewModel: ViewModel) }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f <code>OrderCell<\/code> \u0442\u0435\u043f\u0435\u0440\u044c \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0442\u0430\u043a:<\/p>\n<p>  <\/p>\n<pre><code class=\"swift\">final class OrderCell: UITableViewCell, IHaveViewModel {     typealias ViewModel = OrderVM      var anyViewModel: Any? {         didSet {             guard let viewModel = anyViewModel as? ViewModel else { return }             viewModelChanged(viewModel)         }     }      var viewModel: ViewModel? {         get {             return anyViewModel as? ViewModel         }         set {             anyViewModel = newValue         }     }      func viewModelChanged(_ viewModel: ViewModel) {         textLabel?.text = viewModel.name     } }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0421\u0432\u043e\u0439\u0441\u0442\u0432\u043e <code>anyViewModel<\/code>, \u043b\u0438\u0448\u0435\u043d\u043d\u043e\u0435 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043e \u0442\u0438\u043f\u0435, \u0443\u0434\u043e\u0431\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u043d\u0430\u0440\u0443\u0436\u0438 \u043a\u043b\u0430\u0441\u0441\u0430. \u041e\u043d\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043b\u044e\u0431\u0443\u044e \u0432\u044c\u044e\u0445\u0443 \u043f\u0440\u0438\u0432\u0435\u0441\u0442\u0438 \u043a \u0442\u0438\u043f\u0443 <code>IHaveAnyViewModel<\/code> \u0438 \u0437\u0430\u0434\u0430\u0442\u044c \u0435\u0439 \u0432\u044c\u044e-\u043c\u043e\u0434\u0435\u043b\u044c. \u0421\u0432\u043e\u0439\u0441\u0442\u0432\u043e <code>viewModel<\/code>, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0442\u0438\u043f\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u0443\u044e \u0432\u044c\u044e-\u043c\u043e\u0434\u0435\u043b\u044c, \u0443\u0434\u043e\u0431\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0432\u043d\u0443\u0442\u0440\u0438 \u043a\u043b\u0430\u0441\u0441\u0430, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u0432 \u043c\u0435\u0442\u043e\u0434\u0435 <code>viewModelChanged(_:)<\/code> \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0442\u044c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0432\u044c\u044e\u0445\u0438. <\/p>\n<p>  <\/p>\n<p>\u0423\u0434\u0438\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e, \u043d\u0430\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043e\u0442\u0432\u0440\u0430\u0442\u0438\u0442\u0435\u043b\u044c\u043d\u0443\u044e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e MVVM \u043c\u044b \u0441 \u0432\u0430\u043c\u0438 \u0442\u043e\u043b\u044c\u043a\u043e \u0447\u0442\u043e \u043d\u0430\u043f\u0438\u0441\u0430\u043b\u0438: \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0435\u044e \u0440\u0435\u0448\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e. \u0412\u0441\u0435 \u043f\u043e\u0442\u043e\u043c\u0443, \u0447\u0442\u043e \u0432 \u043a\u0430\u0436\u0434\u043e\u0439 \u0432\u044c\u044e\u0445\u0435 \u0438 \u0432\u044c\u044e-\u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0435 \u043c\u044b \u0432\u044b\u043d\u0443\u0436\u0434\u0435\u043d\u044b \u0431\u0443\u0434\u0435\u043c \u043f\u0438\u0441\u0430\u0442\u044c \u043e\u0447\u0435\u043d\u044c \u043c\u043d\u043e\u0433\u043e \u043f\u043e\u0432\u0442\u043e\u0440\u044f\u044e\u0449\u0435\u0433\u043e\u0441\u044f \u043a\u043e\u0434\u0430 \u0434\u043b\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 <code>IHaveViewModel<\/code>, \u0447\u0442\u043e, \u0432\u043e\u043e\u0431\u0449\u0435 \u0433\u043e\u0432\u043e\u0440\u044f, \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0443\u0442\u043e\u043c\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0438 \u043d\u0438 \u043a\u0430\u043f\u0435\u043b\u044c\u043a\u0438 \u043d\u0435 \u0432\u0435\u0441\u0435\u043b\u043e. \u0425\u043e\u0440\u043e\u0448\u0430\u044f \u043d\u043e\u0432\u043e\u0441\u0442\u044c \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u044d\u0442\u043e\u0442 \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043e\u043a \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u0435\u043e\u0434\u043e\u043b\u0435\u0442\u044c \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f, \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u044e\u0449\u0435\u0433\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u0434\u043b\u044f \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0430 <code>IHaveViewModel<\/code>.<\/p>\n<p>  <\/p>\n<h2 id=\"1.4\">\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u0447\u0435\u0440\u0435\u0437 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0430<\/h2>\n<p>  <\/p>\n<p>\u0412 \u043e\u0441\u043d\u043e\u0432\u0435 \u043a\u043e\u043d\u0446\u0435\u043f\u0446\u0438\u0438 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0439 (extensions) \u043b\u0435\u0436\u0438\u0442 \u043e\u0447\u0435\u043d\u044c \u043f\u0440\u043e\u0441\u0442\u0430\u044f \u0438\u0434\u0435\u044f: \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f \u043d\u0435 \u043c\u043e\u0433\u0443\u0442 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0442\u044c \u043d\u0438\u043a\u0430\u043a\u0438\u0445 \u043d\u043e\u0432\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 \u043a \u0442\u0438\u043f\u0443. \u0412\u0441\u0435 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 \u0438 \u043c\u0435\u0442\u043e\u0434\u044b, \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c\u044b\u0435 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435\u043c, \u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u043d\u0435 \u0447\u0435\u043c \u0438\u043d\u044b\u043c, \u043a\u0430\u043a \u043a\u043e\u043c\u0431\u0438\u043d\u0430\u0446\u0438\u0435\u0439 \u0434\u0430\u043d\u043d\u044b\u0445, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0443\u0436\u0435 \u043e\u0431\u044a\u044f\u0432\u043b\u0435\u043d\u044b \u0432 \u0442\u0438\u043f\u0435.<\/p>\n<p>  <\/p>\n<p>\u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u0435\u0441\u043b\u0438 \u043c\u044b \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u0434\u043b\u044f <code>IHaveViewModel<\/code>, \u0442\u043e \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u043e \u0441\u0442\u043e\u043b\u043a\u043d\u0435\u043c\u0441\u044f \u0441 \u043d\u0435\u0438\u0437\u0431\u0435\u0436\u043d\u044b\u043c\u0438 \u0441\u043b\u043e\u0436\u043d\u043e\u0441\u0442\u044f\u043c\u0438 \u0432 \u0432\u0438\u0434\u0435 \u043e\u0448\u0438\u0431\u043a\u0438 <em>extensions must not contain stored properties:<\/em><\/p>\n<p>  <\/p>\n<pre><code class=\"swift\">extension IHaveViewModel {     var anyViewModel: Any? \/\/ \u041d\u0435 \u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u0443\u0435\u0442\u0441\u044f :( }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0412\u043f\u043e\u043b\u043d\u0435 \u0432\u0435\u0440\u043e\u044f\u0442\u043d\u043e, \u0447\u0442\u043e \u044d\u0442\u043e \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435 \u0441\u0432\u044f\u0437\u0430\u043d\u043e \u0441 \u043d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c\u044e \u043d\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u043e \u0430\u043b\u043b\u043e\u0446\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u0430\u043c\u044f\u0442\u044c \u043f\u043e\u0434 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443, \u043e\u0431\u043c\u0430\u0437\u0430\u043d\u043d\u0443\u044e \u044d\u043a\u0441\u0442\u0435\u043d\u0448\u0435\u043d\u0430\u043c\u0438 \u0441 \u0445\u0440\u0430\u043d\u0438\u043c\u044b\u043c\u0438 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430\u043c\u0438. \u041d\u043e \u044d\u0442\u043e \u0434\u0430\u0436\u0435 \u043a \u043b\u0443\u0447\u0448\u0435\u043c\u0443.<\/p>\n<p>  <\/p>\n<p>\u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u044c\u0442\u0435, \u0432 \u043a\u0430\u043a\u0443\u044e \u0430\u043d\u0430\u0440\u0445\u0438\u044e \u043f\u043e\u0433\u0440\u0443\u0437\u0438\u043b\u043e\u0441\u044c \u0431\u044b \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435, \u0435\u0441\u043b\u0438 \u0431\u044b \u0432\u0441\u0435 \u043c\u043e\u0433\u043b\u0438 \u0432\u043e\u0442 \u0442\u0430\u043a \u0437\u0430\u043f\u0440\u043e\u0441\u0442\u043e \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0442\u044c \u043d\u043e\u0432\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u043a \u043b\u044e\u0431\u044b\u043c \u0442\u0438\u043f\u0430\u043c. \u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043e\u0448\u0438\u0431\u043a\u0438 <em>extensions must not contain stored properties<\/em> \u0441\u043e\u0437\u0434\u0430\u0442\u0435\u043b\u0438 \u044f\u0437\u044b\u043a\u0430 \u043d\u0435\u0436\u043d\u043e \u0437\u0430\u0431\u043e\u0442\u044f\u0442\u0441\u044f \u043e \u043d\u0430\u0441, \u043d\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044f \u043f\u043e\u0439\u0442\u0438 \u043f\u043e \u0441\u043a\u043e\u043b\u044c\u0437\u043a\u043e\u0439 \u0434\u043e\u0440\u043e\u0436\u043a\u0435, \u043f\u043e\u043a\u0430\u0442\u0438\u0442\u044c\u0441\u044f \u043f\u043e\u0434 \u043e\u0442\u043a\u043e\u0441, \u0440\u0438\u043d\u0443\u0442\u044c\u0441\u044f \u0432 \u0431\u0443\u0440\u043b\u044f\u0449\u0443\u044e \u0431\u0435\u0437\u0434\u043d\u0443 \u0445\u0430\u043e\u0441\u0430. \u0412\u043e\u043f\u0440\u0435\u043a\u0438 \u0438\u0445 \u0441\u0442\u0430\u0440\u0430\u043d\u0438\u044f\u043c, \u0438\u043c\u0435\u043d\u043d\u043e \u044d\u0442\u0438\u043c \u043c\u044b \u0441\u0435\u0439\u0447\u0430\u0441 \u0438 \u0437\u0430\u0439\u043c\u0435\u043c\u0441\u044f, \u043f\u0440\u0435\u0434\u0432\u0430\u0440\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0445\u0430\u043a\u043d\u0443\u0432 \u0441\u0432\u0438\u0444\u0442\u043e\u0432\u044b\u0435 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0441\u0442\u0430\u0440\u043e\u0433\u043e \u0434\u043e\u0431\u0440\u043e\u0433\u043e Objective-C-\u0440\u0430\u043d\u0442\u0430\u0439\u043c\u0430. \u0427\u0438\u0442\u0430\u0439 \u0434\u0430\u043b\u044c\u0448\u0435, \u0435\u0441\u043b\u0438 \u043d\u0435 \u0431\u043e\u0438\u0448\u044c\u0441\u044f, \u0447\u0442\u043e \u043f\u043e\u043b\u0438\u0446\u0438\u044f \u044d\u043a\u0441\u0442\u0435\u043d\u0448\u0435\u043d\u043e\u0432 \u043f\u0440\u0438\u0434\u0435\u0442 \u0437\u0430 \u0442\u043e\u0431\u043e\u0439:<\/p>\n<p>  <\/p>\n<pre><code class=\"swift\">private var viewModelKey: UInt8 = 0  extension IHaveViewModel {      var anyViewModel: Any? {         get {             return objc_getAssociatedObject(self, &amp;viewModelKey)         }         set {             let viewModel = newValue as? ViewModel              objc_setAssociatedObject(self,                  &amp;viewModelKey,                  viewModel,                  .OBJC_ASSOCIATION_RETAIN_NONATOMIC)              if let viewModel = viewModel {                 viewModelChanged(viewModel)             }     }      var viewModel: ViewModel? {         get {             return anyViewModel as? ViewModel         }         set {             anyViewModel = newValue         }     }      func viewModelChanged(_ viewModel: ViewModel) {      } }<\/code><\/pre>\n<p>  <\/p>\n<p>\u042d\u0442\u043e \u043a\u043e\u0434 \u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u0443\u0435\u0442\u0441\u044f, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u0432 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0438 \u043c\u044b \u043d\u0435 \u043e\u0431\u044a\u044f\u0432\u0438\u043b\u0438 \u043d\u0438 \u043e\u0434\u043d\u043e\u0433\u043e \u043d\u043e\u0432\u043e\u0433\u043e \u0445\u0440\u0430\u043d\u0438\u043c\u043e\u0433\u043e \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430. \u041d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0433\u043e \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0434\u043e\u0441\u0442\u0438\u0447\u044c \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0434\u0432\u0443\u0445 \u0444\u0443\u043d\u043a\u0446\u0438\u0439 \u044f\u0437\u044b\u043a\u0430 \u0421\u0438: <code>objc_getAssociatedObject<\/code> \u0438 <code>objc_setAssociatedObject<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0432 \u0433\u0435\u0442\u0435\u0440\u0435 \u0438 \u0441\u0435\u0442\u0435\u0440\u0435 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e.<\/p>\n<p>  <\/p>\n<p>\u042d\u0442\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0441 \u0443\u0441\u043f\u0435\u0445\u043e\u043c \u0437\u0430\u043c\u0435\u043d\u044f\u044e\u0442 \u0445\u0440\u0430\u043d\u0438\u043c\u044b\u0435 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430, \u0442\u0430\u043a \u043a\u0430\u043a \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0442 \u0441\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u043e\u0431\u044a\u0435\u043a\u0442\u0443 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u043e \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u043e\u043c\u0443 \u043a\u043b\u044e\u0447\u0443. \u041e\u0431\u044b\u0447\u043d\u043e \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0442\u0430\u043a\u043e\u0433\u043e \u043a\u043b\u044e\u0447\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442 \u0430\u0434\u0440\u0435\u0441 \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u043e\u0439 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439, \u0442\u0430\u043a\u043e\u0439 \u043a\u0430\u043a <code>viewModelKey<\/code>. \u0411\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f <code>OrderCell<\/code> \u0438\u0437\u0431\u0430\u0432\u0438\u043b\u0430\u0441\u044c \u043e\u0442 \u043b\u0438\u0448\u043d\u0435\u0433\u043e \u043a\u043e\u0434\u0430 \u0438 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0442\u0435\u043f\u0435\u0440\u044c \u0433\u043e\u0440\u0430\u0437\u0434\u043e \u043f\u0440\u0438\u0432\u043b\u0435\u043a\u0430\u0442\u0435\u043b\u044c\u043d\u0435\u0435:<\/p>\n<p>  <\/p>\n<pre><code class=\"swift\">final class OrderCell: UITableViewCell, IHaveViewModel {     typealias ViewModel = OrderVM      func viewModelChanged(_ viewModel: OrderVM) {         textLabel?.text = viewModel.name     } }<\/code><\/pre>\n<p>  <\/p>\n<p>\u041f\u043e\u0432\u0442\u043e\u0440\u044e\u0441\u044c, \u0447\u0442\u043e \u0441\u043f\u043e\u0441\u043e\u0431, \u043f\u043e\u043a\u0430\u0437\u0430\u043d\u043d\u044b\u0439 \u0432\u044b\u0448\u0435, \u0441\u0435\u0440\u044c\u0435\u0437\u043d\u043e \u043d\u0430\u0440\u0443\u0448\u0430\u0435\u0442 \u043a\u043e\u043d\u0446\u0435\u043f\u0446\u0438\u044e \u044d\u043a\u0441\u0442\u0435\u043d\u0448\u0435\u043d\u043e\u0432. \u041f\u043e\u0441\u0442\u0430\u0440\u0430\u0439\u0442\u0435\u0441\u044c \u043d\u0435 \u043f\u043e\u0434\u0441\u0435\u0441\u0442\u044c \u043d\u0430 \u0438\u0433\u043b\u0443 Objective-C-\u0440\u0430\u043d\u0442\u0430\u0439\u043c\u0430 \u0438 \u043d\u0435 \u043d\u0430\u0447\u0430\u0442\u044c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0435\u0433\u043e \u043f\u043e \u043f\u043e\u0432\u043e\u0434\u0443 \u0438 \u0431\u0435\u0437 \u043f\u043e\u0432\u043e\u0434\u0430\u00a0\u2014 \u044d\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0437\u0430\u043f\u0443\u0442\u0430\u0442\u044c \u0432\u0430\u0448 \u0438 \u0431\u0435\u0437 \u0442\u043e\u0433\u043e \u043d\u0435\u0438\u0434\u0435\u0430\u043b\u044c\u043d\u044b\u0439 \u043a\u043e\u0434. \u0412 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043d\u0430\u0440\u0443\u0448\u0435\u043d\u0438\u0435 \u043f\u0440\u0430\u0432\u0438\u043b \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u0438\u0441\u0430\u0442\u044c \u0433\u043e\u0440\u0430\u0437\u0434\u043e \u043c\u0435\u043d\u044c\u0448\u0435 \u043a\u043e\u0434\u0430 \u0438 \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0441\u043b\u0438\u0448\u043a\u043e\u043c \u043f\u0440\u0438\u0432\u043b\u0435\u043a\u0430\u0442\u0435\u043b\u044c\u043d\u043e, \u0447\u0442\u043e\u0431\u044b \u0438\u043c \u043d\u0435 \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f.<\/p>\n<p>  <\/p>\n<h2 id=\"1.5\">\u041e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0441\u043f\u0438\u0441\u043a\u0430 \u0437\u0430\u043a\u0430\u0437\u043e\u0432 (\u043d\u0430 \u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435 \u043d\u0435\u0442)<\/h2>\n<p>  <\/p>\n<p>\u0412\u043e\u043e\u0440\u0443\u0436\u0438\u0432\u0448\u0438\u0441\u044c \u0434\u0435\u0444\u043e\u043b\u0442\u043d\u043e\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0435\u0439 <code>IHaveViewModel<\/code> \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u0441\u0442\u0440\u043e \u043d\u0430\u043a\u0438\u0434\u0430\u0442\u044c \u043a\u043e\u0434 \u0441\u0432\u044f\u0437\u043a\u0438 <code>OrdersVC\u00a0\u2014 OrdersVM<\/code>. \u0412\u044c\u044e-\u043c\u043e\u0434\u0435\u043b\u044c \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0442\u0430\u043a:<\/p>\n<p>  <\/p>\n<pre><code class=\"swift\">final class OrdersVM {     var orders: [OrderVM] = []      private var ordersProvider: OrdersProvider      init(ordersProvider: OrdersProvider) {         self.ordersProvider = ordersProvider     }      func loadOrders() {         ordersProvider.loadOrders() { [weak self] model in             self?.orders = model.map { OrderVM(order: $0) }         }     } }<\/code><\/pre>\n<p>  <\/p>\n<p><code>OrdersVM<\/code> \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 <code>OrdersProvider<\/code> \u0434\u043b\u044f \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u043e\u0442\u0437\u044b\u0432\u043e\u0432. <code>OrdersProvider<\/code> \u0441 \u0443\u043c\u043d\u044b\u043c \u0432\u0438\u0434\u043e\u043c \u0438\u043c\u0438\u0442\u0438\u0440\u0443\u0435\u0442 \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u044b\u0439 \u0437\u0430\u043f\u0440\u043e\u0441 \u0438 \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u0441\u043f\u0438\u0441\u043a\u043e\u043c \u043e\u0442\u0437\u044b\u0432\u043e\u0432 \u0447\u0435\u0440\u0435\u0437 \u0441\u0435\u043a\u0443\u043d\u0434\u0443 \u043f\u043e\u0441\u043b\u0435 \u0432\u044b\u0437\u043e\u0432\u0430 <code>loadOrders(completion:)<\/code>:<\/p>\n<p>  <\/p>\n<pre><code class=\"swift\">struct Order {     let name: String     let id: Int }  final class OrdersProvider {     func loadOrders(completion: @escaping ([Order]) -&gt; Void) {         DispatchQueue.main.asyncAfter(deadline: .now() + 1) {             completion((0...99).map { Order(name: &quot;Order&quot;, id: $0) })         }     } }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0418, \u043d\u0430\u043a\u043e\u043d\u0435\u0446, \u0432\u044c\u044e-\u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440:<\/p>\n<p>  <\/p>\n<pre><code class=\"swift\">final class OrdersVC: UIViewController, IHaveViewModel {     typealias ViewModel = OrdersVM      private lazy var tableView = UITableView()      override func viewDidLoad() {         super.viewDidLoad()          tableView.dataSource = self         tableView.register(OrderCell.self, forCellReuseIdentifier: &quot;order&quot;)         view.addSubview(tableView)          viewModel?.loadOrders()     }      override func viewDidLayoutSubviews() {         super.viewDidLayoutSubviews()          tableView.frame = view.bounds     }      func viewModelChanged(_ viewModel: OrdersVM) {         tableView.reloadData()     } }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0412 \u043c\u0435\u0442\u043e\u0434\u0435 <code>viewDidLoad()<\/code> \u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u043e\u043c \u0432\u044b\u0437\u043e\u0432\u0430 <code>loadOrders()<\/code> \u043c\u044b \u0441\u043e\u043e\u0431\u0449\u0430\u0435\u043c \u0432\u044c\u044e-\u043c\u043e\u0434\u0435\u043b\u0438, \u0447\u0442\u043e \u043d\u0430\u043c \u0445\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u0431\u044b \u043d\u0430\u0447\u0430\u0442\u044c \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0443 \u0437\u0430\u043a\u0430\u0437\u043e\u0432. \u041d\u0430 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u0432\u044c\u044e-\u043c\u043e\u0434\u0435\u043b\u0438 \u043c\u044b \u0440\u0435\u0430\u0433\u0438\u0440\u0443\u0435\u043c \u0432 \u043c\u0435\u0442\u043e\u0434\u0435 <code>viewModelChanged(_:)<\/code>, \u043f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0436\u0430\u044f \u0442\u0430\u0431\u043b\u0438\u0446\u0443. \u0420\u0430\u0431\u043e\u0442\u0443 \u0441 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u043e\u043c \u0434\u0430\u043d\u043d\u044b\u0445 \u0434\u043b\u044f \u0442\u0430\u0431\u043b\u0438\u0446\u044b \u043c\u044b \u0432\u044b\u043d\u0435\u0441\u043b\u0438 \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u044d\u043a\u0441\u0442\u0435\u043d\u0448\u0435\u043d:<\/p>\n<p>  <\/p>\n<pre><code class=\"swift\">extension OrdersVC: UITableViewDataSource {     func tableView(_ tableView: UITableView,          numberOfRowsInSection section: Int) -&gt; Int {          return viewModel?.orders.count ?? 0     }      func tableView(_ tableView: UITableView,          cellForRowAt indexPath: IndexPath) -&gt; UITableViewCell {          let cell = tableView.dequeueReusableCell(withIdentifier: &quot;order&quot;,              for: indexPath)          if let cell = cell as? IHaveAnyViewModel {             cell.anyViewModel = viewModel?.orders[indexPath.row]         }         return cell     } }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0417\u0434\u0435\u0441\u044c \u0432\u0441\u0435 \u0441\u043e\u0432\u0435\u0440\u0448\u0435\u043d\u043d\u043e \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e, \u0437\u0430 \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435\u043c \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u043a \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0443 <code>IHaveAnyViewModel<\/code>, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0436\u0438\u0437\u043d\u0435\u043d\u043d\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u0441\u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432\u044c\u044e-\u043c\u043e\u0434\u0435\u043b\u044c \u044f\u0447\u0435\u0439\u043a\u0438. \u0412\u043e\u0442 \u0438 \u0432\u0441\u0435. \u0422\u0435\u043f\u0435\u0440\u044c \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0441\u043e\u0431\u0440\u0430\u0442\u044c \u0432\u0441\u0435\u0445 \u0440\u0435\u0431\u044f\u0442 \u0432\u043c\u0435\u0441\u0442\u0435, \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u0442\u0430\u043a:<\/p>\n<p>  <\/p>\n<pre><code class=\"swift\">let viewModel = OrdersVM(ordersProvider: OrdersProvider()) let viewController = OrdersVC() viewController.viewModel = viewModel<\/code><\/pre>\n<p>  <\/p>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0442\u043e\u0433\u043e \u043a\u0430\u043a \u043c\u044b \u043e\u0442\u043e\u0431\u0440\u0430\u0437\u0438\u043c <code>OrdersVC<\/code> \u043d\u0430 \u044d\u043a\u0440\u0430\u043d\u0435, \u043c\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u0443\u0432\u0438\u0434\u0435\u0442\u044c \u0442\u0430\u0431\u043b\u0438\u0446\u0443 \u0441\u043e \u0441\u043f\u0438\u0441\u043a\u043e\u043c \u0437\u0430\u043a\u0430\u0437\u043e\u0432. \u041e\u0434\u043d\u0430\u043a\u043e \u0432\u043d\u0438\u043c\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u0447\u0438\u0442\u0430\u0442\u0435\u043b\u044c, \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u0443\u0436\u0435 \u0434\u043e\u0433\u0430\u0434\u0430\u043b\u0441\u044f, \u0447\u0442\u043e \u043d\u0438\u0447\u0435\u0433\u043e \u0443 \u043d\u0430\u0441 \u043d\u0435 \u0432\u044b\u0439\u0434\u0435\u0442 \u0438 \u0441\u043f\u0438\u0441\u043e\u043a \u0437\u0430\u043a\u0430\u0437\u043e\u0432 \u043c\u044b \u0442\u0430\u043a \u0438 \u043d\u0435 \u0443\u0432\u0438\u0434\u0438\u043c.<\/p>\n<p>  <\/p>\n<p>\u0414\u0435\u043b\u043e \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u043c\u0435\u0442\u043e\u0434 <code>loadOrders(completion:)<\/code> \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u043e, \u0441\u043f\u0438\u0441\u043e\u043a \u0437\u0430\u043a\u0430\u0437\u043e\u0432 \u0444\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0447\u0435\u0440\u0435\u0437 \u0441\u0435\u043a\u0443\u043d\u0434\u0443 \u043f\u043e\u0441\u043b\u0435 \u0432\u044b\u0437\u043e\u0432\u0430 <code>viewDidLoad()<\/code>, \u0430 \u044d\u0442\u043e \u0437\u043d\u0430\u0447\u0438\u0442, \u0447\u0442\u043e \u043d\u0430 \u043c\u043e\u043c\u0435\u043d\u0442 \u0432\u044b\u0437\u043e\u0432\u0430 <code>reloadData()<\/code> \u043c\u0430\u0441\u0441\u0438\u0432 <code>orders<\/code> \u043f\u0443\u0441\u0442. \u0414\u043b\u044f \u0442\u043e\u0433\u043e \u0447\u0442\u043e\u0431\u044b \u0432\u0441\u0435 \u0437\u0430\u0440\u0430\u0431\u043e\u0442\u0430\u043b\u043e, \u043d\u0430\u043c \u043d\u0435 \u0445\u0432\u0430\u0442\u0430\u0435\u0442 \u043e\u0434\u043d\u043e\u0439 \u0432\u0430\u0436\u043d\u043e\u0439 \u0434\u0435\u0442\u0430\u043b\u0438\u00a0\u2014 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f \u043e\u0431 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f\u0445 \u0432\u044c\u044e-\u043c\u043e\u0434\u0435\u043b\u0438. <\/p>\n<p>  <\/p>\n<h2 id=\"1.6\">\u0423\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0435 \u043e\u0431 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0438 \u043c\u043e\u0434\u0435\u043b\u0438 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f<\/h2>\n<p>  <\/p>\n<p>\u041e\u0434\u043d\u0430 \u0438\u0437 \u043a\u043b\u044e\u0447\u0435\u0432\u044b\u0445 \u043a\u043e\u043d\u0446\u0435\u043f\u0446\u0438\u0439 MVVM \u0441\u043e\u0441\u0442\u043e\u0438\u0442 \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e ViewModel \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u0436\u0435\u043b\u0430\u0435\u0442 \u0437\u043d\u0430\u0442\u044c \u043e View. \u041e\u043d\u0430 \u043d\u0435 \u0434\u0435\u0440\u0436\u0438\u0442 \u0441\u0441\u044b\u043b\u043a\u0443 \u043d\u0430 View \u0438 \u043d\u0435 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442 \u0435\u0435 \u043c\u0435\u0442\u043e\u0434\u044b\u00a0\u2014 \u043d\u0438 \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e, \u043d\u0438 \u0447\u0435\u0440\u0435\u0437 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b. \u0412\u044c\u044e-\u043c\u043e\u0434\u0435\u043b\u044c \u0432\u0435\u0434\u0435\u0442 \u0441\u0435\u0431\u044f \u0442\u0430\u043a, \u0441\u043b\u043e\u0432\u043d\u043e View \u043f\u0440\u043e\u0441\u0442\u043e-\u043d\u0430\u043f\u0440\u043e\u0441\u0442\u043e \u043d\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442. \u041a\u043e\u043c\u043f\u0435\u043d\u0441\u0438\u0440\u0443\u044f \u0441\u0432\u043e\u0435 \u043d\u0435\u0436\u0435\u043b\u0430\u043d\u0438\u0435 \u043e\u0431\u0449\u0430\u0442\u044c\u0441\u044f \u0441 View, \u0432\u044c\u044e-\u043c\u043e\u0434\u0435\u043b\u044c \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f \u043e \u0432\u0430\u0436\u043d\u044b\u0445 \u0441\u043e\u0431\u044b\u0442\u0438\u044f\u0445, \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u044f\u0449\u0438\u0445 \u0432 \u0435\u0435 \u0436\u0438\u0437\u043d\u0438. \u042d\u0442\u0438\u043c \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u043e\u043c \u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f View, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0442\u044c \u0441\u0435\u0431\u044f \u0432 \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u043c \u0432\u0438\u0434\u0435, \u0438 \u043d\u0430 \u0434\u0438\u0430\u0433\u0440\u0430\u043c\u043c\u0435 \u043a\u043b\u0430\u0441\u0441\u043e\u0432 \u044d\u0442\u043e \u0432\u044b\u0440\u0430\u0436\u0430\u0435\u0442\u0441\u044f \u043f\u0443\u043d\u043a\u0442\u0438\u0440\u043d\u043e\u0439 \u0441\u0442\u0440\u0435\u043b\u043a\u043e\u0439, \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043d\u043e\u0439 \u043e\u0442 ViewModel \u043a View.<\/p>\n<p>  <\/p>\n<p>\u0412 \u0441\u0430\u043c\u043e\u0431\u044b\u0442\u043d\u043e\u043c \u043c\u0438\u0440\u0435 iOS-\u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0441\u043b\u043e\u0436\u0438\u043b\u0430\u0441\u044c \u043d\u0435\u0432\u0435\u0441\u0435\u043b\u0430\u044f \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u044f: \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f \u043e\u0431 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0438 \u0441\u0432\u043e\u0439\u0441\u0442\u0432 \u043c\u043e\u0434\u0435\u043b\u0438 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0447\u0430\u0449\u0435 \u0432\u0441\u0435\u0433\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044e\u0442 \u0447\u0435\u0440\u0435\u0437 \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0435 \u0441\u0438\u0433\u043d\u0430\u043b\u044b. \u042d\u0442\u043e\u0442 \u043f\u043e\u0434\u0445\u043e\u0434 \u043d\u0430\u0441\u0442\u043e\u043b\u044c\u043a\u043e \u0440\u0430\u0441\u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0435\u043d, \u0447\u0442\u043e \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0430\u0432\u0442\u043e\u0440\u044b \u0435\u0434\u0432\u0430 \u043b\u0438 \u043d\u0435 \u0441\u0442\u0430\u0432\u044f\u0442 \u0437\u043d\u0430\u043a \u0440\u0430\u0432\u0435\u043d\u0441\u0442\u0432\u0430 \u043c\u0435\u0436\u0434\u0443 MVVM \u0438 <a href=\"https:\/\/en.wikipedia.org\/wiki\/Reactive_extensions\">Rx<\/a>. \u041c\u0435\u0436\u0434\u0443 \u0442\u0435\u043c MVVM \u0432\u043e\u0432\u0441\u0435 \u043d\u0435 \u043f\u043e\u0434\u0440\u0430\u0437\u0443\u043c\u0435\u0432\u0430\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0441\u0442\u043e\u0440\u043e\u043d\u043d\u0435\u0433\u043e \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0433\u043e \u0444\u0440\u044d\u0439\u043c\u0432\u043e\u0440\u043a\u0430. \u0412 \u0442\u043e\u043c \u0436\u0435 .NET\u00a0\u2014 \u0438\u0441\u0442\u043e\u0440\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u0440\u043e\u0434\u0438\u043d\u0435 \u043f\u0430\u0442\u0442\u0435\u0440\u043d\u0430\u00a0\u2014 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442 \u0447\u0435\u0440\u0435\u0437 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 <a href=\"https:\/\/docs.microsoft.com\/en-us\/dotnet\/api\/system.componentmodel.inotifypropertychanged\">INotifyPropertyChanged<\/a>, \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c\u044b\u0439 \u043d\u0430 \u0441\u0442\u043e\u0440\u043e\u043d\u0435 ViewModel, \u0432 \u0441\u0432\u044f\u0437\u043a\u0435 \u0441 \u0434\u0435\u043a\u043b\u0430\u0440\u0430\u0442\u0438\u0432\u043d\u044b\u043c\u0438 \u0431\u0438\u043d\u0434\u0438\u043d\u0433\u0430\u043c\u0438\u00a0\u2014 \u043d\u0430 \u0441\u0442\u043e\u0440\u043e\u043d\u0435 View.<\/p>\n<p>  <\/p>\n<p>\u0410\u0432\u0442\u043e\u0440 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438, \u043c\u044f\u0433\u043a\u043e \u0433\u043e\u0432\u043e\u0440\u044f, \u043d\u0435 \u0444\u0430\u043d\u0430\u0442 \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0433\u043e \u043f\u043e\u0434\u0445\u043e\u0434\u0430. \u041e\u0447\u0435\u043d\u044c \u0443\u0436 \u043d\u0435\u043f\u0440\u043e\u0441\u0442\u043e \u0431\u044b\u0432\u0430\u0435\u0442 \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u0442\u044c\u0441\u044f \u0432 \u0445\u0438\u0442\u0440\u043e\u0441\u043f\u043b\u0435\u0442\u0435\u043d\u0438\u0438 \u0441\u0438\u0433\u043d\u0430\u043b\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0441\u0442\u0440\u0435\u043b\u044f\u044e\u0442 \u0434\u0440\u0443\u0433\u0438\u043c\u0438 \u0441\u0438\u0433\u043d\u0430\u043b\u0430\u043c\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0442\u0440\u0430\u043d\u0441\u0444\u043e\u0440\u043c\u0438\u0440\u0443\u044e\u0442\u0441\u044f \u0432 \u0442\u0440\u0435\u0442\u044c\u0438 \u0441\u0438\u0433\u043d\u0430\u043b\u044b. \u041d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0437\u0430\u043f\u0443\u0442\u0430\u043d\u043d\u044b\u0439 \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0439 \u043a\u043e\u0434 \u0441\u043b\u0438\u0448\u043a\u043e\u043c \u043f\u0440\u043e\u0441\u0442\u043e. \u0421\u0435\u0433\u043e\u0434\u043d\u044f \u0432\u044b \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442\u0435 \u0432 \u043f\u0440\u043e\u0435\u043a\u0442 \u043e\u0434\u0438\u043d \u043c\u0430\u043b\u0435\u043d\u044c\u043a\u0438\u0439 \u0441\u0438\u0433\u043d\u0430\u043b\u044c\u0447\u0438\u043a, \u0430 \u0437\u0430\u0432\u0442\u0440\u0430 \u0432\u0430\u0448\u0435 \u043f\u0440\u043e\u0441\u0442\u043e\u0435 \u043d\u0430 \u043f\u0435\u0440\u0432\u044b\u0439 \u0432\u0437\u0433\u043b\u044f\u0434 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043f\u0440\u0435\u0432\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f \u0432 \u043d\u0435\u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c\u044b\u0439 \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0439 \u0438\u0441\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b\u044c, \u043d\u0435\u0441\u0443\u0449\u0438\u0439\u0441\u044f \u043d\u0430 \u0441\u0432\u0435\u0440\u0445\u0437\u0432\u0443\u043a\u043e\u0432\u043e\u0439 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0438 \u0432 \u0431\u0435\u0437\u0434\u043d\u0443 \u043e\u0442\u0447\u0430\u044f\u043d\u0438\u044f. \u0414\u0430 \u0438 \u043d\u0435 \u0445\u043e\u0447\u0435\u0442\u0441\u044f \u0432 \u043c\u0435\u043b\u043a\u0438\u0439 \u0434\u043e\u043c\u0430\u0448\u043d\u0438\u0439 \u043f\u0440\u043e\u0435\u043a\u0442 \u0446\u0435\u043b\u044b\u0439 RxSwift \u0442\u0430\u0449\u0438\u0442\u044c, \u0430 Combine\u00a0\u2014 \u0442\u0430\u043a \u0432\u043e\u043e\u0431\u0449\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0441 iOS 13. <\/p>\n<p>  <\/p>\n<p>\u0412 \u043e\u0431\u0449\u0435\u043c, \u043c\u044b \u0441 \u0432\u0430\u043c\u0438, \u043a\u0430\u043a \u043e\u0431\u044b\u0447\u043d\u043e, \u043f\u043e\u0439\u0434\u0435\u043c \u0441\u043a\u043e\u043b\u044c\u0437\u043a\u043e\u0439, \u043d\u043e \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e\u0439 \u0434\u043e\u0440\u043e\u0436\u043a\u043e\u0439 \u0438 \u043d\u0430\u043f\u0438\u0448\u0435\u043c \u043f\u043e\u0434 iOS \u043d\u0435\u0447\u0442\u043e \u043f\u043e\u0445\u043e\u0436\u0435\u0435 <a href=\"https:\/\/docs.microsoft.com\/en-us\/dotnet\/standard\/events\/\">\u043d\u0430 \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u0438\u0437 .NET.<\/a> \u041d\u0430\u0448\u0435 \u0442\u0432\u043e\u0440\u0435\u043d\u0438\u0435 \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0442 \u043d\u0430\u043c \u0432\u0435\u0447\u043d\u0443\u044e \u0441\u043b\u0430\u0432\u0443 \u0438 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439 \u043e\u0431 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f\u0445 ViewModel.<\/p>\n<p>  <\/p>\n<h2 id=\"1.7\">\u0417\u0430\u043d\u043e\u0432\u043e \u0438\u0437\u043e\u0431\u0440\u0435\u0442\u0430\u0435\u043c \u0441\u043e\u0431\u044b\u0442\u0438\u044f<\/h2>\n<p>  <\/p>\n<p>\u0421\u043e\u0431\u044b\u0442\u0438\u044f \u0432 .NET\u00a0\u2014 \u044d\u0442\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u043e\u0433\u043e <a href=\"https:\/\/en.wikipedia.org\/wiki\/Observer_pattern\">\u043f\u0430\u0442\u0442\u0435\u0440\u043d\u0430 \u00ab\u041d\u0430\u0431\u043b\u044e\u0434\u0430\u0442\u0435\u043b\u044c\u00bb<\/a>, \u0442\u0430\u043a\u043e\u0439 \u0441\u0442\u0430\u043b\u043a\u0438\u043d\u0433 \u043e\u0442 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f: \u0432\u044c\u044e\u0445\u0430 \u043e\u0447\u0435\u043d\u044c \u043f\u0440\u0438\u0441\u0442\u0430\u043b\u044c\u043d\u043e \u0441\u043b\u0435\u0434\u0438\u0442 \u0437\u0430 \u0442\u0435\u043c, \u0447\u0442\u043e \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 c \u0432\u044c\u044e-\u043c\u043e\u0434\u0435\u043b\u044c\u044e. \u0414\u043b\u044f \u043d\u0430\u0441 \u043a\u0440\u0438\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0432\u0430\u0436\u043d\u043e, \u0447\u0442\u043e\u0431\u044b \u0441\u043e\u0431\u044b\u0442\u0438\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u043b\u043e \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u0434\u043f\u0438\u0441\u0447\u0438\u043a\u043e\u0432, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043d\u0430 \u043e\u0434\u043d\u043e \u0438 \u0442\u043e \u0436\u0435 \u0441\u043e\u0431\u044b\u0442\u0438\u0435 \u0432\u044c\u044e-\u043c\u043e\u0434\u0435\u043b\u0438 \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u0434\u043f\u0438\u0441\u0430\u0442\u044c\u0441\u044f \u043a\u0430\u043a ViewController, \u0442\u0430\u043a \u0438 \u0435\u0433\u043e View. <\/p>\n<p>  <\/p>\n<p>\u0420\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0442\u0430\u043a\u043e\u0435 \u043d\u0430 Swift \u043c\u043e\u0436\u043d\u043e \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u043c\u0438 \u0441\u043f\u043e\u0441\u043e\u0431\u0430\u043c\u0438: \u0447\u0435\u0440\u0435\u0437 \u043c\u0430\u0441\u0441\u0438\u0432 \u0434\u0435\u043b\u0435\u0433\u0430\u0442\u043e\u0432, \u0447\u0435\u0440\u0435\u0437 \u043c\u0430\u0441\u0441\u0438\u0432 \u0437\u0430\u043c\u044b\u043a\u0430\u043d\u0438\u0439, \u0447\u0435\u0440\u0435\u0437 NotificationCenter. \u0422\u043e\u0442 \u0441\u043f\u043e\u0441\u043e\u0431, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0434\u0436\u0438\u0434\u0430\u0435\u0442 \u0447\u0438\u0442\u0430\u0442\u0435\u043b\u044f \u043d\u0438\u0436\u0435 \u043f\u043e \u0442\u0435\u043a\u0441\u0442\u0443, \u0432\u044b\u043d\u0443\u0436\u0434\u0430\u0435\u0442 \u043d\u0430\u0441 \u0434\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u043a\u043b\u0430\u0441\u0441. \u0412\u043e\u0442 \u0442\u0430\u043a\u043e\u0439:<\/p>\n<p>  <\/p>\n<pre><code class=\"swift\">final class Weak&lt;T: AnyObject&gt; {      private let id: ObjectIdentifier?     private(set) weak var value: T?      var isAlive: Bool {         return value != nil     }      init(_ value: T?) {         self.value = value         if let value = value {             id = ObjectIdentifier(value)         } else {             id = nil         }     } }<\/code><\/pre>\n<p>  <\/p>\n<p>\u042d\u0442\u043e \u043d\u0435\u0445\u0438\u0442\u0440\u0430\u044f \u043e\u0431\u0435\u0440\u0442\u043a\u0430, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0434\u0435\u0440\u0436\u0438\u0442 \u0441\u043b\u0430\u0431\u0443\u044e \u0441\u0441\u044b\u043b\u043a\u0443 \u043d\u0430 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \u0441\u0441\u044b\u043b\u043e\u0447\u043d\u043e\u0433\u043e \u0442\u0438\u043f\u0430, \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0435\u043c\u044b\u0439 \u0432 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0442\u043e\u0440. \u0415\u0441\u043b\u0438 \u0432 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0442\u043e\u0440 \u043f\u0440\u0438\u0448\u043b\u043e \u0447\u0442\u043e-\u0442\u043e \u043e\u0442\u043b\u0438\u0447\u043d\u043e\u0435 \u043e\u0442 <code>nil<\/code>, \u043e\u0431\u0435\u0440\u0442\u043a\u0430 \u0437\u0430\u043f\u043e\u043c\u0438\u043d\u0430\u0435\u0442 <code>ObjectIdentifier<\/code> \u044d\u0442\u043e\u0433\u043e \u043e\u0431\u044a\u0435\u043a\u0442\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u043f\u043e\u0441\u043b\u0435\u0434\u0441\u0442\u0432\u0438\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 <code>Hashable<\/code>:<\/p>\n<p>  <\/p>\n<pre><code class=\"swift\">extension Weak: Hashable {     static func == (lhs: Weak&lt;T&gt;, rhs: Weak&lt;T&gt;) -&gt; Bool {         return lhs.id == rhs.id     }      func hash(into hasher: inout Hasher) {         if let id = id {             hasher.combine(id)         }     } }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0412\u043e\u043e\u0440\u0443\u0436\u0438\u0432\u0448\u0438\u0441\u044c <code>Weak&lt;T&gt;<\/code>, \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u0438\u0441\u0442\u0443\u043f\u0438\u0442\u044c \u043a \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0441\u043e\u0431\u044b\u0442\u0438\u0439:<\/p>\n<p>  <\/p>\n<pre><code class=\"swift\">final class Event&lt;Args&gt; {     \/\/ \u0422\u0443\u0442 \u0436\u0438\u0432\u0443\u0442 \u043f\u043e\u0434\u043f\u0438\u0441\u0447\u0438\u043a\u0438 \u043d\u0430 \u0441\u043e\u0431\u044b\u0442\u0438\u0435 \u0438 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0438 \u044d\u0442\u043e\u0433\u043e \u0441\u043e\u0431\u044b\u0442\u0438\u044f     private var handlers: [Weak&lt;AnyObject&gt;: (Args) -&gt; Void] = [:]      func subscribe&lt;Subscriber: AnyObject&gt;(         _ subscriber: Subscriber,         handler: @escaping (Subscriber, Args) -&gt; Void) {          \/\/ \u0424\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u043c \u043a\u043b\u044e\u0447         let key = Weak&lt;AnyObject&gt;(subscriber)         \/\/ \u041f\u043e\u0447\u0438\u0441\u0442\u0438\u043c \u043c\u0430\u0441\u0441\u0438\u0432 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432 \u043e\u0442 \u043c\u0435\u0440\u0442\u0432\u044b\u0445 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432, \u0447\u0442\u043e\u0431\u044b \u043d\u0435 \u0437\u0430\u0441\u043e\u0440\u044f\u0442\u044c \u043f\u0430\u043c\u044f\u0442\u044c         handlers = handlers.filter { $0.key.isAlive }         \/\/ \u0421\u043e\u0437\u0434\u0430\u0435\u043c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0441\u043e\u0431\u044b\u0442\u0438\u044f         handlers[key] = {             [weak subscriber] args in             \/\/ \u0417\u0430\u0445\u0432\u0430\u0442\u044b\u0432\u0430\u0435\u043c \u043f\u043e\u0434\u043f\u0438\u0441\u0447\u0438\u043a\u0430 \u0441\u043b\u0430\u0431\u043e\u0439 \u0441\u0441\u044b\u043b\u043a\u043e\u0439 \u0438 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a,             \/\/ \u0442\u043e\u043b\u044c\u043a\u043e \u0435\u0441\u043b\u0438 \u043f\u043e\u0434\u043f\u0438\u0441\u0447\u0438\u043a \u0436\u0438\u0432             guard let subscriber = subscriber else { return }             handler(subscriber, args)         }     }      func unsubscribe(_ subscriber: AnyObject) {         \/\/ \u041e\u0442\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u043c\u0441\u044f \u043e\u0442 \u0441\u043e\u0431\u044b\u0442\u0438\u044f, \u0443\u0434\u0430\u043b\u044f\u044f \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0439 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0438\u0437 \u0441\u043b\u043e\u0432\u0430\u0440\u044f         let key = Weak&lt;AnyObject&gt;(subscriber)         handlers[key] = nil     }      func raise(_ args: Args) {         \/\/ \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0441\u043f\u0438\u0441\u043e\u043a \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432 \u0441 \u0436\u0438\u0432\u044b\u043c\u0438 \u043f\u043e\u0434\u043f\u0438\u0441\u0447\u0438\u043a\u0430\u043c\u0438         let aliveHandlers = handlers.filter { $0.key.isAlive }         \/\/ \u0414\u043b\u044f \u0432\u0441\u0435\u0445 \u0436\u0438\u0432\u044b\u0445 \u043f\u043e\u0434\u043f\u0438\u0441\u0447\u0438\u043a\u043e\u0432 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u043a\u043e\u0434 \u0438\u0445 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432 \u0441\u043e\u0431\u044b\u0442\u0438\u0439         aliveHandlers.forEach { $0.value(args) }     } }<\/code><\/pre>\n<p>  <\/p>\n<p>\u042d\u0442\u043e\u0442 \u043a\u043e\u0434 \u043d\u0435 \u043e\u0447\u0435\u043d\u044c \u0441\u043b\u043e\u0436\u043d\u044b\u0439, \u043d\u043e, \u0447\u0442\u043e\u0431\u044b \u043e\u043d \u043d\u0435 \u043a\u0430\u0437\u0430\u043b\u0441\u044f \u0432\u0430\u043c \u0441\u043e\u0432\u0441\u0435\u043c \u0443\u0436 \u043f\u0440\u0438\u043c\u0438\u0442\u0438\u0432\u043d\u044b\u043c, \u044f \u043d\u0430\u043f\u0438\u0441\u0430\u043b \u043f\u043e\u0431\u043e\u043b\u044c\u0448\u0435 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0435\u0432. \u041a\u043b\u0430\u0441\u0441 <code>Weak&lt;T&gt;<\/code>, \u043a\u0430\u043a \u043e\u043a\u0430\u0437\u0430\u043b\u043e\u0441\u044c, \u043d\u0443\u0436\u0435\u043d \u0431\u044b\u043b \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0432\u0441\u0435\u0445 \u043f\u043e\u0434\u043f\u0438\u0441\u0447\u0438\u043a\u043e\u0432 \u0432 \u0441\u043b\u043e\u0432\u0430\u0440\u0435 \u0438 \u0434\u0430\u0442\u044c \u0438\u043c \u0441\u043f\u043e\u043a\u043e\u0439\u043d\u043e \u0443\u043c\u0435\u0440\u0435\u0442\u044c, \u0435\u0441\u043b\u0438 \u043e\u043d\u0438 \u0442\u043e\u0433\u043e \u0436\u0435\u043b\u0430\u044e\u0442\u00a0\u2014 \u043d\u0435 \u0434\u0435\u0440\u0436\u0430\u0442\u044c \u0438\u0445 \u0441\u0438\u043b\u044c\u043d\u043e\u0439 \u0441\u0441\u044b\u043b\u043a\u043e\u0439. <\/p>\n<p>  <\/p>\n<p>\u041e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u043e\u0431\u043e\u0439 \u0437\u0430\u043c\u044b\u043a\u0430\u043d\u0438\u0435, \u0432 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043f\u043e\u043f\u0430\u0434\u0430\u0435\u0442 \u0436\u0438\u0432\u043e\u0439 \u043f\u043e\u0434\u043f\u0438\u0441\u0447\u0438\u043a \u0438 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435, \u0435\u0441\u043b\u0438 \u0442\u0430\u043a\u043e\u0432\u044b\u0435 \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u044b \u0434\u043b\u044f \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0441\u043e\u0431\u044b\u0442\u0438\u044f. \u041f\u043e\u043b\u0443\u0447\u0438\u0432\u0448\u0438\u0439\u0441\u044f \u043a\u043b\u0430\u0441\u0441 <code>Event&lt;Args&gt;<\/code> \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u043e\u0434\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u043d\u0430 \u0441\u043e\u0431\u044b\u0442\u0438\u0435 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043c\u0435\u0442\u043e\u0434\u0430 <code>subscribe(_:handler:)<\/code> \u0438 \u043e\u0442\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u043e\u0442 \u043d\u0435\u0433\u043e \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043c\u0435\u0442\u043e\u0434\u0430 <code>unsubscribe(_:)<\/code>. \u041a\u043e\u0433\u0434\u0430 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a \u0441\u043e\u0431\u044b\u0442\u0438\u044f (\u0432 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u044d\u0442\u043e \u0432\u044c\u044e-\u043c\u043e\u0434\u0435\u043b\u044c) \u0437\u0430\u0445\u043e\u0447\u0435\u0442 \u0443\u0432\u0435\u0434\u043e\u043c\u0438\u0442\u044c \u043e \u0447\u0435\u043c-\u0442\u043e \u0441\u0432\u043e\u044e \u0430\u0440\u043c\u0438\u044e \u043f\u043e\u0434\u043f\u0438\u0441\u0447\u0438\u043a\u043e\u0432, \u0435\u043c\u0443 \u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043c\u0435\u0442\u043e\u0434\u043e\u043c <code>raise(_:)<\/code>.<\/p>\n<p>  <\/p>\n<p>\u0414\u043b\u044f \u0443\u0434\u043e\u0431\u0441\u0442\u0432\u0430 \u043c\u043e\u0436\u043d\u043e \u043e\u0431\u043c\u0430\u0437\u0430\u0442\u044c\u0441\u044f \u044d\u043a\u0441\u0442\u0435\u043d\u0448\u0435\u043d\u043e\u043c, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043e\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b \u0442\u0438\u043f\u0430 <code>Void<\/code> \u043f\u0440\u0438 \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0435 \u043d\u0430 \u0441\u043e\u0431\u044b\u0442\u0438\u0435 \u0438 \u043f\u0440\u0438 \u0435\u0433\u043e \u0432\u044b\u0437\u043e\u0432\u0435:<\/p>\n<p>  <\/p>\n<pre><code class=\"swift\">extension Event where Args == Void {     func subscribe&lt;Subscriber: AnyObject&gt;(         _ subscriber: Subscriber,         handler: @escaping (Subscriber) -&gt; Void) {          subscribe(subscriber) { this, _ in             handler(this)         }     }      func raise() {         raise(())     } }<\/code><\/pre>\n<p>  <\/p>\n<p>\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0441\u043e\u0431\u044b\u0442\u0438\u044f\u043c\u0438 \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u0442\u0430\u043a. \u041d\u0430 \u0441\u0442\u043e\u0440\u043e\u043d\u0435 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0430 \u0441\u043e\u0431\u044b\u0442\u0438\u0439 \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u043e\u0431\u044a\u0435\u043a\u0442 \u0441\u043e\u0431\u044b\u0442\u0438\u044f, \u043f\u043e\u0441\u043b\u0435 \u0447\u0435\u0433\u043e \u0432 \u043a\u0430\u043a\u043e\u0439-\u0442\u043e \u043c\u043e\u043c\u0435\u043d\u0442 \u0441\u0442\u0440\u0435\u043b\u044f\u0435\u043c \u043d\u043e\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0435\u0439:<\/p>\n<p>  <\/p>\n<pre><code class=\"swift\">let event = Event&lt;Void&gt;() event.raise() \/\/ \u041a\u0430\u043a\u043e\u0439-\u0442\u043e \u043c\u043e\u043c\u0435\u043d\u0442 \u043d\u0430\u0441\u0442\u0443\u043f\u0438\u043b, \u0441\u0442\u0440\u0435\u043b\u044f\u0435\u043c<\/code><\/pre>\n<p>  <\/p>\n<p>\u041d\u0430 \u0441\u0442\u043e\u0440\u043e\u043d\u0435 \u043f\u043e\u0434\u043f\u0438\u0441\u0447\u0438\u043a\u0430 \u043f\u043e\u0434\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u043c\u0441\u044f \u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u043f\u043e\u043b\u0435\u0437\u043d\u0443\u044e \u0440\u0430\u0431\u043e\u0442\u0443 \u0432 \u0437\u0430\u043c\u044b\u043a\u0430\u043d\u0438\u0438. \u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435, \u0447\u0442\u043e \u0432 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430 \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u043f\u043e\u0441\u0442\u0443\u043f\u0430\u0435\u0442 \u0436\u0438\u0432\u043e\u0439 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \u043f\u043e\u0434\u043f\u0438\u0441\u0447\u0438\u043a\u0430, \u0447\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043d\u0435 \u043f\u0438\u0441\u0430\u0442\u044c <code>weak self<\/code>, \u0435\u0441\u043b\u0438 \u043d\u0430\u043c \u043d\u0443\u0436\u0435\u043d \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u043f\u043e\u0434\u043f\u0438\u0441\u0447\u0438\u043a\u0443 \u0432\u043d\u0443\u0442\u0440\u0438 \u0437\u0430\u043c\u044b\u043a\u0430\u043d\u0438\u044f:<\/p>\n<p>  <\/p>\n<pre><code class=\"swift\">event.subscribe(self) { this in     this.foo() \/\/ \u0422\u0443\u0442 \u043f\u043e\u043b\u0435\u0437\u043d\u0430\u044f \u0440\u0430\u0431\u043e\u0442\u0430 }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0415\u0441\u043b\u0438 \u043f\u043e\u0434\u043f\u0438\u0441\u0447\u0438\u043a \u0431\u043e\u043b\u0435\u0435 \u043d\u0435 \u0437\u0430\u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043e\u0432\u0430\u043d \u0432 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0438 \u0441\u043e\u0431\u044b\u0442\u0438\u0439, \u043e\u043d \u0434\u0435\u043b\u0430\u0435\u0442 \u0432\u043e\u0442 \u0442\u0430\u043a:<\/p>\n<p>  <\/p>\n<pre><code class=\"swift\">event.unsubscribe(self) \/\/ \u041d\u0430\u043c \u043b\u0443\u0447\u0448\u0435 \u0440\u0430\u0441\u0441\u0442\u0430\u0442\u044c\u0441\u044f<\/code><\/pre>\n<p>  <\/p>\n<p>\u0423\u0440\u0430! \u0412\u044b \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u043b\u0438 \u043f\u043e\u0447\u0442\u0438 \u0432\u0441\u044e \u0441\u0442\u0430\u0442\u044c\u044e, \u043e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u0441\u043e\u0432\u0441\u0435\u043c \u043d\u0435\u043c\u043d\u043e\u0433\u043e. \u0427\u0442\u043e\u0431\u044b \u043f\u0435\u0440\u0435\u0434\u043e\u0445\u043d\u0443\u0442\u044c, \u043e\u0442\u0432\u043b\u0435\u043a\u0438\u0442\u0435\u0441\u044c \u043d\u0430 \u043c\u0438\u043d\u0443\u0442\u043a\u0443 \u0438 \u043f\u043e\u0434\u0443\u043c\u0430\u0439\u0442\u0435 \u043e \u0442\u043e\u043c, \u043d\u0430\u0441\u043a\u043e\u043b\u044c\u043a\u043e MVVM \u043f\u0440\u0435\u043a\u0440\u0430\u0441\u0435\u043d. \u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u0440\u0430\u0437\u0434\u0435\u043b \u043f\u043e\u0447\u0442\u0438 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0439.<\/p>\n<p>  <\/p>\n<h2 id=\"1.8\">\u041e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0441\u043f\u0438\u0441\u043a\u0430 \u0437\u0430\u043a\u0430\u0437\u043e\u0432<\/h2>\n<p>  <\/p>\n<p>\u0427\u0442\u043e\u0431\u044b \u043d\u0430\u0443\u0447\u0438\u0442\u044c <code>OrdersVM<\/code> \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u044f\u0442\u044c <code>OrdersVC<\/code> \u043e\u0431 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0438 \u0441\u043f\u0438\u0441\u043a\u0430 \u0437\u0430\u043a\u0430\u0437\u043e\u0432, \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0432\u043e \u0432\u044c\u044e-\u043c\u043e\u0434\u0435\u043b\u044c \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0435\u0435 \u0441\u043e\u0431\u044b\u0442\u0438\u0435. \u041e\u0434\u043d\u0430\u043a\u043e, \u0441\u043e\u0433\u043b\u0430\u0441\u0438\u0442\u0435\u0441\u044c, \u043d\u0435 \u0445\u043e\u0447\u0435\u0442\u0441\u044f \u0432 \u043a\u0430\u0436\u0434\u043e\u0439 \u0432\u044c\u044e-\u043c\u043e\u0434\u0435\u043b\u0438, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0434\u043e\u043b\u0436\u043d\u0430 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u044f\u0442\u044c \u043e \u0441\u0432\u043e\u0438\u0445 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f\u0445, \u0441\u043d\u043e\u0432\u0430 \u0438 \u0441\u043d\u043e\u0432\u0430 \u043f\u0438\u0441\u0430\u0442\u044c \u043a\u043e\u0434 \u043f\u043e \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044e \u0441\u043e\u0431\u044b\u0442\u0438\u044f. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u043c\u044b \u043f\u043e\u0439\u0434\u0435\u043c \u0443\u0436\u0435 \u0437\u043d\u0430\u043a\u043e\u043c\u044b\u043c \u043f\u0443\u0442\u0435\u043c \u0438 \u043e\u0431\u0440\u0430\u0442\u0438\u043c\u0441\u044f \u0437\u0430 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043a \u0437\u0430\u043f\u0440\u0435\u0442\u043d\u044b\u043c \u0442\u0435\u0445\u043d\u0438\u043a\u0430\u043c Objective-C-\u0440\u0430\u043d\u0442\u0430\u0439\u043c\u0430, \u043a\u043b\u044f\u0442\u0432\u0435\u043d\u043d\u043e \u043f\u043e\u043e\u0431\u0435\u0449\u0430\u0432 \u0441\u0435\u0431\u0435 \u0431\u043e\u043b\u044c\u0448\u0435 \u043d\u0438\u043a\u043e\u0433\u0434\u0430 \u0442\u0430\u043a \u043d\u0435 \u0434\u0435\u043b\u0430\u0442\u044c:<\/p>\n<p>  <\/p>\n<pre><code class=\"swift\">private var changedEventKey: UInt8 = 0  protocol INotifyOnChanged {     var changed: Event&lt;Void&gt; { get } }  extension INotifyOnChanged {     var changed: Event&lt;Void&gt; {         get {             if let event = objc_getAssociatedObject(self,                  &amp;changedEventKey) as? Event&lt;Void&gt; {                 return event             } else {                 let event = Event&lt;Void&gt;()                 objc_setAssociatedObject(self,                      &amp;changedEventKey,                      event,                      .OBJC_ASSOCIATION_RETAIN_NONATOMIC)                 return event             }         }     } }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0421 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0430 <code>INotifyOnChanged<\/code> \u0438 \u0435\u0433\u043e \u0434\u0435\u0444\u043e\u043b\u0442\u043d\u043e\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043b\u044e\u0431\u0430\u044f \u0432\u044c\u044e-\u043c\u043e\u0434\u0435\u043b\u044c \u0441\u043c\u043e\u0436\u0435\u0442 \u0431\u0435\u0441\u043f\u043b\u0430\u0442\u043d\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0441\u043e\u0431\u044b\u0442\u0438\u0435 <code>changed<\/code>. \u0421 \u043f\u043e\u044f\u0432\u043b\u0435\u043d\u0438\u0435\u043c <code>INotifyOnChanged<\/code> \u0434\u0435\u0444\u043e\u043b\u0442\u043d\u0430\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0430 <code>IHaveViewModel<\/code> \u0432\u044b\u043d\u0443\u0436\u0434\u0435\u043d\u0430 \u0431\u0443\u0434\u0435\u0442 \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u044d\u0432\u043e\u043b\u044e\u0446\u0438\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u0442\u044c: \u0432 \u043d\u0435\u0439 \u043c\u044b \u0437\u0430\u0445\u043e\u0442\u0438\u043c \u043f\u043e\u0434\u043f\u0438\u0441\u0430\u0442\u044c\u0441\u044f \u043d\u0430 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u0432\u044c\u044e-\u043c\u043e\u0434\u0435\u043b\u0438 \u0438 \u0432\u044b\u0437\u0432\u0430\u0442\u044c <code>viewModelChanged(_:)<\/code> \u0432 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0435 \u0441\u043e\u0431\u044b\u0442\u0438\u044f:<\/p>\n<p>  <\/p>\n<pre><code class=\"swift\">extension IHaveViewModel {     var anyViewModel: Any? {         get {             return objc_getAssociatedObject(self, &amp;viewModelKey)         }         set {             (anyViewModel as? INotifyOnChanged)?.changed.unsubscribe(self)             let viewModel = newValue as? ViewModel              objc_setAssociatedObject(self,                  &amp;viewModelKey,                  viewModel,                  .OBJC_ASSOCIATION_RETAIN_NONATOMIC)              if let viewModel = viewModel {                 viewModelChanged(viewModel)             }              (viewModel as? INotifyOnChanged)?.changed.subscribe(self) { this in                 if let viewModel = viewModel {                     this.viewModelChanged(viewModel)                 }             }         }     } }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0418, \u043d\u0430\u043a\u043e\u043d\u0435\u0446, \u0444\u0438\u043d\u0430\u043b\u044c\u043d\u044b\u0439 \u0448\u0442\u0440\u0438\u0445:<\/p>\n<p>  <\/p>\n<pre><code class=\"swift\">final class OrdersVM: INotifyOnChanged {     var orders: [OrderVM] = []      private var ordersProvider: OrdersProvider      init(ordersProvider: OrdersProvider) {         self.ordersProvider = ordersProvider     }      func loadOrders() {         ordersProvider.loadOrders() { [weak self] model in             self?.orders = model.map { OrderVM(name: $0.name) }             self?.changed.raise() \/\/ \u041f\u044b\u0449!         }     } }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0412\u0441\u0435, \u0447\u0442\u043e \u043c\u044b \u0434\u0435\u043b\u0430\u043b\u0438 \u0432\u044b\u0448\u0435\u00a0\u2014 \u043a\u043b\u0430\u0441\u0441 <code>Weak&lt;T&gt;<\/code>, \u043a\u043b\u0430\u0441\u0441 <code>Event&lt;Args&gt;<\/code>, \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b <code>INotifyOnChanged<\/code> \u0438 \u0435\u0433\u043e \u0434\u0435\u0444\u043e\u043b\u0442\u043d\u0430\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f,\u00a0\u2014 \u0431\u044b\u043b\u043e \u043d\u0443\u0436\u043d\u043e \u0440\u0430\u0434\u0438 \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u043c\u044b \u0441\u043c\u043e\u0433\u043b\u0438 \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u043e\u0434\u043d\u0443 \u0435\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u0443\u044e \u0441\u0442\u0440\u043e\u0447\u043a\u0443 \u043a\u043e\u0434\u0430 \u0432\u043e \u0432\u044c\u044e-\u043c\u043e\u0434\u0435\u043b\u0438: <code>changed.raise()<\/code>. <\/p>\n<p>  <\/p>\n<p>\u0412\u044b\u0437\u043e\u0432 <code>rise()<\/code>, \u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u043d\u044b\u0439 \u0432 \u043f\u043e\u0434\u0445\u043e\u0434\u044f\u0449\u0438\u0439 \u043c\u043e\u043c\u0435\u043d\u0442, \u043f\u043e\u0441\u043b\u0435 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0432\u0441\u0435\u0445 \u0434\u0430\u043d\u043d\u044b\u0445, \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u0442 \u043a \u0442\u043e\u043c\u0443, \u0447\u0442\u043e \u0432 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0435 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043c\u0435\u0442\u043e\u0434 <code>viewModelChanged(_:)<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u0442 \u0442\u0430\u0431\u043b\u0438\u0446\u0443, \u0438 \u043e\u043d\u0430 \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u0442 \u0441\u043f\u0438\u0441\u043e\u043a \u0437\u0430\u043a\u0430\u0437\u043e\u0432.<\/p>\n<p>  <\/p>\n<h2 id=\"1.9\">One More Thing: \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0430 \u043d\u0430 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0445 \u0441\u0432\u043e\u0439\u0441\u0442\u0432 \u043c\u043e\u0434\u0435\u043b\u0438 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0447\u0435\u0440\u0435\u0437 \u043e\u0431\u0435\u0440\u0442\u043a\u0438 \u0441\u0432\u043e\u0439\u0441\u0442\u0432<\/h2>\n<p>  <\/p>\n<p>\u041f\u0440\u043e\u0442\u043e\u043a\u043e\u043b <code>INotifyOnChanged<\/code> \u0438 \u0441\u043e\u0431\u044b\u0442\u0438\u0435 <code>changed<\/code> \u043d\u0435\u043f\u043b\u043e\u0445\u043e \u0441\u043f\u0440\u0430\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u0441 \u0437\u0430\u0434\u0430\u0447\u0435\u0439 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f \u043e\u0431 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0438 <em>\u0432\u0441\u0435\u0439<\/em> \u0432\u044c\u044e-\u043c\u043e\u0434\u0435\u043b\u0438 \u0441 \u043f\u043e\u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0439 \u043f\u0435\u0440\u0435\u0440\u0438\u0441\u043e\u0432\u043a\u043e\u0439 <em>\u0432\u0441\u0435\u0439<\/em> \u0432\u044c\u044e\u0445\u0438. \u0412 \u0431\u043e\u043b\u044c\u0448\u0438\u043d\u0441\u0442\u0432\u0435 \u0441\u043b\u0443\u0447\u0430\u0435\u0432 \u044d\u0442\u043e\u0433\u043e \u0432\u043f\u043e\u043b\u043d\u0435 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e, \u043d\u043e \u0447\u0442\u043e, \u0435\u0441\u043b\u0438 \u043c\u044b \u0445\u043e\u0442\u0438\u043c\u00a0\u2014 \u0438\u0437 \u0441\u043e\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0439 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u0438\u043b\u0438, \u0447\u0442\u043e \u0431\u043e\u043b\u0435\u0435 \u0432\u0430\u0436\u043d\u043e, \u0440\u0430\u0434\u0438 \u0440\u0430\u0437\u0432\u043b\u0435\u0447\u0435\u043d\u0438\u044f\u00a0\u2014 \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u0430\u0442\u044c View \u043e\u0431 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0438 \u043a\u0430\u043a\u043e\u0433\u043e-\u0442\u043e \u043e\u0434\u043d\u043e\u0433\u043e \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 ViewModel? \u041e\u0447\u0435\u0432\u0438\u0434\u043d\u043e, \u0447\u0442\u043e \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0434\u043b\u044f \u044d\u0442\u0438\u0445 \u0446\u0435\u043b\u0435\u0439 \u0437\u0430\u0432\u0435\u0441\u0442\u0438 \u0432\u043e \u0432\u044c\u044e-\u043c\u043e\u0434\u0435\u043b\u0438 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0435 \u0441\u043e\u0431\u044b\u0442\u0438\u0435 <code>myPropertyChanged<\/code>, \u043f\u043e\u0434\u043f\u0438\u0441\u0430\u0442\u044c\u0441\u044f \u043d\u0430 \u043d\u0435\u0433\u043e \u043d\u0430 \u0441\u0442\u043e\u0440\u043e\u043d\u0435 \u0432\u044c\u044e\u0445\u0438\u00a0\u2014 \u0438 \u0434\u0435\u043b\u043e \u0441\u0434\u0435\u043b\u0430\u043d\u043e. <\/p>\n<p>  <\/p>\n<p>\u041d\u043e \u0437\u0430\u0447\u0435\u043c \u0441\u0430\u043c\u0438\u043c \u043f\u0438\u0441\u0430\u0442\u044c \u043a\u043e\u0434, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0437\u0430 \u043d\u0430\u0441 \u043c\u043e\u0433\u0443\u0442 \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438\u043d\u0436\u0435\u043d\u0435\u0440\u044b Apple?<\/p>\n<p>  <\/p>\n<p>\u0412 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0439 <a href=\"https:\/\/habr.com\/ru\/company\/tinkoff\/blog\/508452\/\">\u0441\u0442\u0430\u0442\u044c\u0435<\/a> \u044f \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u044b\u0432\u0430\u043b \u043f\u0440\u043e \u043e\u0431\u0435\u0440\u0442\u043a\u0438 \u0441\u0432\u043e\u0439\u0441\u0442\u0432, \u0438 \u0432\u044b \u043c\u043e\u0433\u043b\u0438 \u0443\u0431\u0435\u0434\u0438\u0442\u044c\u0441\u044f, \u0447\u0442\u043e \u044d\u0442\u043e \u0432\u0435\u0441\u044c\u043c\u0430 \u0441\u0432\u043e\u0435\u043e\u0431\u0440\u0430\u0437\u043d\u0430\u044f, \u043d\u043e \u0437\u0430\u043d\u0438\u043c\u0430\u0442\u0435\u043b\u044c\u043d\u0430\u044f \u0448\u0442\u0443\u043a\u043e\u0432\u0438\u043d\u0430, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043d\u0430\u0434\u0435\u043b\u0438\u0442\u044c \u043d\u0438\u0447\u0435\u043c \u043d\u0435 \u043f\u0440\u0438\u043c\u0435\u0447\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 \u0440\u0430\u0437\u043d\u044b\u043c\u0438 \u0441\u0443\u043f\u0435\u0440\u0441\u043f\u043e\u0441\u043e\u0431\u043d\u043e\u0441\u0442\u044f\u043c\u0438. <\/p>\n<p>  <\/p>\n<p>\u0427\u0442\u043e\u0431\u044b \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0441\u0432\u043e\u0439 property wrapper, \u043d\u0443\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043a\u043b\u0430\u0441\u0441 \u0438\u043b\u0438 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443, \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e <code>wrappedValue<\/code> \u0438 \u0443\u043a\u0440\u0430\u0441\u0438\u0442\u044c \u0432\u0441\u0435 \u044d\u0442\u043e \u0434\u0435\u043b\u043e, \u043a\u0430\u043a \u0432\u0438\u0448\u0435\u043d\u043a\u043e\u0439 \u043d\u0430 \u0442\u043e\u0440\u0442\u0435, \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u043e\u043c <code>@propertyWrapper<\/code>. \u041e\u0434\u043d\u0430\u043a\u043e \u043e\u0431\u0435\u0440\u0442\u043a\u0438 \u0441\u0432\u043e\u0439\u0441\u0442\u0432 \u043d\u0435 \u0442\u0430\u043a \u043f\u0440\u043e\u0441\u0442\u044b \u0438 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0442 \u043c\u0430\u043d\u0438\u043f\u0443\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0441\u0430\u043c\u0438\u043c \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e\u043c, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043e\u043d\u0438 \u043e\u0431\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u044e\u0442, \u043d\u043e \u0438 \u0435\u0433\u043e \u00ab\u043f\u0440\u043e\u0435\u043a\u0446\u0438\u0435\u0439\u00bb \u0447\u0435\u0440\u0435\u0437 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0435 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e <code>projectedValue<\/code>. \u0421\u043e\u0433\u043b\u0430\u0441\u0438\u0442\u0435\u0441\u044c, \u0437\u0432\u0443\u0447\u0438\u0442 \u043e\u0447\u0435\u043d\u044c \u043d\u0435\u043f\u043e\u043d\u044f\u0442\u043d\u043e, \u043f\u043e\u044d\u0442\u043e\u043c\u0443, \u0447\u0442\u043e\u0431\u044b \u0435\u0449\u0435 \u0431\u043e\u043b\u044c\u0448\u0435 \u0432\u0430\u0441 \u0437\u0430\u043f\u0443\u0442\u0430\u0442\u044c, \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0442\u0430\u043a\u043e\u0439 \u043a\u043e\u0434:<\/p>\n<p>  <\/p>\n<pre><code class=\"swift\">@propertyWrapper struct Observable&lt;T&gt; {     let projectedValue = Event&lt;T&gt;()      init(wrappedValue: T) {         self.wrappedValue = wrappedValue     }      var wrappedValue: T {         didSet {             projectedValue.raise(wrappedValue)         }     } }<\/code><\/pre>\n<p>  <\/p>\n<p>\u041c\u044b \u0442\u043e\u043b\u044c\u043a\u043e \u0447\u0442\u043e \u0441\u043e\u0437\u0434\u0430\u043b\u0438 \u043e\u0431\u0435\u0440\u0442\u043a\u0443 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 \u0438 \u043d\u0430\u0437\u0432\u0430\u043b\u0438 \u0435\u0435 <code>Observable<\/code>. \u041e\u043d\u0430 \u0443\u043c\u0435\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441\u043e \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430\u043c\u0438 \u043b\u044e\u0431\u044b\u0445 \u0442\u0438\u043f\u043e\u0432 \u0438 \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u0445\u0432\u0430\u0441\u0442\u0430\u0442\u044c\u0441\u044f \u043d\u0430\u043b\u0438\u0447\u0438\u0435\u043c <code>projectedValue<\/code>. \u041f\u0440\u043e\u0435\u043a\u0446\u0438\u044f \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0441\u043e\u0431\u044b\u0442\u0438\u0435\u043c, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043e\u0431\u0443\u0447\u0435\u043d\u043e \u0441\u043e\u043e\u0431\u0449\u0430\u0442\u044c \u0441\u0432\u043e\u0438\u043c \u043f\u043e\u0434\u043f\u0438\u0441\u0447\u0438\u043a\u0430\u043c \u043e \u043b\u044e\u0431\u044b\u0445 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f\u0445 <code>wrappedValue<\/code>. \u042d\u0442\u043e \u0441\u043e\u0431\u044b\u0442\u0438\u0435, \u043a\u0430\u043a \u0432\u0438\u0434\u043d\u043e \u0438\u0437 \u043a\u043e\u0434\u0430, \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u043f\u043e \u0441\u0432\u043e\u0435\u043c\u0443 \u043f\u0440\u044f\u043c\u043e\u043c\u0443 \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044e \u0432 <code>didSet<\/code>.<\/p>\n<p>  <\/p>\n<p>\u0418\u043c\u0435\u044f \u0432 \u0441\u0432\u043e\u0435\u043c \u0430\u0440\u0441\u0435\u043d\u0430\u043b\u0435 \u043e\u0431\u0435\u0440\u0442\u043a\u0443 <code>Observable&lt;T&gt;<\/code>, \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043f\u0440\u0438\u043c\u0435\u043d\u0438\u0442\u044c \u0435\u0435 \u043a \u0441\u043f\u0438\u0441\u043a\u0443 \u0437\u0430\u043a\u0430\u0437\u043e\u0432:<\/p>\n<p>  <\/p>\n<pre><code class=\"swift\">@Observable var orders: [OrderVM] = []<\/code><\/pre>\n<p>  <\/p>\n<p>\u042d\u0442\u043e \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u0442 \u043a \u0442\u043e\u043c\u0443, \u0447\u0442\u043e \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440 \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442 \u0437\u0430 \u043d\u0430\u0441 \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u0442\u0430\u043a\u043e\u0439 \u043a\u043e\u0434:<\/p>\n<p>  <\/p>\n<pre><code class=\"swift\">private var _orders = Observable&lt;[OrderVM]&gt;(wrappedValue: [])  var orders: [OrderVM] {   get { _orders.wrappedValue }   set { _orders.wrappedValue = newValue } }  var $orders: Event&lt;[OrderVM]&gt; {   get { _orders.projectedValue } }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0412\u0438\u0434\u043d\u043e, \u0447\u0442\u043e, \u043f\u043e\u043c\u0438\u043c\u043e \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 <code>orders<\/code>, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0447\u0435\u0440\u0435\u0437 \u043e\u0431\u0435\u0440\u0442\u043a\u0443 \u043f\u0440\u043e\u0441\u0442\u043e \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 <code>wrappedValue<\/code>, \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440 \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043b \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0435 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e <code>$orders<\/code>, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043d\u0430\u043c <code>projectedValue<\/code>. \u0412 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 <code>projectedValue<\/code>\u00a0\u2014 \u044d\u0442\u043e \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \u0441\u043e\u0431\u044b\u0442\u0438\u044f, \u0447\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043d\u0430 \u0441\u0442\u043e\u0440\u043e\u043d\u0435 \u0432\u044c\u044e\u0445\u0438 \u043f\u043e\u0434\u043f\u0438\u0441\u0430\u0442\u044c\u0441\u044f \u043d\u0430 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 <code>orders<\/code> \u0432\u043e\u0442 \u0442\u0430\u043a\u0438\u043c \u043d\u0435\u0445\u0438\u0442\u0440\u044b\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<\/p>\n<p>  <\/p>\n<pre><code class=\"swift\">viewModel.$orders.subscribe(self) { this, orders in     this.update(with: orders) }<\/code><\/pre>\n<p>  <\/p>\n<p>\u041f\u043e\u0437\u0434\u0440\u0430\u0432\u043b\u044f\u044e! \u0412\u044b \u0442\u043e\u043b\u044c\u043a\u043e \u0447\u0442\u043e \u0432 15 \u0441\u0442\u0440\u043e\u0447\u043a\u0430\u0445 \u043a\u043e\u0434\u0430 \u043d\u0430\u043f\u0438\u0441\u0430\u043b\u0438 \u0441\u0432\u043e\u0439 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 \u0430\u043d\u0430\u043b\u043e\u0433 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u0430 <a href=\"https:\/\/developer.apple.com\/documentation\/combine\/published\">Published<\/a> \u0438\u0437 \u0444\u0440\u044d\u0439\u043c\u0432\u043e\u0440\u043a\u0430 Combine \u043e\u0442 Apple, \u0430 \u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0447\u0442\u043e \u0434\u043e\u043f\u0438\u0441\u0430\u043b \u043e\u0447\u0435\u0440\u0435\u0434\u043d\u0443\u044e \u0441\u0442\u0430\u0442\u044c\u044e.<\/p>\n<p>  <\/p>\n<h2 id=\"1.10\">\u0417\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435<\/h2>\n<p>  <\/p>\n<p>\u0421\u0435\u0433\u043e\u0434\u043d\u044f \u043c\u044b \u0432\u0435\u0440\u043e\u043b\u043e\u043c\u043d\u043e \u043f\u043e\u0441\u0442\u0443\u043f\u0438\u043b\u0438\u0441\u044c \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u043c \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u043e\u043c \u0440\u0430\u0431\u043e\u0442\u044b \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0439, \u0445\u0430\u043a\u043d\u0443\u0432 \u0438\u0445 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e Objective-C-\u0440\u0430\u043d\u0442\u0430\u0439\u043c\u0430. \u042d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u043b\u043e \u043d\u0430\u043c, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u044b \u0438 \u044d\u043a\u0441\u0442\u0435\u043d\u0448\u0435\u043d\u044b, \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u043f\u0430\u0442\u0442\u0435\u0440\u043d MVVM \u0432 \u043e\u0434\u043d\u043e\u043c \u043c\u0430\u043b\u0435\u043d\u044c\u043a\u043e\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438 \u043f\u043e\u0434 iOS. \u0412 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435 \u0443 \u043d\u0430\u0441 \u0432\u043e\u0437\u043d\u0438\u043a\u043b\u043e \u043d\u0435\u043f\u0440\u0435\u043e\u0434\u043e\u043b\u0438\u043c\u043e\u0435 \u0436\u0435\u043b\u0430\u043d\u0438\u0435 \u043f\u0440\u0438\u043c\u0435\u043d\u0438\u0442\u044c \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0439 \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a, \u0438 \u043c\u044b \u0435\u0434\u0432\u0430 \u0443\u0434\u0435\u0440\u0436\u0430\u043b\u0438\u0441\u044c, \u043d\u0430\u043f\u0438\u0441\u0430\u0432 \u0432\u043c\u0435\u0441\u0442\u043e \u044d\u0442\u043e\u0433\u043e \u0441\u0432\u043e\u044e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u0441\u043e\u0431\u044b\u0442\u0438\u0439, \u0432\u0434\u043e\u0445\u043d\u043e\u0432\u0438\u0432\u0448\u0438\u0441\u044c \u0434\u0440\u0443\u0436\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0439 \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0435\u0439 .NET. \u041f\u043e\u043f\u0443\u0442\u043d\u043e \u043f\u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u043b\u0438\u0441\u044c \u0441 \u043f\u0430\u0440\u043e\u0439 \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u0445 \u0442\u0435\u0445\u043d\u0438\u043a iOS-\u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438, \u0442\u0430\u043a\u0438\u0445 \u043a\u0430\u043a shadow type erasure \u0438 property wrappers \u0441 \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u0435\u043c projected value.<\/p>\n<p>  <\/p>\n<hr>\n<p>  <\/p>\n<p><em>\u0412\u0435\u0441\u044c \u043a\u043e\u0434 \u0438\u0437 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438 \u043c\u043e\u0436\u043d\u043e <a href=\"https:\/\/github.com\/volokhin\/Playgrounds\/tree\/master\/MVVM.playground\">\u0441\u043a\u0430\u0447\u0430\u0442\u044c<\/a> \u0432 \u0432\u0438\u0434\u0435 Swift Playground.<\/em><\/p>\n<\/div>\n<p> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/company\/tinkoff\/blog\/509014\/\"> https:\/\/habr.com\/ru\/company\/tinkoff\/blog\/509014\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"\n<div class=\"post__text post__text-html post__text_v1\" id=\"post-content-body\" data-io-article-url=\"https:\/\/habr.com\/ru\/company\/tinkoff\/blog\/509014\/\">\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/77\/sp\/gj\/77spgjvzw0oo-bnch77pf0usvoe.png\"><\/p>\n<p>  <\/p>\n<p>\u041c\u043d\u043e\u0433\u043e \u043b\u0435\u0442 \u043f\u043e\u0434\u0440\u044f\u0434 \u044f, \u043f\u043e\u043c\u0438\u043c\u043e \u0432\u0441\u0435\u0433\u043e \u043f\u0440\u043e\u0447\u0435\u0433\u043e, \u0437\u0430\u043d\u0438\u043c\u0430\u043b\u0441\u044f \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u043e\u0439 MVVM \u0432 \u0441\u0432\u043e\u0438\u0445 \u0440\u0430\u0431\u043e\u0447\u0438\u0445 \u0438 \u043d\u0435 \u043e\u0447\u0435\u043d\u044c \u0440\u0430\u0431\u043e\u0447\u0438\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u0430\u0445. \u042f \u0443\u0432\u043b\u0435\u0447\u0435\u043d\u043d\u043e \u0434\u0435\u043b\u0430\u043b \u044d\u0442\u043e \u0432 Windows-\u043f\u0440\u043e\u0435\u043a\u0442\u0430\u0445, \u0433\u0434\u0435 \u043f\u0430\u0442\u0442\u0435\u0440\u043d \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0440\u043e\u0434\u043d\u044b\u043c. \u0421 \u044d\u043d\u0442\u0443\u0437\u0438\u0430\u0437\u043c\u043e\u043c, \u0434\u043e\u0441\u0442\u043e\u0439\u043d\u044b\u043c \u043b\u0443\u0447\u0448\u0435\u0433\u043e \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u044f, \u044f \u0434\u0435\u043b\u0430\u043b \u044d\u0442\u043e \u0432 iOS-\u043f\u0440\u043e\u0435\u043a\u0442\u0430\u0445, \u0433\u0434\u0435 MVVM \u043f\u0440\u043e\u0441\u0442\u043e \u0442\u0430\u043a \u043d\u0435 \u043f\u0440\u0438\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044f.<\/p>\n<p>  <\/p>\n<p>\u0421\u043d\u0430\u0447\u0430\u043b\u0430 \u044f \u0434\u0435\u043b\u0430\u043b \u044d\u0442\u043e \u043e\u0434\u043d\u0438\u043c \u0441\u043f\u043e\u0441\u043e\u0431\u043e\u043c, \u043f\u043e\u0442\u043e\u043c \u043f\u043e\u043d\u0438\u043c\u0430\u043b, \u0447\u0442\u043e \u0442\u0430\u043a \u0434\u0435\u043b\u0430\u0442\u044c \u043d\u0435 \u043d\u0443\u0436\u043d\u043e, \u0438 \u0432 \u0434\u0440\u0443\u0433\u043e\u0439 \u0440\u0430\u0437 \u0434\u0435\u043b\u0430\u043b \u043a\u0430\u043a-\u0442\u043e \u0438\u043d\u0430\u0447\u0435 \u043b\u0438\u0448\u044c \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u0432 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u0440\u0430\u0437 \u0441\u043d\u043e\u0432\u0430 \u0432\u0441\u0435 \u043f\u0435\u0440\u0435\u0434\u0435\u043b\u0430\u0442\u044c.<\/p>\n<p>  <\/p>\n<p>\u0421\u043e\u0432\u0435\u0442\u0443\u044e \u0437\u0430\u043f\u0430\u0441\u0442\u0438\u0441\u044c \u043f\u043e\u043f\u043a\u043e\u0440\u043d\u043e\u043c \u0438 \u043a\u043e\u043a\u0430-\u043a\u043e\u043b\u043e\u0439\u00a0\u2014 \u044d\u0442\u043e \u0432\u0435\u0447\u0435\u0440\u043d\u0435\u0435 \u0448\u043e\u0443 \u043e \u0442\u043e\u043c, \u043a\u0430\u043a \u044f \u043d\u0438 \u0432 \u0447\u0435\u043c \u0441\u0435\u0431\u0435 \u043d\u0435 \u043e\u0442\u043a\u0430\u0437\u044b\u0432\u0430\u043b, \u0432 \u043e\u0447\u0435\u0440\u0435\u0434\u043d\u043e\u0439 \u0440\u0430\u0437 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044f MVVM \u0432 \u043e\u0434\u043d\u043e\u043c \u0438\u0437 \u0441\u0432\u043e\u0438\u0445 \u0434\u043e\u043c\u0430\u0448\u043d\u0438\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432. \u0421\u0435\u0433\u043e\u0434\u043d\u044f \u0432\u0442\u043e\u0440\u0430\u044f \u0441\u0435\u0440\u0438\u044f: \u043f\u0440\u043e \u0442\u043e, \u043a\u0430\u043a \u0438\u0437 MVC \u0441\u0434\u0435\u043b\u0430\u0442\u044c MVVM \u0438 \u043d\u0435 \u043d\u0430\u0441\u0442\u0443\u043f\u0438\u0442\u044c \u0432 \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u0449\u0438\u043d\u0443.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-306740","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/306740","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=306740"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/306740\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=306740"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=306740"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=306740"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}