{"id":385923,"date":"2024-06-29T06:24:39","date_gmt":"2024-06-29T06:24:39","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=385923"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=385923","title":{"rendered":"<span>\u041a\u0430\u043a \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u043d\u0430\u0442\u0438\u0432\u043d\u044b\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b \u0438 \u043c\u043e\u0434\u0443\u043b\u0438 \u0432 React Native \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e Swift<\/span>"},"content":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-1\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/k8\/gw\/hc\/k8gwhc1wyy6eywxi5lfa6c7ewb8.png\" data-src=\"https:\/\/habrastorage.org\/webt\/k8\/gw\/hc\/k8gwhc1wyy6eywxi5lfa6c7ewb8.png\"\/><\/p>\n<p>  <\/p>\n<p>\u041f\u0440\u0438\u0432\u0435\u0442! \u041c\u0435\u043d\u044f \u0437\u043e\u0432\u0443\u0442 \u0413\u0435\u043e\u0440\u0433\u0438\u0439 \u041c\u0438\u0448\u0438\u043d, \u044f \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u044b\u0439 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0432 \u0421\u0431\u0435\u0440\u041c\u0430\u0440\u043a\u0435\u0442\u0435. \u0425\u043e\u0447\u0443 \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u0430\u0442\u044c, \u043a\u0430\u043a \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c Swift \u0432 React Native-\u043f\u0440\u043e\u0435\u043a\u0442. \u0412 \u0440\u0430\u043c\u043a\u0430\u0445 \u0441\u0442\u0430\u0442\u044c\u0438 \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043f\u0440\u043e\u0441\u0442\u0435\u043d\u044c\u043a\u0438\u0439 \u043d\u0430\u0442\u0438\u0432\u043d\u044b\u0439 \u043c\u043e\u0434\u0443\u043b\u044c \u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442, \u043e\u0431\u0441\u0443\u0434\u0438\u043c layout \u0432 React Native-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438 \u0438 \u043f\u043e\u0433\u043e\u0432\u043e\u0440\u0438\u043c, \u0447\u0442\u043e \u0436\u0435 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0432 shadow thread.<\/p>\n<p>  <\/p>\n<p>\u042d\u0442\u043e \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u0430\u044f \u0432\u0435\u0440\u0441\u0438\u044f \u043c\u043e\u0435\u0433\u043e <a href=\"https:\/\/youtu.be\/LpgpJZzDMWk?t=300\">\u0432\u044b\u0441\u0442\u0443\u043f\u043b\u0435\u043d\u0438\u044f \u043d\u0430 Android Meetup | \u0421\u0431\u0435\u0440\u041c\u0430\u0440\u043a\u0435\u0442 Tech<\/a>.<\/p>\n<p><a name=\"habracut\"><\/a>  <\/p>\n<h1 id=\"kak-ispolzovat-swift-v-react-native-prilozhenii\">\u041a\u0430\u043a \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c Swift \u0432 React Native-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438<\/h1>\n<p>  <\/p>\n<p>\u0414\u043b\u044f \u0442\u043e\u0433\u043e \u0447\u0442\u043e\u0431\u044b Swift \u0437\u0430\u0440\u0430\u0431\u043e\u0442\u0430\u043b \u0432 React Native-\u043f\u0440\u043e\u0435\u043a\u0442\u0435, \u043d\u0443\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c bridge-\u0444\u0430\u0439\u043b. XCode \u043f\u0440\u0435\u0434\u043b\u043e\u0436\u0438\u0442 \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u044d\u0442\u043e \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u043f\u0435\u0440\u0432\u043e\u0433\u043e swift-\u0444\u0430\u0439\u043b\u0430.<\/p>\n<p>  <\/p>\n<p>\u041f\u0440\u0438 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u043a\u0430\u0436\u0434\u044b\u0439 \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u043c\u044b\u0439 \u0432 JavaScript \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u043f\u043e\u043c\u0435\u0447\u0435\u043d \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u043e\u043c <a href=\"https:\/\/habr.com\/ru\/users\/objc\/\" class=\"user_link\">objc<\/a>, \u0447\u0442\u043e\u0431\u044b \u0435\u0433\u043e \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0432 Objective C runtime.<\/p>\n<p>  <\/p>\n<h1 id=\"iz-chego-sostoit-nativnyy-modul\">\u0418\u0437 \u0447\u0435\u0433\u043e \u0441\u043e\u0441\u0442\u043e\u0438\u0442 \u043d\u0430\u0442\u0438\u0432\u043d\u044b\u0439 \u043c\u043e\u0434\u0443\u043b\u044c<\/h1>\n<p>  <\/p>\n<p>\u041d\u0430\u0442\u0438\u0432\u043d\u044b\u0439 \u043c\u043e\u0434\u0443\u043b\u044c \u0441\u043e\u0441\u0442\u043e\u0438\u0442 \u0438\u0437 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043d\u0430 Swift \u0438 \u0444\u0430\u0439\u043b\u0430 \u0438\u043c\u043f\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 \u043d\u0430 Objective-C. \u041d\u0430 Swift \u043f\u0438\u0448\u0435\u043c \u0432\u0441\u044e \u043b\u043e\u0433\u0438\u043a\u0443, \u0430 \u043d\u0430 Objective-C \u0435\u0451 \u0438\u043c\u043f\u043b\u0435\u043c\u0435\u043d\u0442\u0438\u0440\u0443\u0435\u043c \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043c\u0430\u043a\u0440\u043e\u0441\u043e\u0432 \u0438\u0437 React Native, \u0447\u0442\u043e\u0431\u044b \u043e\u043d\u0430 \u043f\u043e\u0434\u0445\u0432\u0430\u0442\u0438\u043b\u0430\u0441\u044c \u0432 JS.<\/p>\n<p>  <\/p>\n<pre><code class=\"objectivec\">import Foundation import React  @objc(SimpleModule) class SimpleModule: NSObject (   @objc var bridge: RCTBridge!    @objc func log() {     print(\"Called from native\")   }    @objc static func requiresMainQueueSetup() -> Bool {     return false   } }<\/code><\/pre>\n<p>  <\/p>\n<pre><code class=\"objectivec\">#import &lt;Foundation\/Foundation.h> #import &lt;React\/RCTBridgeModule.h>  @interface RCT_EXTERN_MODULE(SimpleModule, NSObject)   RCT_EXTERN_METHOD(log) @end<\/code><\/pre>\n<p>  <\/p>\n<p><em>\u041f\u0440\u043e\u0441\u0442\u043e\u0439 \u043f\u0440\u0438\u043c\u0435\u0440 \u043d\u0430\u0442\u0438\u0432\u043d\u043e\u0433\u043e \u043c\u043e\u0434\u0443\u043b\u044f<\/em><\/p>\n<p>  <\/p>\n<p>\u041a\u0430\u0436\u0434\u044b\u0439 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u043f\u043e\u043c\u0435\u0447\u0435\u043d \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u043e\u043c <a href=\"https:\/\/habr.com\/ru\/users\/objc\/\" class=\"user_link\">objc<\/a>. \u042d\u0442\u043e \u043a\u043b\u0430\u0441\u0441, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u043e\u043c \u043c\u043e\u0434\u0443\u043b\u044f \u0438 \u043c\u0435\u0442\u043e\u0434, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u043e\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c \u0438\u0437 JS. \u0412 \u0444\u0430\u0439\u043b\u0435 \u0438\u043c\u043f\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c, \u043a\u0430\u043a\u043e\u0439 \u043c\u043e\u0434\u0443\u043b\u044c \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u043c, \u043e\u0442 \u043a\u0430\u043a\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430 \u043d\u0430\u0441\u043b\u0435\u0434\u0443\u0435\u0442\u0441\u044f \u0438 \u0447\u0442\u043e \u043e\u043d \u0431\u0443\u0434\u0435\u0442 \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c.<\/p>\n<p>  <\/p>\n<p>\u041c\u043e\u0436\u043d\u043e \u043e\u0431\u0440\u0430\u0442\u0438\u0442\u044c \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0430 \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u043c\u0435\u0442\u043e\u0434 requiresMainQueueSetup. \u041e\u043d \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0431\u0443\u043b\u0435\u0432\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u0446\u0438\u0440\u0443\u0435\u0442, \u0433\u0434\u0435 \u0434\u043e\u043b\u0436\u0435\u043d \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043c\u0435\u0442\u043e\u0434. \u0415\u0441\u043b\u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f \u00abtrue\u00bb, \u043c\u0435\u0442\u043e\u0434 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0434\u043e JavaScript, \u0435\u0441\u043b\u0438 \u00abfalse\u00bb \u2014 \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u0438\u043b\u0438 \u043f\u043e\u0441\u043b\u0435.<\/p>\n<p>  <\/p>\n<p><a href=\"https:\/\/reactnative.dev\/docs\/native-modules-ios#exporting-swift\">\u0414\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f \u0433\u043e\u0432\u043e\u0440\u0438\u0442<\/a>, \u0447\u0442\u043e, \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u044f \u043c\u0435\u0442\u043e\u0434 constantsToExport (\u0434\u043b\u044f \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u043a\u0430\u043a\u0438\u0445-\u043b\u0438\u0431\u043e \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442 \u0438\u0437 React Native \u0432 JS), \u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u0442\u0430\u043a\u0436\u0435 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c requiresMainQueueSetup. \u041d\u0443\u0436\u043d\u043e \u0432\u0435\u0440\u043d\u0443\u0442\u044c \u00abtrue\u00bb, \u0442\u0430\u043a \u043a\u0430\u043a \u0432\u0430\u0448\u0438 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0435 \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u044b \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u044b \u0432 \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u043e\u0439 \u043e\u0431\u043b\u0430\u0441\u0442\u0438, \u043d\u043e \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0443 \u0432\u0438\u0434\u043d\u0435\u0435.<\/p>\n<p>  <\/p>\n<p>\u0418\u0442\u0430\u043a, \u0435\u0441\u0442\u044c \u043d\u0430\u0442\u0438\u0432\u043d\u044b\u0439 \u043c\u043e\u0434\u0443\u043b\u044c \u0441 \u043e\u0434\u043d\u0438\u043c \u043c\u0435\u0442\u043e\u0434\u043e\u043c log. \u0427\u0442\u043e\u0431\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0435\u0433\u043e \u043d\u0430 \u0441\u0442\u043e\u0440\u043e\u043d\u0435 React Native, \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u043c \u0438\u0437 React Native \u043e\u0431\u044a\u0435\u043a\u0442 NativeModules. \u0412 NativeModules, \u0435\u0441\u043b\u0438 \u0432\u0441\u0435 \u0441\u0434\u0435\u043b\u0430\u043d\u043e \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e, \u0431\u0443\u0434\u0435\u0442 \u043e\u0431\u044a\u0435\u043a\u0442 \u0441 \u043d\u0430\u0448\u0438\u043c \u043c\u043e\u0434\u0443\u043b\u0435\u043c \u2014 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0431\u0443\u0434\u0435\u0442 \u0442\u043e, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043c\u044b \u0443\u043a\u0430\u0437\u0430\u043b\u0438 \u0432 RCTExternModule. \u0414\u0430\u043b\u044c\u0448\u0435 \u043c\u043e\u0436\u043d\u043e \u043e\u0431\u0440\u0430\u0449\u0430\u0442\u044c\u0441\u044f \u043a\u043e \u0432\u0441\u0435\u043c \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u044f\u043c \u044d\u0442\u043e\u0433\u043e \u043c\u043e\u0434\u0443\u043b\u044f.<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">import React from 'react'; import {View, Button, NativeModules} from 'react-native';  const {SimpleModule} = NativeModules;  const App = () => (   &lt;View style={{flex: 1, justifyContent: 'center', backgroundColor: 'gray'}}>     &lt;Button onPress={() => SimpleModule.log()} title={'Execute'} \/>   &lt;\/View> );  export default App;<\/code><\/pre>\n<p>  <\/p>\n<h1 id=\"peredacha-argumentov-v-nativnyy-modul\">\u041f\u0435\u0440\u0435\u0434\u0430\u0447\u0430 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u0432 \u043d\u0430\u0442\u0438\u0432\u043d\u044b\u0439 \u043c\u043e\u0434\u0443\u043b\u044c<\/h1>\n<p>  <\/p>\n<p>\u041c\u0435\u0445\u0430\u043d\u0438\u0437\u043c \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0439: \u0443 \u043c\u0435\u0442\u043e\u0434\u0430 \u0435\u0441\u0442\u044c \u0441\u0438\u0433\u043d\u0430\u0442\u0443\u0440\u0430, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0432\u043a\u043b\u044e\u0447\u0430\u0435\u0442 \u0432 \u0441\u0435\u0431\u044f \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0435 \u0432\u0445\u043e\u0434\u043d\u044b\u0435 \u0438 \u0432\u044b\u0445\u043e\u0434\u043d\u044b\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b:<\/p>\n<p>  <\/p>\n<pre><code class=\"swift\">@objc(SimpleModule) class SimpleModule: NSObject {   @objc var bridge: RCTBridge!    @objc func log(_ contentToLog: NSString) {     print(contentToLog)   }    @objc static func requiresMainQueueSetup() -> Bool {     return false   } }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0412\u0430\u0436\u043d\u043e \u0443\u0447\u0435\u0441\u0442\u044c, \u0447\u0442\u043e \u0432 Swift \u0438 Objective-C \u0432 \u0441\u0438\u0433\u043d\u0430\u0442\u0443\u0440\u0435 \u043c\u0435\u0442\u043e\u0434\u0430 \u043f\u0440\u0438\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u044f\u0440\u043b\u044b\u043a \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430 \u2014 \u043f\u0440\u0435\u0444\u0438\u043a\u0441 \u043a \u0432\u0445\u043e\u0434\u043d\u043e\u0439 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439. \u0421\u0435\u0439\u0447\u0430\u0441 \u0442\u0430\u043c \u043f\u0440\u043e\u043f\u0443\u0441\u043a, \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u044d\u0442\u043e\u0442 \u043c\u043e\u043c\u0435\u043d\u0442 \u0434\u0430\u043b\u044c\u0448\u0435 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e.<\/p>\n<p>  <\/p>\n<p>\u0412 \u043c\u0435\u0442\u043e\u0434\u044b \u043c\u043e\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c \u0441\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u0443\u0435\u043c\u044b\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u044b \u0438 \u043a\u043e\u043b\u043b\u0431\u044d\u043a\u0438. \u0414\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0435 \u0442\u0438\u043f\u044b \u0443\u043a\u0430\u0437\u0430\u043d\u044b \u0432 <a href=\"https:\/\/reactnative.dev\/docs\/native-modules-ios#argument-types\">\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 React Native<\/a>. \u041c\u043e\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u0434\u0430\u0442\u044c \u043a\u0430\u043a \u043e\u0434\u0438\u043d \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440, \u0442\u0430\u043a \u0438 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u2014 \u0442\u0430\u043a \u0436\u0435, \u043a\u0430\u043a \u0441 \u043b\u044e\u0431\u044b\u043c \u043c\u0435\u0442\u043e\u0434\u043e\u043c:<\/p>\n<p>  <\/p>\n<pre><code class=\"swift\">@objc(SimpleModule) class SimpleModule: NSObject {   @objc var bridge: RCTBridge!    @objc func log(_ contentToLog: NSString, _ contentToLog1: NSString, _ contentToLog2: NSString) {     print(contentToLog)   }    @objc static func requiresMainQueueSetup() -> Bool {     return false   } }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043d\u0430 \u0441\u0442\u043e\u0440\u043e\u043d\u0435 JS \u043c\u043e\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u043a\u0430\u043a \u043e\u0431\u044b\u0447\u043d\u044b\u0435 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b \u0444\u0443\u043d\u043a\u0446\u0438\u0438. \u0412\u0441\u0435 \u0442\u0438\u043f\u044b \u0431\u0443\u0434\u0443\u0442 \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u044b \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438.<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">import React from 'react'; import {View, Button, NativeModules} from 'react-native';  const {SimpleModule} = NativeModules;  const App = () => (   &lt;View style={{flex: 1, justifyContent: 'center'}}>     &lt;Button onPress={() => SimpleModule.log('1', '2', '3')} title={'Execute'} \/>   &lt;\/View> );  export default App;<\/code><\/pre>\n<p>  <\/p>\n<h1 id=\"vzaimodeystvie-nativnyh-moduley-i-javascript\">\u0412\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u043d\u0430\u0442\u0438\u0432\u043d\u044b\u0445 \u043c\u043e\u0434\u0443\u043b\u0435\u0439 \u0438 JavaScript<\/h1>\n<p>  <\/p>\n<p>\u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0442\u044c \u0438\u0437 \u043c\u0435\u0442\u043e\u0434\u0430 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043d\u0435 \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u0435\u0442\u0441\u044f. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f JS \u0438 Native \u2014 \u043a\u043e\u043b\u043b\u0431\u044d\u043a\u0438 \u0438 \u043f\u0440\u043e\u043c\u0438\u0441\u044b. \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043c\u043e\u0436\u043d\u043e, \u0442\u0430\u043a\u043e\u0439 \u043c\u0435\u0442\u043e\u0434 \u0431\u0443\u0434\u0435\u0442 \u043d\u0430\u0437\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u044b\u043c, \u043d\u043e <a href=\"https:\/\/reactnative.dev\/docs\/native-modules-ios#synchronous-methods\">\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f \u043d\u0435 \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0442\u0430\u043a\u043e\u0439 \u043f\u043e\u0434\u0445\u043e\u0434<\/a>.<\/p>\n<p>  <\/p>\n<p><strong>\u041a\u043e\u043b\u043b\u0431\u044d\u043a<\/strong> \u2014 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0435\u0440\u0435\u0434\u0430\u0451\u043c \u0442\u0430\u043a \u0436\u0435, \u043a\u0430\u043a \u0438 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0435 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b. \u0415\u0433\u043e \u043c\u043e\u0436\u0435\u043c \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c \u043f\u043e\u0441\u043b\u0435 \u043a\u0430\u043a\u043e\u0433\u043e-\u043b\u0438\u0431\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u0430.<\/p>\n<p>  <\/p>\n<pre><code class=\"swift\">import Foundation import React  @objc(SimpleModule) class SimpleModule: NSObject {   @objc var bridge: RCTBridge!    @objc func logWithCallback(_ contentToLog: NSString, _ cb: RCTResponseSenderBLock) {     print(contentToLog)     cb(nil)   }    @objc static func requiresMainQueueSetup() -> Bool {     return true   } }<\/code><\/pre>\n<p>  <\/p>\n<pre><code class=\"objectivec\">#import &lt;Foundation\/Foundation.h> #import &lt;React\/RCTBridgeModule.h>  @interface RCT_EXTERN_MODULE(SimpleModule, NSObject) RCT_EXTERN_METHOD(logWithCallback :(NSString *)contentToLog                                   :(RCTResponseSenderBLock *) cb) @end<\/code><\/pre>\n<p>  <\/p>\n<p>\u0412 \u044d\u0442\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043a\u043e\u043b\u043b\u0431\u044d\u043a \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u0441\u044f \u0440\u043e\u0432\u043d\u043e \u043f\u043e\u0441\u043b\u0435 \u0442\u043e\u0433\u043e, \u043a\u0430\u043a \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043f\u043e\u043f\u0430\u0434\u0451\u0442 \u043d\u0430 \u043a\u043e\u043d\u0441\u043e\u043b\u044c. \u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0438\u043c\u043f\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 \u0442\u043e \u0436\u0435 \u0441\u0430\u043c\u043e\u0435 \u2014 \u043f\u0440\u043e\u0441\u0442\u043e \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c.<\/p>\n<p>  <\/p>\n<p>\u0427\u0442\u043e\u0431\u044b \u043c\u0435\u0442\u043e\u0434 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u043b <strong>\u043f\u0440\u043e\u043c\u0438\u0441<\/strong> (Promise) \u0438 \u0435\u0433\u043e \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0441 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0435\u0439 async\/await, \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0434\u0432\u0443\u0445 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0445 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u043c\u0435\u0442\u043e\u0434\u0430 \u043d\u0443\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u0434\u0430\u0442\u044c RCTPromiseResolveBlock \u0438 RCTPromiseRejectBlock. \u041f\u043e \u0441\u0443\u0442\u0438, \u044d\u0442\u043e \u0442\u0435 \u0436\u0435 \u0441\u0430\u043c\u044b\u0435 \u043a\u043e\u043b\u043b\u0431\u044d\u043a\u0438.<\/p>\n<p>  <\/p>\n<pre><code class=\"swift\">import Foundation import React  @objc(SimpleModule) class SimpleModule: NSObject {   @objc var bridge: RCTBridge!    @objc func logWithPromise(_ contentToLog: NSString,                             resolver resolve: RCTPromiseResolveBlock,                             rejecter reject: RCTPromiseRejectBlock) {     print(contentToLog)     resolve(nil)   }    @objc static func requiresMainQueueSetup() -> Bool {     return true   } }<\/code><\/pre>\n<p>  <\/p>\n<pre><code class=\"objectivec\">@interface RCT_EXTERN_MODULE(SimpleModule, NSObject) RCT_EXTERN_METHOD(logWithPromise :(NSString *)contentToLog                   resolver :(RCTPromiseResolveBlock) resolve                   rejecter :(RCTPromiseRejectBlock) reject) @end<\/code><\/pre>\n<p>  <\/p>\n<h1 id=\"primer-nativnogo-modulya\">\u041f\u0440\u0438\u043c\u0435\u0440 \u043d\u0430\u0442\u0438\u0432\u043d\u043e\u0433\u043e \u043c\u043e\u0434\u0443\u043b\u044f<\/h1>\n<p>  <\/p>\n<p>\u0418\u0442\u0430\u043a, \u043c\u044b \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u043b\u0438\u0441\u044c, \u0447\u0442\u043e:<\/p>\n<p>  <\/p>\n<ul>\n<li>\u043a\u0430\u0436\u0434\u044b\u0439 \u0430\u0442\u0440\u0438\u0431\u0443\u0442 \u043c\u043e\u0434\u0443\u043b\u044f \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u043f\u043e\u043c\u0435\u0447\u0435\u043d \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u043e\u043c <a href=\"https:\/\/habr.com\/ru\/users\/objc\/\" class=\"user_link\">objc<\/a>;<\/li>\n<li>\u0432 \u043c\u0435\u0442\u043e\u0434\u044b \u043c\u043e\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b;<\/li>\n<li>\u0441 \u043d\u0430\u0442\u0438\u0432\u043d\u044b\u043c\u0438 \u043c\u0435\u0442\u043e\u0434\u0430\u043c\u0438 \u043c\u043e\u0436\u043d\u043e \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u0447\u0435\u0440\u0435\u0437 \u043a\u043e\u043b\u043b\u0431\u044d\u043a\u0438 \u0438 \u043f\u0440\u043e\u043c\u0438\u0441\u044b.<\/li>\n<\/ul>\n<p>  <\/p>\n<p>\u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043f\u0440\u0438\u043c\u0435\u0440\u0430 \u0440\u0430\u0437\u0431\u0435\u0440\u0451\u043c \u043f\u0440\u043e\u0441\u0442\u0435\u043d\u044c\u043a\u0438\u0439 \u043c\u043e\u0434\u0443\u043b\u044c \u0432\u044b\u0431\u043e\u0440\u0430 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0438\u0437 \u0433\u0430\u043b\u0435\u0440\u0435\u0438. \u042d\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u043e\u0431\u044b\u0447\u043d\u044b\u0439 PHImagePicker, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0438\u0437 React Native. \u041e\u043d \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u0442 \u0432\u044b\u0431\u0440\u0430\u0442\u044c \u043e\u0434\u043d\u0443 \u0444\u043e\u0442\u043e\u0433\u0440\u0430\u0444\u0438\u044e, \u043f\u0435\u0440\u0435\u0434\u0430\u0442\u044c \u0435\u0451 \u043f\u043e \u0441\u0441\u044b\u043b\u043a\u0435 \u0432 \u0444\u0430\u0439\u043b\u043e\u0432\u043e\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u0435 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u043c\u0443 JS \u0438 \u043e\u0442\u043e\u0431\u0440\u0430\u0437\u0438\u0442\u044c \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438. \u0421\u043d\u0430\u0447\u0430\u043b\u0430 \u043e\u043f\u0438\u0448\u0435\u043c, \u043a\u0430\u043a \u044d\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u043d\u0430 \u0441\u0442\u043e\u0440\u043e\u043d\u0435 JavaScript.<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">import React from 'react'; import {View, Button, NativeModules, Image} from 'react-native';  const {ImagePicker} = NativeModules;  const App = () => {   const [image, setImage] = React.useState(null);    const selectImage = React.useCallback(() => {     ImagePicker.selectPhoto()       .then(newImage => {         setImage(newImage);       })       .catch(ex => console.warn(ex));   }, []);<\/code><\/pre>\n<p>  <\/p>\n<p>\u0415\u0441\u0442\u044c \u043d\u0430\u0442\u0438\u0432\u043d\u044b\u0439 \u043c\u043e\u0434\u0443\u043b\u044c ImagePicker \u0441 \u043e\u0434\u043d\u0438\u043c \u043c\u0435\u0442\u043e\u0434\u043e\u043c \u2014 selectPhoto. \u042d\u0442\u043e\u0442 \u043c\u0435\u0442\u043e\u0434 \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u044b\u0439 \u0438 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 resolve-\u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430 \u0431\u0443\u0434\u0435\u0442 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0442\u044c \u0441\u0441\u044b\u043b\u043a\u0443 \u043d\u0430 \u0444\u043e\u0442\u043e\u0433\u0440\u0430\u0444\u0438\u044e, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u044b \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u043c \u0432 temp directory. <\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">return (   &lt;View style={{flex: 1, justifyContent: 'center', alignItems: 'center'}}>     &lt;Button onPress={selectImage} title={'\u0412\u044b\u0431\u0440\u0430\u0442\u044c \u0444\u043e\u0442\u043e'} \/>     &lt;Image       key={image}       source={{uri: image}}       style={{width: '100%', aspectRatio: 1}}     \/>   &lt;\/View> );<\/code><\/pre>\n<p>  <\/p>\n<p>\u0412 UI \u0431\u0443\u0434\u0435\u0442 \u0440\u0438\u0441\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043a\u043d\u043e\u043f\u043a\u0430, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043e\u0442\u043a\u0440\u043e\u0435\u0442 \u043f\u0438\u043a\u0435\u0440 \u0438 \u0441\u0430\u043c\u043e \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435, \u0435\u0441\u043b\u0438 \u043e\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u0432 \u0441\u0442\u0435\u0439\u0442\u0435:<\/p>\n<p>  <\/p>\n<pre><code class=\"objectivec\">#import &lt;Foundation\/Foundation.h> #import &lt;React\/RCTBridgeModule.h>  @interface RCT_EXTERN_MODULE(ImagePicker, NSObject) RCT_EXTERN_METHOD(selectPhoto :(RCTPromiseResolveBlock) resolve                   rejecter :(RCTPromiseRejectBlock) reject) @end<\/code><\/pre>\n<p>  <\/p>\n<p>\u0421\u0430\u043c \u043d\u0430\u0442\u0438\u0432\u043d\u044b\u0439 \u043c\u043e\u0434\u0443\u043b\u044c \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<\/p>\n<p>  <\/p>\n<pre><code class=\"swift\">  @objc func selectPhoto(_ resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) {     self.resolve = resolve     self.reject = reject      guard let rootControlller = RCTPresentedViewController() else {         return     }     var config = PHPickerConfiguration()     config.selectionLimit = 1     config.filter = .images     let pickerController = PHPickerViewController(configuration: config)     pickerController.delegate = self      rootControlller.present(pickerController, animated: true, completion: nil)   }    @objc static func requiresMainQueueSetup() -> Bool {     return true   } }<\/code><\/pre>\n<p>  <\/p>\n<p>\u041d\u0430\u0442\u0438\u0432\u043d\u044b\u0439 \u043c\u0435\u0442\u043e\u0434 selectPhoto \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 resolve \u0438 reject. \u0422\u0443\u0442 \u043c\u043e\u0436\u043d\u043e \u043e\u0431\u0440\u0430\u0442\u0438\u0442\u044c \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0430 @escaping. \u042d\u0442\u043e \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442, \u0447\u0442\u043e \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0435\u043c\u044b\u0435 \u043a\u043e\u043b\u043b\u0431\u044d\u043a\u0438 \u043c\u043e\u0433\u0443\u0442 \u00ab\u0443\u0431\u0435\u0436\u0430\u0442\u044c\u00bb \u2014 \u0432\u044b\u0437\u0432\u0430\u0442\u044c\u0441\u044f \u043d\u0435 \u0441\u0440\u0430\u0437\u0443 \u0432 \u0442\u0435\u043b\u0435 \u043c\u0435\u0442\u043e\u0434\u0430, \u0430 \u043f\u043e\u0437\u0436\u0435, \u043b\u0438\u0431\u043e \u043d\u0435 \u0432\u044b\u0437\u0432\u0430\u0442\u044c\u0441\u044f \u0432\u043e\u043e\u0431\u0449\u0435. \u041f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u0442\u044c <a href=\"https:\/\/docs.swift.org\/swift-book\/LanguageGuide\/Closures.html#ID546\">\u0432 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 \u043f\u043e Swift 5.7<\/a>.<\/p>\n<p>  <\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043c\u044b \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c resolver \u0438 rejecter, \u0447\u0442\u043e\u0431\u044b \u0432\u044b\u0437\u0432\u0430\u0442\u044c \u0432 \u043c\u043e\u043c\u0435\u043d\u0442 \u0432\u044b\u0431\u043e\u0440\u0430 \u0444\u043e\u0442\u043e. \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c rootController \u2014 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 UIViewController, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u00ab\u0440\u0438\u0441\u0443\u0435\u0442\u0441\u044f\u00bb \u0432\u0441\u0451 React Native \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435. \u0421\u043e\u0437\u0434\u0430\u0451\u043c \u0438 \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u043c \u043a\u043e\u043d\u0444\u0438\u0433 \u0434\u043b\u044f PHPickerViewController \u0438 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u043c \u0435\u0433\u043e. \u0410 \u0432 \u043a\u043e\u043d\u0446\u0435 \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c delegate \u0432 pickerController (\u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043c\u043e\u0434\u0443\u043b\u044c \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b \u0424PHPickerViewControllerDelegate) \u0438 \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u043c \u0435\u0433\u043e \u043f\u043e\u0432\u0435\u0440\u0445 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0433\u043e.<\/p>\n<p>  <\/p>\n<p>\u0420\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043d\u0430\u043c \u043c\u0435\u0442\u043e\u0434 func picker (PHPickerViewController, didFinishPicking: [PHPickerResult]), \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u044b\u0437\u043e\u0432\u0435\u0442\u0441\u044f \u0441 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u043c, \u0442\u0430\u043a \u043a\u0430\u043a \u043c\u044b \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043b\u0438 \u0434\u0435\u043b\u0435\u0433\u0430\u0442. \u0414\u0430\u043b\u0435\u0435 \u0432 \u043c\u0435\u0442\u043e\u0434\u0435 prepare \u043c\u044b \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u043c \u044d\u0442\u043e\u0442 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0438 \u0432 \u0441\u043b\u0443\u0447\u0430\u0435 \u0443\u0441\u043f\u0435\u0445\u0430 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c resolve (\u0438\u043b\u0438 reject \u0432 \u0441\u043b\u0443\u0447\u0430\u0435 \u043a\u0430\u043a\u043e\u0439-\u043b\u0438\u0431\u043e \u043e\u0448\u0438\u0431\u043a\u0438).<\/p>\n<p>  <\/p>\n<pre><code class=\"swift\">func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {   picker.dismiss(animated: true, completion: nil)    guard let resolve = resolve, let reject = reject else {     return   }    if results.isEmpty {     resolve(nil)     return   }    prepare(results.first!) { url in     resolve(url)   } _: { code, message, error in     reject(code.rawValue, message, error)   } }<\/code><\/pre>\n<p>  <\/p>\n<pre><code class=\"swift\">private func prepare(_ result: PHPickerResult, _ success: @escaping (String) -> Void, _ failure: @escaping (Code, String, NSError?) -> Void) {   let itemProvider = result.itemProvider    let typeId = itemProvider.registeredTypeIdentifiers.last(where: {     return itemProvider.hasRepresentationConforming(toTypeIdentifier: $0, fileOptions: .init())   })    guard let identifier = typeId else {     failure(Code.NotJPEG, \"Can not represent selected media\", nil)     return   }    itemProvider.loadDataRepresentation(forTypeIdentifier: identifier) { data, error in     let error = ErrorPointer(nilLiteral: ())    guard let tmpFile = RCTTempFilePath(\"jpg\", error), let inputData = data, let uiImage = UIImage(data: inputData) else {     failure(Code.TmpCreationError, \"Can not create intermediate file\", error?.pointee)     return   }    let url = URL(fileURLWithPath: tmpFile)    do {     try uiImage.jpegData(compressionQuality: 1)?.write(to: url)   } catch {     failure(Code.TmpWriteError, \"Can not write to intermediate file\", nil)     return   }<\/code><\/pre>\n<p>  <\/p>\n<p>|<img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/webt\/0g\/ln\/dw\/0glndwma2zkach6dqcjdtldc-py.jpeg\" data-src=\"https:\/\/habrastorage.org\/webt\/0g\/ln\/dw\/0glndwma2zkach6dqcjdtldc-py.jpeg\" data-blurred=\"true\"\/>|<img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/webt\/rb\/ss\/dt\/rbssdtdimwlkglpa19swu_r84so.jpeg\" data-src=\"https:\/\/habrastorage.org\/webt\/rb\/ss\/dt\/rbssdtdimwlkglpa19swu_r84so.jpeg\" data-blurred=\"true\"\/>|<\/p>\n<p>  <\/p>\n<p>\u041f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c. \u0415\u0441\u043b\u0438 \u043d\u0430\u0436\u0430\u0442\u044c \u043d\u0430 \u0435\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u0443\u044e \u043a\u043d\u043e\u043f\u043a\u0443 \u00ab\u0412\u044b\u0431\u0440\u0430\u0442\u044c \u0444\u043e\u0442\u043e\u00bb, \u0442\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u043e\u0448\u0438\u0431\u043a\u0443. \u041e\u043d\u0430 \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442, \u0447\u0442\u043e \u043c\u044b \u043f\u043e\u043f\u044b\u0442\u0430\u043b\u0438\u0441\u044c \u0432\u044b\u0437\u0432\u0430\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0435 \u0434\u043e\u043b\u0436\u0435\u043d \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u0432 \u044d\u0442\u043e\u043c \u043f\u043e\u0442\u043e\u043a\u0435. \u041d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u043f\u043e\u043d\u0438\u043c\u0430\u0442\u044c, \u0433\u0434\u0435 \u0438\u0441\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u043d\u0430\u0448 \u043c\u0435\u0442\u043e\u0434.<\/p>\n<p>  <\/p>\n<p>\u0412 \u0434\u0430\u043d\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b UIKit (UIViewController), \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043a\u043e\u0434 \u0434\u043e\u043b\u0436\u0435\u043d \u0438\u0441\u043f\u043e\u043b\u043d\u044f\u0442\u044c\u0441\u044f \u0432 MainThread:<\/p>\n<p>  <\/p>\n<pre><code class=\"swift\">@objc func selectPhoto(_ resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) {   self.resolve = resolve   self.reject = reject    guard let rootControlller = RCTPresentedViewController() else {     return   }   var config = PHPickerConfiguration()   config.selectionLimit = 1   config.filter = .images   let pickerController = PHPickerViewController(configuration: config)   pickerController.delegate = self    rootControlller.present(pickerController, animated: true, completion: nil) }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0427\u0442\u043e\u0431\u044b \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b \u0432 MainThread, \u0443 React Native \u0435\u0441\u0442\u044c \u043c\u0435\u0442\u043e\u0434 RCTExecuteOnMainQueue. \u0412 \u043d\u0435\u0433\u043e \u043d\u0443\u0436\u043d\u043e \u043f\u043e\u043c\u0435\u0441\u0442\u0438\u0442\u044c \u0431\u043b\u043e\u043a \u043a\u043e\u0434\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0443\u0436\u043d\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u0432 MainThread:<\/p>\n<p>  <\/p>\n<pre><code class=\"swift\">RCTExecuteOnMainQueue {   guard let rootControlller = RCTPresentedViewController() else {     return   }   var config = PHPickerConfiguration()   config.selectionLimit = 1   config.filter = .images   let pickerController = PHPickerViewController(configuration: config)   pickerController.delegate = self    rootControlller.present(pickerController, animated: true, completion: nil)  }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0422\u043e\u0433\u0434\u0430 \u043a\u043e\u0434 \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043e\u0442\u043b\u0438\u0447\u043d\u043e: \u043e\u0442\u043a\u0440\u043e\u0435\u0442\u0441\u044f \u043f\u0438\u043a\u0435\u0440, \u043c\u044b \u0443\u0432\u0438\u0434\u0438\u043c \u0444\u043e\u0442\u043e \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438. \u041f\u043e \u043d\u0435\u043c\u0443 \u043c\u043e\u0436\u043d\u043e \u043a\u043b\u0438\u043a\u0430\u0442\u044c, \u0438 \u043d\u0438\u043a\u0430\u043a\u043e\u0439 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u043d\u0435\u0442.<\/p>\n<p>  <\/p>\n<p>\u0414\u043b\u044f \u043e\u0434\u043d\u043e\u0433\u043e \u043c\u0435\u0442\u043e\u0434\u0430 \u0432\u0441\u0451 \u0445\u043e\u0440\u043e\u0448\u043e. \u041d\u043e \u0435\u0441\u043b\u0438 \u0438\u0445 \u043c\u043d\u043e\u0433\u043e, \u0437\u0430\u0447\u0435\u043c \u043a\u0430\u0436\u0434\u044b\u0439 \u0440\u0430\u0437 \u043f\u0438\u0441\u0430\u0442\u044c RCTExecuteOnMainQueue? \u0423 React Native \u0435\u0441\u0442\u044c \u0430\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u0430 \u2014 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u043f\u043e\u0442\u043e\u043a \u0438\u0441\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0434\u043b\u044f \u0432\u0441\u0435\u0433\u043e \u043d\u0430\u0442\u0438\u0432\u043d\u043e\u0433\u043e \u043c\u043e\u0434\u0443\u043b\u044f, \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0432 \u043c\u0435\u0442\u043e\u0434 methodQueue:<\/p>\n<p>  <\/p>\n<pre><code class=\"swift\">  guard let rootControlller = RCTPresentedViewController() else {     return   }   var config = PHPickerConfiguration()   config.selectionLimit = 1   config.filter = .images   let pickerController = PHPickerViewController(configuration: config)   pickerController.delegate = self    rootControlller.present(pickerController, animated: true, completion: nil) }  @objc func methodQueue() -> DispatchQueue {   return .main }<\/code><\/pre>\n<p>  <\/p>\n<p>\u042d\u0442\u043e\u0442 \u043c\u0435\u0442\u043e\u0434 \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u0432 \u0438\u043d\u0441\u0442\u0430\u043d\u0441\u0435 \u043d\u0430\u0442\u0438\u0432\u043d\u043e\u0433\u043e \u043c\u043e\u0434\u0443\u043b\u044f \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 DispatchQueue. \u0422\u0435\u043f\u0435\u0440\u044c \u0432\u0441\u0435 \u043d\u0430\u0448\u0438 \u043d\u0430\u0442\u0438\u0432\u043d\u044b\u0435 \u043c\u043e\u0434\u0443\u043b\u0438 \u0431\u0443\u0434\u0443\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c\u0441\u044f \u0441\u0442\u0440\u043e\u0433\u043e MainQueue.<\/p>\n<p>  <\/p>\n<h1 id=\"struktura-nativnogo-komponenta-i-shadow-thread\">\u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u043d\u0430\u0442\u0438\u0432\u043d\u043e\u0433\u043e \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 \u0438 Shadow thread<\/h1>\n<p>  <\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043f\u0435\u0440\u0435\u0439\u0434\u0451\u043c \u043a \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0438 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0435 \u043d\u0430\u0442\u0438\u0432\u043d\u044b\u0445 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432. \u0421\u043d\u0430\u0447\u0430\u043b\u0430 \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043d\u0430 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0443 React Native-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f:<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/webt\/5d\/wp\/ua\/5dwpua2fpohlxsuxicouncqaiay.jpeg\" data-src=\"https:\/\/habrastorage.org\/webt\/5d\/wp\/ua\/5dwpua2fpohlxsuxicouncqaiay.jpeg\" data-blurred=\"true\"\/><\/p>\n<p>  <\/p>\n<p>\u0415\u0441\u0442\u044c \u0431\u0440\u0438\u0434\u0436, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0433\u043e\u043d\u044f\u0435\u0442 JSON \u0438\u0437 JS \u0432 native \u0438 \u043e\u0431\u0440\u0430\u0442\u043d\u043e. \u0418 Shadow thread, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u0442\u0440\u043e\u0438\u0442 \u0432\u0435\u0441\u044c layout \u2014 \u0440\u0430\u0437\u043c\u0435\u0440\u044b \u0438 \u043f\u043e\u0437\u0438\u0446\u0438\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0434\u0440\u0443\u0433\u0438\u0445 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432. \u0422\u0443\u0442 React Native \u043e \u043d\u0430\u0441 \u043f\u043e\u0437\u0430\u0431\u043e\u0442\u0438\u043b\u0441\u044f: \u043d\u0435 \u043d\u0443\u0436\u043d\u043e \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0442\u044c layout-\u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b (\u0432\u044b\u0441\u043e\u0442\u0430, \u0448\u0438\u0440\u0438\u043d\u0430, flex-\u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430, paddings \u0438 \u0442\u0430\u043a \u0434\u0430\u043b\u0435\u0435). \u041f\u0440\u043e\u0441\u0442\u043e \u043f\u0438\u0448\u0435\u043c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442, \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u043c \u0438\u0434\u0435\u0430\u043b\u044c\u043d\u044b\u0435 \u0443\u0441\u043b\u043e\u0432\u0438\u044f \u2014 \u0438 \u0432\u0441\u0451 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442. \u041d\u043e \u0442\u0430\u043a\u0430\u044f \u0441\u0445\u0435\u043c\u0430 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0441\u043b\u043e\u0436\u043d\u043e\u0441\u0442\u0438.<\/p>\n<p>  <\/p>\n<p>\u041d\u0430\u0442\u0438\u0432\u043d\u044b\u0439 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0432 \u043f\u0435\u0440\u0432\u0443\u044e \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u0441\u043e\u0441\u0442\u043e\u0438\u0442 \u0438\u0437 ViewManager \u2014 \u0444\u0430\u0431\u0440\u0438\u043a\u0438, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u0440\u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u0442 UIView \u0438 ShadowView. \u041f\u043e \u0441\u0443\u0442\u0438, ViewManager \u2014 \u0442\u043e\u0442 \u0436\u0435 \u043d\u0430\u0442\u0438\u0432\u043d\u044b\u0439 \u043c\u043e\u0434\u0443\u043b\u044c, \u043d\u043e \u0441 \u0434\u0440\u0443\u0433\u0438\u043c \u0431\u0430\u0437\u043e\u0432\u044b\u043c \u043a\u043b\u0430\u0441\u0441\u043e\u043c.<\/p>\n<p>  <\/p>\n<h1 id=\"napishem-prostoy-komponent-bez-shadowview\">\u041d\u0430\u043f\u0438\u0448\u0435\u043c \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0431\u0435\u0437 ShadowView<\/h1>\n<p>  <\/p>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043d\u0430\u043f\u0438\u0448\u0435\u043c \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u043b\u0435\u0439\u0431\u043b \u0438 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c, \u043a\u0430\u043a \u044d\u0442\u043e \u0432\u0441\u0451 \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0438 \u043a\u0430\u043a\u0438\u0435 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u043c\u043e\u0433\u0443\u0442 \u0432\u043e\u0437\u043d\u0438\u043a\u043d\u0443\u0442\u044c \u043f\u0440\u0438 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u0441\u0432\u043e\u0435\u0433\u043e \u043d\u0430\u0442\u0438\u0432\u043d\u043e\u0433\u043e \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430.<\/p>\n<p>  <\/p>\n<pre><code class=\"swift\">import Foundation  class SimpleTextViewManager: RCTViewManager {   override static func requiresMainQueueSetup() -> Bool {     return true   }    override func view() -> UIView! {     return SimpeTextView()   } }<\/code><\/pre>\n<p>  <\/p>\n<pre><code class=\"objectivec\">#import &lt;React\/RCTViewManager.h>  @interface RCT_EXTERN_MODULE(SimpleTextViewManager, RCTViewManager) @end<\/code><\/pre>\n<p>  <\/p>\n<pre><code class=\"swift\">import Foundation  class SimpeTextView : UILabel {  }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0421\u043d\u0430\u0447\u0430\u043b\u0430 \u043e\u043f\u0438\u0448\u0435\u043c \u043a\u043b\u0430\u0441\u0441 SimpleTextViewManager \u0438 \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043c \u0443 \u043d\u0435\u0433\u043e \u043c\u0435\u0442\u043e\u0434 view, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0434\u043e\u043b\u0436\u0435\u043d \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0442\u044c UIView (\u0438\u0437 UIKit). \u042d\u0442\u043e\u0442 UIView \u0438 \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c\u0441\u044f \u0438\u0437 RN. \u0414\u0430\u043b\u0435\u0435 \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043a\u043b\u0430\u0441\u0441 SimpleTextView, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043e\u0442 UILabel (\u0430 \u043e\u043d, \u0432 \u0441\u0432\u043e\u044e \u043e\u0447\u0435\u0440\u0435\u0434\u044c, \u043e\u0442 UIView) \u0438 \u0432\u0435\u0440\u043d\u0435\u043c \u0435\u0433\u043e \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \u0438\u0437 \u043c\u0435\u0442\u043e\u0434\u0430 view() \u0432 SimpleViewManager.<\/p>\n<p>  <\/p>\n<p>\u0414\u043e\u0431\u0430\u0432\u0438\u043c \u0432 SimpleTextView \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e content, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0431\u0443\u0434\u0435\u0442 \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0442\u044c \u0442\u0435\u043a\u0441\u0442 \u0447\u0435\u0440\u0435\u0437 React props. \u0422\u0430\u043a\u0438\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b, \u043a\u0430\u043a font, alignment, numberOfLines, \u0437\u0430\u0445\u0430\u0440\u0434\u043a\u043e\u0434\u0438\u043c, \u043d\u043e \u0438\u0445 \u0442\u043e\u0436\u0435 \u043c\u043e\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c.<\/p>\n<p>  <\/p>\n<p>\u0427\u0442\u043e\u0431\u044b \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0447\u0435\u0440\u0435\u0437 React props, \u043a\u0430\u043a \u0438 \u0441 \u043d\u0430\u0442\u0438\u0432\u043d\u044b\u043c\u0438 \u043c\u043e\u0434\u0443\u043b\u044f\u043c\u0438, \u043a\u0430\u0436\u0434\u043e\u0435 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e \u0432 UIView \u043d\u0443\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043c\u0435\u0447\u0430\u0442\u044c \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u043e\u043c <a href=\"https:\/\/habr.com\/ru\/users\/objc\/\" class=\"user_link\">objc<\/a> \u0438 \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432 \u0444\u0430\u0439\u043b\u0435 \u0438\u043c\u043f\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 UIManager.<\/p>\n<p>  <\/p>\n<pre><code class=\"swift\">import Foundation  class SimpleTextView: UILabel {   override init(frame: CGRect) {     super.init(frame: frame)      setupView()   }    required init?(coder: NSCoder) {     super.init(coder: coder)      setupView()   }    @objc var content: String = \"\" {     didSet {       self.text = content     }   }    func setupView() {     font = .systemFont(ofSize: 14)     textAlignment = .center     numberOfLines = 0   } }<\/code><\/pre>\n<p>  <\/p>\n<pre><code class=\"objectivec\">#import &lt;React\/RCTViewManager.h>  @interface RCT_EXTERN_MODULE(SimpleTextViewManager, RCTViewManager)   RCT_EXPORT_VIEW_PROPERTY(content, NSString) @end<\/code><\/pre>\n<p>  <\/p>\n<p>\u041f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u043d\u0430 \u0441\u0442\u043e\u0440\u043e\u043d\u0443 React Native:<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">import React from 'react'; import {View, requireNativeComponent} from 'react-native';  const SimpleTextView = requireNativeComponent('SimpleTextView');  const App = () => (   &lt;View style={{flex: 1, justifyContent: 'center'}}>     &lt;SimpleTextView style={{flex:1}} content={'Hello world'} \/>   &lt;\/View> );  export default App;<\/code><\/pre>\n<p>  <\/p>\n<p>\u0427\u0442\u043e\u0431\u044b \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u043d\u0430\u0442\u0438\u0432\u043d\u044b\u0439 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442, \u0443 React Native \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 \u0444\u0443\u043d\u043a\u0446\u0438\u044f requireNativeComponent. \u041e\u043d\u0430 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u0432 \u0441\u0435\u0431\u044f \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 \u2014 \u0432 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u044d\u0442\u043e SimpleTextView.<\/p>\n<p>  <\/p>\n<p>\u041f\u043e\u043b\u0443\u0447\u0430\u0435\u0442\u0441\u044f \u0432\u044c\u044e\u0448\u043a\u0430, \u0443 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0432\u044b\u0441\u043e\u0442\u0430 \u0438 \u0448\u0438\u0440\u0438\u043d\u0430 \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u0435, \u0430 \u0432\u0435\u0441\u044c \u043a\u043e\u043d\u0442\u0435\u043d\u0442 \u0440\u0430\u0441\u043f\u043e\u043b\u0430\u0433\u0430\u0435\u0442\u0441\u044f \u043f\u043e \u0446\u0435\u043d\u0442\u0440\u0443. \u0418 \u043d\u0430\u0442\u0438\u0432\u043d\u0430\u044f \u0432\u044c\u044e\u0448\u043a\u0430, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0440\u0430\u0441\u0442\u044f\u0433\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u043f\u043e \u0432\u0441\u0435\u043c\u0443 \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u043c\u0443 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0443. \u041a\u043e\u043d\u0442\u0435\u043d\u0442 \u043e\u0431\u044b\u0447\u043d\u044b\u0439, \u00abHello world\u00bb. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c, \u043a\u0430\u043a \u044d\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u043d\u0430 \u044d\u043a\u0440\u0430\u043d\u0435:<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/webt\/ad\/zk\/0o\/adzk0ojwmxmu_t-cnlj8mlekvle.jpeg\" data-src=\"https:\/\/habrastorage.org\/webt\/ad\/zk\/0o\/adzk0ojwmxmu_t-cnlj8mlekvle.jpeg\" data-blurred=\"true\"\/><\/p>\n<p>  <\/p>\n<p>\u0412 \u0438\u043d\u0441\u043f\u0435\u043a\u0442\u043e\u0440\u0435 \u0432\u0438\u0434\u0438\u043c, \u0447\u0442\u043e \u0432\u044c\u044e\u0448\u043a\u0430 \u0437\u0430\u043d\u0438\u043c\u0430\u0435\u0442 \u0432\u0441\u0451 \u0441\u0432\u043e\u0431\u043e\u0434\u043d\u043e\u0435 \u043c\u0435\u0441\u0442\u043e. \u042d\u0442\u043e \u043b\u043e\u0433\u0438\u0447\u043d\u043e: \u043c\u044b \u0443\u043a\u0430\u0437\u0430\u043b\u0438 \u0435\u0439 flex = 1. \u041d\u043e \u0445\u043e\u0442\u0438\u043c \u043b\u0438 \u043c\u044b, \u0447\u0442\u043e\u0431\u044b \u043b\u0435\u0439\u0431\u043b \u0442\u0430\u043a \u0441\u0435\u0431\u044f \u0432\u0451\u043b? \u041d\u0435\u0442. \u0410 \u0435\u0441\u043b\u0438 \u0443\u0431\u0435\u0440\u0451\u043c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 flex, \u043d\u0430 \u044d\u043a\u0440\u0430\u043d\u0435 \u043f\u0440\u043e\u0441\u0442\u043e \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u0431\u0443\u0434\u0435\u0442, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e Yoga \u043f\u043e\u0441\u0447\u0438\u0442\u0430\u0435\u0442 \u0432\u044b\u0441\u043e\u0442\u0443 \u0438 \u0448\u0438\u0440\u0438\u043d\u0443 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430, \u0440\u0430\u0432\u043d\u0443\u044e 0.<\/p>\n<p>  <\/p>\n<p>\u0420\u0435\u0448\u0438\u0442\u044c \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0443, \u043e\u043f\u0438\u0441\u0430\u043d\u043d\u0443\u044e \u0432\u044b\u0448\u0435, \u043d\u0430\u043c \u043f\u043e\u043c\u043e\u0436\u0435\u0442 ShadowView. \u042d\u0442\u043e \u043a\u043b\u0430\u0441\u0441, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0432\u0441\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 \u0434\u043b\u044f Yoga engine \u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b \u0440\u0430\u0441\u0447\u0451\u0442\u0430 \u0432\u0441\u0435\u0433\u043e Layout. \u0417\u0430\u0434\u0430\u0432\u0430\u0442\u044c \u0435\u043c\u0443 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 \u043c\u043e\u0436\u043d\u043e \u0447\u0435\u0440\u0435\u0437 props \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430.<\/p>\n<p>  <\/p>\n<p>\u0414\u043b\u044f \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u0437\u0430\u0434\u0430\u0447\u0438 \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043a\u043b\u0430\u0441\u0441, \u043d\u0430\u0441\u043b\u0435\u0434\u0443\u0435\u043c\u044b\u0439 \u043e\u0442 ShadowView, \u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u043c \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0434\u043b\u044f \u0440\u0430\u0441\u0447\u0451\u0442\u0430 layout. ShadowView \u2014 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u043a\u043b\u0430\u0441\u0441, \u0443 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0443\u0436\u0435 \u0435\u0441\u0442\u044c \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 \u0434\u043b\u044f \u043f\u043e\u0434\u0441\u0447\u0451\u0442\u0430 layout: flex, width, height \u0438 \u0434\u0440\u0443\u0433\u0438\u0435.<\/p>\n<p>  <\/p>\n<pre><code class=\"objectivec\">import React  class SimpleTextShadowView: RCTShadowView {   @objc var content: String = \"\" }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0427\u0442\u043e\u0431\u044b \u0432\u044b\u0441\u043e\u0442\u0430 \u0438 \u0448\u0438\u0440\u0438\u043d\u0430 \u043d\u0430\u0448\u0435\u0433\u043e \u043b\u0435\u0439\u0431\u043b\u0430 \u0441\u0447\u0438\u0442\u0430\u043b\u0438\u0441\u044c \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0435\u043c\u044b\u0445 \u0442\u0443\u0434\u0430 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432, \u043d\u0430\u043c \u043f\u043e\u043a\u0430 \u043d\u0443\u0436\u043d\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e content.<\/p>\n<p>  <\/p>\n<p>\u041d\u0430\u0441\u043b\u0435\u0434\u0443\u0435\u0442\u0441\u044f \u043e\u043d \u043e\u0442 \u043a\u043b\u0430\u0441\u0441\u0430 RCTShadowView \u0438 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u0432 \u0441\u0435\u0431\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 content, \u043f\u043e \u0434\u0435\u0444\u043e\u043b\u0442\u0443 \u043f\u0443\u0441\u0442\u043e\u0439. \u0422\u0435\u043f\u0435\u0440\u044c \u0443 ShadowView \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432, \u0447\u0442\u043e\u0431\u044b \u0440\u0430\u0441\u0441\u0447\u0438\u0442\u044b\u0432\u0430\u0442\u044c layout \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0432\u0445\u043e\u0434\u044f\u0449\u0438\u0445 props.<\/p>\n<p>  <\/p>\n<p>\u041a\u043b\u0430\u0441\u0441 ShadowView \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e yogaNode, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0438 \u0443\u0447\u0430\u0441\u0442\u0432\u0443\u0435\u0442 \u0432 \u0440\u0430\u0441\u0447\u0451\u0442\u0435 \u0432\u0441\u0435\u0433\u043e layout. \u0415\u043c\u0443 \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u0434\u0430\u0432\u0430\u0442\u044c \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0435 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 \u0442\u0438\u043f\u0430 flex, flexShrink, flexBasis, height \u0438 \u0434\u0440\u0443\u0433\u0438\u0435.<\/p>\n<p>  <\/p>\n<p>\u041d\u043e \u0447\u0442\u043e \u0434\u0435\u043b\u0430\u0442\u044c, \u0435\u0441\u043b\u0438 \u0432\u044b\u0441\u043e\u0442\u0430 \u0438 \u0448\u0438\u0440\u0438\u043d\u0430 \u043a\u043e\u043d\u0442\u0435\u043d\u0442\u0430 \u043d\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u043d\u0430 \u0438 \u0434\u043e\u043b\u0436\u043d\u0430 \u0437\u0430\u0432\u0438\u0441\u0435\u0442\u044c \u043e\u0442 \u043a\u0430\u043a\u043e\u0433\u043e-\u043b\u0438\u0431\u043e \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430? \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0432 Yoga \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u0434\u0430\u0442\u044c \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 measureFunc. \u041e\u043d\u0430 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 YogaNode \u0432\u043c\u0435\u0441\u0442\u0435 \u0441 \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0439 \u0438 \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0439 \u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u043e\u0439 \u0432\u044b\u0441\u043e\u0442\u043e\u0439 \u0438 \u0448\u0438\u0440\u0438\u043d\u043e\u0439. \u0410 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 YGSize \u2014 \u0438\u0442\u043e\u0433\u043e\u0432\u0443\u044e \u0432\u044b\u0441\u043e\u0442\u0443 \u0438 \u0448\u0438\u0440\u0438\u043d\u0443. \u0412 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 ShadowView \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<\/p>\n<p>  <\/p>\n<pre><code class=\"swift\">class SimpleTextShadowView: RCTShadowView {   static let measure: YGMeasureFunc = {node, width, widthNode, height, heightNode in     guard let context = YGNodeGetContext(node) else {       return YGSize(width: 0, height: 0)     }      let instance = Unmanaged&lt;SimpleTextShadowView>.fromOpaque(context).takeRetainedValue()     let height = getHeight(       for: NSAttributedString(string: instance.content),       font: .systemFont(ofSize: 14),       width: width)      return YGSize(width: width, height: height)    }    @objc var content: String = \"\"    override init() {     super.init()      YGNodeSetMeasureFunc(self.yogaNode!, SimpleTextShadowView.measure)     YGNodeSetContext(self.yogaNode!, Unmanaged.passRetained(self).toOpaque())   }    override func layout(with layoutMetrics: RCTLayoutMetrics, layoutContext: RCTLayoutContext) {     super.layout(with: layoutMetrics, layoutContext: layoutContext)   } }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0417\u0434\u0435\u0441\u044c \u043c\u044b:<\/p>\n<p>  <\/p>\n<ol>\n<li>\u0421\u043e\u0437\u0434\u0430\u043b\u0438 \u043a\u043b\u0430\u0441\u0441, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0430\u0441\u043b\u0435\u0434\u0443\u0435\u0442\u0441\u044f \u043e\u0442 RCTShadowView, \u2014 \u0431\u0430\u0437\u043e\u0432\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 \u0434\u043b\u044f ShadowView.<\/li>\n<li>\u0414\u043b\u044f yogaNode \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043b\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u044e measure.<\/li>\n<li>\u0414\u043b\u044f yogaNode \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043b\u0438 context \u2014 \u0441\u0441\u044b\u043b\u043a\u0443 \u043d\u0430 \u043e\u0431\u044a\u0435\u043a\u0442 \u043d\u0430\u0448\u0435\u0433\u043e SimpleTextShadowView, \u0447\u0442\u043e\u0431\u044b \u0432 measureFunc \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f content.<\/li>\n<\/ol>\n<p>  <\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043d\u0430 \u043d\u0430\u0448\u0443 \u0444\u0443\u043d\u043a\u0446\u0438\u044e measure. \u0412 \u043d\u0435\u0439 \u043c\u044b:<\/p>\n<p>  <\/p>\n<ol>\n<li>\u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0441\u0441\u044b\u043b\u043a\u0443 \u043d\u0430 \u043d\u0430\u0448 \u043e\u0431\u044a\u0435\u043a\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u044b \u0437\u0430\u043f\u0430\u043a\u043e\u0432\u0430\u043b\u0438 \u0432 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440\u0435. \u042d\u0442\u043e \u043d\u0443\u0436\u043d\u043e, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e content.<\/li>\n<li>\u0420\u0430\u0441\u0441\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u043c \u0432\u044b\u0441\u043e\u0442\u0443 \u0434\u043b\u044f \u043d\u0430\u0448\u0435\u0433\u043e \u0442\u0435\u043a\u0441\u0442\u0430 \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e \u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u043e\u0439 \u0448\u0438\u0440\u0438\u043d\u044b. \u0424\u0443\u043d\u043a\u0446\u0438\u044e getHeight \u044f \u0432\u0437\u044f\u043b \u0438\u0437 \u043f\u0435\u0440\u0432\u043e\u0433\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0432 Google, \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u043e\u043d\u0430 \u0442\u0430\u043a:<br \/> \n<pre><code class=\"swift\">func getHeight(for attributedString: NSAttributedString, font: UIFont, width: Float) -> Float {   let textStorage = NSTextStorage(attributedString: attributedString)   let textContainter = NSTextContainer(size: CGSize(width: CGFloat.greatestFiniteMagnitude, height: CGFloat.greatestFiniteMagnitude))   let layoutManager = NSLayoutManager()   layoutManager.addTextContainer(textContainter)   textStorage.addLayoutManager(layoutManager)   textStorage.addAttribute(NSAttributedString.Key.font, value: font, range: NSMakeRange(0, textStorage.length))   textContainter.maximumNumberOfLines = 0   textContainter.lineFragmentPadding = 0.0   layoutManager.glyphRange(for: textContainter)   return Float(layoutManager.usedRect(for: textContainter).size.height) }<\/code><\/pre>\n<\/li>\n<\/ol>\n<p>  <\/p>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0442\u0435\u043f\u0435\u0440\u044c \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043c \u043f\u0440\u0438\u043c\u0435\u0440, \u0443\u0431\u0440\u0430\u0432 \u0432\u0441\u0435 style props \u0432 \u043d\u0430\u0448\u0435\u043c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0435, \u0438 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0432 layout-\u0438\u043d\u0441\u043f\u0435\u043a\u0442\u043e\u0440\u0435, \u0447\u0442\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u043e\u0441\u044c:<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/webt\/m4\/cb\/_9\/m4cb_9x7k-uwvfs16du9flpf2be.jpeg\" data-src=\"https:\/\/habrastorage.org\/webt\/m4\/cb\/_9\/m4cb_9x7k-uwvfs16du9flpf2be.jpeg\" data-blurred=\"true\"\/><\/p>\n<p>  <\/p>\n<p>\u0412\u044b\u0441\u043e\u0442\u0430 \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0430\u0441\u044c 51 \u043f\u043e\u0438\u043d\u0442, \u0430 \u0448\u0438\u0440\u0438\u043d\u0430 \u2014 \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430\u044f \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u0430\u044f. \u041c\u043e\u0436\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043f\u044d\u0434\u0434\u0438\u043d\u0433\u0438 \u0443 \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044f, \u0438 \u043f\u0440\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0435 \u043e\u043d\u0438 \u0441\u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442.<\/p>\n<p>  <\/p>\n<p>\u0412\u043e\u0442 \u0438 \u0432\u0441\u044f \u0438\u0441\u0442\u043e\u0440\u0438\u044f \u2014 \u043c\u043e\u0436\u043d\u043e \u0431\u0440\u0430\u0442\u044c \u0438 \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0442\u044c \u043d\u0430 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0435. \u0415\u0441\u043b\u0438 \u043e\u0441\u0442\u0430\u043b\u0438\u0441\u044c \u0432\u043e\u043f\u0440\u043e\u0441\u044b \u0438\u043b\u0438 \u043f\u043e\u044f\u0432\u0438\u043b\u0438\u0441\u044c \u043a\u0430\u043a\u0438\u0435-\u0442\u043e \u043c\u044b\u0441\u043b\u0438, \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442\u0435 \u0432 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0438, \u043f\u043e\u043e\u0431\u0449\u0430\u0435\u043c\u0441\u044f.<\/p>\n<p>  <\/p>\n<p><em>\u041c\u044b \u0437\u0430\u0432\u0435\u043b\u0438 \u0441\u043e\u0446\u0441\u0435\u0442\u0438 \u0441 \u043d\u043e\u0432\u043e\u0441\u0442\u044f\u043c\u0438 \u0438 \u0430\u043d\u043e\u043d\u0441\u0430\u043c\u0438 Tech-\u043a\u043e\u043c\u0430\u043d\u0434\u044b. \u0415\u0441\u043b\u0438 \u0445\u043e\u0442\u0438\u0442\u0435 \u0443\u0437\u043d\u0430\u0442\u044c, \u0447\u0442\u043e \u043f\u043e\u0434 \u043a\u0430\u043f\u043e\u0442\u043e\u043c \u0432\u044b\u0441\u043e\u043a\u043e\u043d\u0430\u0433\u0440\u0443\u0436\u0435\u043d\u043d\u043e\u0433\u043e e-commerce, \u0441\u043b\u0435\u0434\u0438\u0442\u0435 \u0437\u0430 \u043d\u0430\u043c\u0438 \u0442\u0430\u043c, \u0433\u0434\u0435 \u0432\u0430\u043c \u0443\u0434\u043e\u0431\u043d\u0435\u0435 \u0432\u0441\u0435\u0433\u043e: <a href=\"https:\/\/t.me\/sbermarket_tech\">Telegram<\/a>, <a href=\"https:\/\/vk.com\/sbermarket_tech\">VK<\/a>.<\/em><\/p>\n<\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/671978\/\"> https:\/\/habr.com\/ru\/articles\/671978\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-1\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/k8\/gw\/hc\/k8gwhc1wyy6eywxi5lfa6c7ewb8.png\" data-src=\"https:\/\/habrastorage.org\/webt\/k8\/gw\/hc\/k8gwhc1wyy6eywxi5lfa6c7ewb8.png\"\/><\/p>\n<p>  <\/p>\n<p>\u041f\u0440\u0438\u0432\u0435\u0442! \u041c\u0435\u043d\u044f \u0437\u043e\u0432\u0443\u0442 \u0413\u0435\u043e\u0440\u0433\u0438\u0439 \u041c\u0438\u0448\u0438\u043d, \u044f \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u044b\u0439 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0432 \u0421\u0431\u0435\u0440\u041c\u0430\u0440\u043a\u0435\u0442\u0435. \u0425\u043e\u0447\u0443 \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u0430\u0442\u044c, \u043a\u0430\u043a \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c Swift \u0432 React Native-\u043f\u0440\u043e\u0435\u043a\u0442. \u0412 \u0440\u0430\u043c\u043a\u0430\u0445 \u0441\u0442\u0430\u0442\u044c\u0438 \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043f\u0440\u043e\u0441\u0442\u0435\u043d\u044c\u043a\u0438\u0439 \u043d\u0430\u0442\u0438\u0432\u043d\u044b\u0439 \u043c\u043e\u0434\u0443\u043b\u044c \u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442, \u043e\u0431\u0441\u0443\u0434\u0438\u043c layout \u0432 React Native-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438 \u0438 \u043f\u043e\u0433\u043e\u0432\u043e\u0440\u0438\u043c, \u0447\u0442\u043e \u0436\u0435 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0432 shadow thread.<\/p>\n<p>  <\/p>\n<p>\u042d\u0442\u043e \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u0430\u044f \u0432\u0435\u0440\u0441\u0438\u044f \u043c\u043e\u0435\u0433\u043e <a href=\"https:\/\/youtu.be\/LpgpJZzDMWk?t=300\">\u0432\u044b\u0441\u0442\u0443\u043f\u043b\u0435\u043d\u0438\u044f \u043d\u0430 Android Meetup | \u0421\u0431\u0435\u0440\u041c\u0430\u0440\u043a\u0435\u0442 Tech<\/a>.<\/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-385923","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/385923","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=385923"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/385923\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=385923"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=385923"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=385923"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}