{"id":443083,"date":"2024-12-26T04:53:11","date_gmt":"2024-12-26T04:53:11","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=443083"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=443083","title":{"rendered":"<span>\u0423\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 Xcode \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u043e\u043c \u0438\u0437 \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u0430<\/span>"},"content":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u041a\u0430\u043a \u043c\u044b \u0437\u043d\u0430\u0435\u043c, \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u043e\u043c \u043c\u043e\u0436\u043d\u043e \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0438\u0442\u044c \u0438\u0437 \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u043b\u0430, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f <em>simctl<\/em> \u0443\u0442\u0438\u043b\u0438\u0442\u0443, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0432\u043c\u0435\u0441\u0442\u0435 \u0441 Xcode \u0438 \u0440\u0430\u0441\u043f\u043e\u043b\u0430\u0433\u0430\u0435\u0442\u0441\u044f \u043f\u043e \u043f\u0443\u0442\u0438:<\/p>\n<pre><code class=\"bash\">Xcode.app\/Contents\/Developer\/usr\/bin\/simctl<\/code><\/pre>\n<p>\u0415\u0441\u043b\u0438 \u0438\u0437 \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u043b\u0430 \u0432\u044b\u0437\u0432\u0430\u0442\u044c <em>simctl<\/em>, \u0442\u043e, \u0441\u043a\u043e\u0440\u0435\u0435 \u0432\u0441\u0435\u0433\u043e, \u0432\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u0435 \u043e\u0448\u0438\u0431\u043a\u0443:<\/p>\n<pre><code class=\"bash\">\"command not found: simctl\"<\/code><\/pre>\n<p>\u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c proxy \u0443\u0442\u0438\u043b\u0438\u0442\u0443 <em>xcrun<\/em>, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u0435\u0440\u0435\u043d\u0430\u043f\u0440\u0430\u0432\u0438\u0442 \u043e\u0431\u0440\u0430\u0449\u0435\u043d\u0438\u0435 \u043a <em>simctl<\/em>, \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u0443\u044e \u0432 Xcode \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e (\u0447\u0442\u043e\u0431\u044b \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c Xcode \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e, \u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c xcode-select \u0443\u0442\u0438\u043b\u0438\u0442\u0443 \u0441 \u043f\u0440\u0430\u0432\u0430\u043c\u0438 root) \u0438\u043b\u0438 \u0436\u0435 \u043c\u043e\u0436\u043d\u043e \u0432 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f \u0440\u0430\u0441\u0448\u0438\u0440\u0438\u0442\u044c PATH, \u0447\u0442\u043e\u0431\u044b \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0435 \u0442\u0430\u043a\u0436\u0435 \u0441\u043c\u043e\u0442\u0440\u0435\u043b\u043e \u0438 \u0432 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044e:<\/p>\n<pre><code class=\"bash\">\/Applications\/Xcode.app\/Contents\/Developer\/usr\/bin\/<\/code><\/pre>\n<p>\u0412\u044b\u0437\u043e\u0432\u0435\u043c <em>simctl<\/em> \u0435\u0449\u0435 \u0440\u0430\u0437, \u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f <em>xcrun<\/em>, \u0438 \u0443\u0431\u0435\u0434\u0438\u043c\u0441\u044f, \u0447\u0442\u043e \u0432\u044b\u0437\u043e\u0432 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442:<\/p>\n<pre><code class=\"bash\">xcrun simctl --version @(#)PROGRAM:simctl  PROJECT:CoreSimulator-993.7<\/code><\/pre>\n<p>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f <em>simctl<\/em>, \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0443\u0437\u043d\u0430\u0442\u044c \u043a\u0430\u043a\u0438\u0435 Xcode \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440 \u0440\u0430\u043d\u0442\u0430\u0439\u043c\u044b \u0443 \u043d\u0430\u0441 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u044b \u0438 \u043a\u0430\u043a\u0438\u0435 \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u044b \u0437\u0430 \u043a\u0430\u0436\u0434\u044b\u043c \u0440\u0430\u043d\u0442\u0430\u0439\u043c\u043e\u043c \u0437\u0430\u043a\u0440\u0435\u043f\u043b\u0435\u043d\u044b:<\/p>\n<pre><code class=\"bash\">xcrun simctl list devices  == Devices == -- iOS 16.4 -- -- iOS 17.2 -- -- iOS 17.5 --     iPhone 15 (FDFE4922-31B3-45C2-920E-CB7D157438D8) (Shutdown)      iPhone 15 1 (322438F1-8B66-468E-A1DD-8285BEDB6235) (Shutdown)  -- iOS 18.2 --     iPhone 16 1 (EB373B43-A9D5-4186-9ED3-721FBBB025E6) (Booted)      iPhone 16 Pro (0457CF4E-0D34-4F10-8EE3-C9DE90CDC7F8) (Shutdown)      iPhone 16 (B67A0BE4-83D6-4423-B022-AC4F82F583FD) (Booted) <\/code><\/pre>\n<p>\u0417\u043d\u0430\u044f UUID \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u0430, \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u043e\u043c \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0432\u0441\u0451 \u0442\u043e\u0439 \u0436\u0435 <em>simctl<\/em> \u0443\u0442\u0438\u043b\u0438\u0442\u044b. \u041c\u043e\u0436\u043d\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440, \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u0432\u0435\u0440\u0448\u0430\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u0443 \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u0430, \u043c\u043e\u0436\u043d\u043e \u0443\u0434\u0430\u043b\u0438\u0442\u044c \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440, \u043c\u043e\u0436\u043d\u043e \u0442\u0430\u043a\u0436\u0435 \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043a\u043b\u043e\u043d \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u0430. \u0412\u0441\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0443\u0437\u043d\u0430\u0442\u044c, \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0432 \u043a\u043e\u043c\u0430\u043d\u0434\u0443:<\/p>\n<pre><code class=\"bash\">xcrun simctl help<\/code><\/pre>\n<p>\u0412\u0435\u0440\u043d\u0435\u043c\u0441\u044f \u043a \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0443 \u0441\u0442\u0430\u0442\u044c\u0438. \u0422\u0435\u043f\u0435\u0440\u044c \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f \u0431\u043e\u043b\u0435\u0435 \u043c\u0435\u043d\u0435\u0435 \u043f\u043e\u043d\u044f\u0442\u043d\u043e, \u0447\u0442\u043e \u043d\u0443\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c, \u0447\u0442\u043e\u0431\u044b \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u043e\u043c \u0438\u0437 \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u0430. \u041d\u0443\u0436\u043d\u043e \u043a\u0430\u043a\u0438\u043c-\u0442\u043e \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u0438\u0437 \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u0430 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c bash \u043a\u043e\u043c\u0430\u043d\u0434\u0443 (xcrun simctl &#8230;) \u043d\u0430 \u0445\u043e\u0441\u0442 \u043c\u0430\u0448\u0438\u043d\u0435, \u0442\u043e \u0435\u0441\u0442\u044c \u043d\u0430 MacOS, \u0433\u0434\u0435 \u0437\u0430\u043f\u0443\u0449\u0435\u043d \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440.<\/p>\n<p>\u041d\u043e \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u044e \u043d\u0430\u0447\u0430\u0442\u044c \u0441 \u043f\u0440\u043e\u0441\u0442\u043e\u0433\u043e \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u0432 \u043a\u0430\u043a\u043e\u043c \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0438 \u0437\u0430\u043f\u0443\u0449\u0435\u043d \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440 \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0445\u043e\u0441\u0442 \u043c\u0430\u0448\u0438\u043d\u044b. \u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043f\u0443\u0441\u0442\u043e\u0435 iOS \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0438 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043c \u0435\u0433\u043e \u043d\u0430 iOS \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u0435. \u0412\u0441\u0435 \u043f\u0440\u0438\u043c\u0435\u0440\u044b \u043a\u043e\u0434\u0430 \u0431\u0443\u0434\u0435\u043c \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u0432\u043d\u0443\u0442\u0440\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f iOS \u0441\u0438\u0441\u0442\u0435\u043c\u043e\u0439 \u043f\u0440\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f:<\/p>\n<pre><code class=\"swift\">func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -&gt; Bool { }<\/code><\/pre>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c, \u0447\u0442\u043e \u043d\u0430\u043c \u0432\u044b\u0432\u0435\u0434\u0435\u0442 \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u043e\u0435 iOS API \u0434\u043b\u044f \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438:<\/p>\n<pre><code class=\"swift\">let dir = FileManager.default.temporaryDirectory print(dir)<\/code><\/pre>\n<p>\u0412\u044b\u0434\u0430\u0441\u0442 \u0432\u044b\u0432\u043e\u0434 \u0432 Xcode \u043a\u043e\u043d\u0441\u043e\u043b\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0433\u043e \u0432\u0438\u0434\u0430:<\/p>\n<blockquote>\n<p>file:\/\/\/Users\/user\/Library\/Developer\/CoreSimulator\/Devices\/FDFE4922-31B3-45C2-920E-CB7D157438D8\/data\/Containers\/Data\/Application\/ED9B6B5F-F62D-4452-B72D-A1A3260F19F3\/tmp\/<\/p>\n<\/blockquote>\n<p>\u041c\u044b \u0442\u0430\u043a\u0436\u0435 \u044d\u0442\u0443 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044e \u043c\u043e\u0436\u0435\u043c \u043e\u0442\u043a\u0440\u044b\u0442\u044c \u0438 \u043d\u0430 \u0445\u043e\u0441\u0442 \u043c\u0430\u0448\u0438\u043d\u0435 \u043f\u0440\u043e\u0441\u0442\u043e \u0432 Finder \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438.<\/p>\n<p>\u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u044d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442 &#8212; \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0444\u0430\u0439\u043b \u0432 $HOME\/Downloads \u044e\u0437\u0435\u0440 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438, \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u043f\u0440\u0430\u0432\u0430 \u043d\u0430 \u0437\u0430\u043f\u0438\u0441\u044c. \u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u043f\u0440\u0438\u043c\u0435\u0440:<\/p>\n<pre><code class=\"swift\"> do {     try \"Hello Habr!\".write(to: URL(fileURLWithPath: \"\/Users\/user\/Downloads\/habr-hello.txt\"), atomically: true, encoding: .utf8) } catch {     print(error) }<\/code><\/pre>\n<p>\u0412 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0435 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0443 \u043d\u0430\u0441 \u0432 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 \/Downloads \u0441\u043e\u0437\u0434\u0430\u0441\u0442\u0441\u044f \u0444\u0430\u0439\u043b habr-hello.txt, \u0438\u043d\u044b\u043c\u0438 \u0441\u043b\u043e\u0432\u0430\u043c\u0438 \u043c\u044b \u043c\u043e\u0436\u0435\u043c, \u043a\u0430\u043a \u043c\u0438\u043d\u0438\u043c\u0443\u043c, \u043c\u0430\u043d\u0438\u043f\u0443\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0444\u0430\u0439\u043b\u0430\u043c\u0438 \u043d\u0430 \u0445\u043e\u0441\u0442 \u0441\u0438\u0441\u0442\u0435\u043c\u0435 \u0441 write \u0443\u0440\u043e\u0432\u043d\u0435\u043c \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u0438\u0437 \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u0430.<\/p>\n<p>\u0413\u0434\u0435 \u044d\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u0438\u0433\u043e\u0434\u0438\u0442\u044c\u0441\u044f:<\/p>\n<ol>\n<li>\n<p>\u042d\u0442\u0438\u043c \u0430\u043a\u0442\u0438\u0432\u043d\u043e \u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f Snapshot Testing \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438. \u041e\u043d\u0438 \u0434\u0435\u043b\u0430\u044e\u0442 \u0441\u043d\u0430\u043f\u0448\u043e\u0442 \u044d\u043a\u0440\u0430\u043d\u0430 \u0438\u043b\u0438 \u0432\u044c\u044e\u0448\u043a\u0438 \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u043f\u0440\u043e\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u044f \u0442\u0435\u0441\u0442\u0430 \u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u044e\u0442 \u0435\u0433\u043e \u043d\u0430 \u0434\u0438\u0441\u043a \u0445\u043e\u0441\u0442 \u043c\u0430\u0448\u0438\u043d\u044b \u0440\u044f\u0434\u043e\u043c \u0441 \u0444\u0430\u0439\u043b\u043e\u043c \u0442\u0435\u0441\u0442\u043e\u0432. \u0412 \u043a\u043e\u0434\u0435 \u044d\u0442\u043e \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442, \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e, \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<\/p>\n<\/li>\n<\/ol>\n<pre><code class=\"swift\">func testSnapshotScreen() throws {     let view = UIView()     let image = UIGraphicsImageRenderer(size: view.bounds.size).image { _ in         view.drawHierarchy(in: view.bounds, afterScreenUpdates: true)     }     let jpeg = image.jpegData(compressionQuality: 1)!     let url = URL(fileURLWithPath: #filePath)         .deletingLastPathComponent()         .appendingPathComponent(#function.replacingOccurrences(of: \"()\", with: \"\"))         .appendingPathExtension(for: .jpeg)     try jpeg.write(to: url) }<\/code><\/pre>\n<p>\u041f\u043e\u0441\u043b\u0435 \u043f\u0440\u043e\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u044f \u0442\u0435\u0441\u0442\u0430, \u0440\u044f\u0434\u043e\u043c \u0441 Swift\/ObjC \u0444\u0430\u0439\u043b\u043e\u043c \u0441 \u0442\u0435\u0441\u0442\u043e\u043c, \u043f\u043e\u044f\u0432\u0438\u0442\u0441\u044f \u0444\u0430\u0439\u043b \u0441\u043d\u0430\u043f\u0448\u043e\u0442\u0430 <em>testSnapshotScreen.jpeg<\/em>.<\/p>\n<ol start=\"2\">\n<li>\n<p>\u0415\u0441\u043b\u0438 \u0432\u044b \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442\u0435 \u0441 \u0431\u0430\u0437\u043e\u0439 \u0434\u0430\u043d\u043d\u044b\u0445, \u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0444\u0430\u0439\u043b \u0431\u0430\u0437\u044b \u0434\u0430\u043d\u043d\u044b\u0445 \u0447\u0435\u0440\u0435\u0437 MacOS Desktop \u043f\u043e\u043b\u043d\u043e\u0446\u0435\u043d\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0441 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u043c\u0438 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u0438 \u0437\u0430\u0442\u0435\u043c \u044d\u0442\u0443 \u0431\u0430\u0437\u0443 \u0434\u0430\u043d\u043d\u044b\u0445 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0442\u044c \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u0437\u0430\u043f\u0443\u0449\u0435\u043d\u043d\u043e\u0435 \u043d\u0430 \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u0435.<\/p>\n<\/li>\n<\/ol>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0441\u043d\u043e\u0432\u0430 \u043f\u0435\u0440\u0435\u0439\u0434\u0435\u043c \u043a \u0441\u0443\u0442\u0438 \u0441\u0430\u043c\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438.<\/p>\n<p>\u0427\u0442\u043e\u0431\u044b \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c <em>bash<\/em> \u043a\u043e\u043c\u0430\u043d\u0434\u0443 \u0438\u0437 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <em>posix<\/em> \u0444\u0443\u043d\u043a\u0446\u0438\u044e <em>system()<\/em>, \u043d\u043e, \u043a \u0441\u043e\u0436\u0430\u043b\u0435\u043d\u0438\u044e, \u043e\u043d\u0430 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0430 \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f MacOS SDK, \u043e \u0447\u0435\u043c \u043d\u0430\u043c \u0433\u043e\u0432\u043e\u0440\u044f\u0442 \u043c\u0430\u043a\u0440\u043e\u0441\u044b \u0432\u043e\u043a\u0440\u0443\u0433 \u043d\u0435\u0435:<\/p>\n<pre><code class=\"cpp\">__swift_unavailable(\"Use posix_spawn APIs or NSTask instead. (On iOS, process spawning is unavailable.)\") __API_AVAILABLE(macos(10.0)) __IOS_PROHIBITED __WATCHOS_PROHIBITED __TVOS_PROHIBITED int system(const char * ) __DARWIN_ALIAS_C(system);<\/code><\/pre>\n<p>\u0411\u043e\u043b\u0435\u0435 \u0442\u043e\u0433\u043e, \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0432 \u043c\u0430\u043a\u0440\u043e\u0441\u0435 \u043d\u0430\u043c \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u0435\u0442 \u0432\u043c\u0435\u0441\u0442\u043e <em>system()<\/em> \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0438\u043b\u0438 <em>posix_spawn()<\/em> \u0438\u0437 Darwin SDK, \u0438\u043b\u0438, \u0437\u043d\u0430\u043a\u043e\u043c\u0443\u044e \u043c\u043d\u043e\u0433\u0438\u043c \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430\u043c, <em>NSTask<\/em> (\u043a\u043b\u0430\u0441\u0441 <em>Process<\/em> \u0432 Swift) \u0438\u0437 \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u043e\u0439 Foundation \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438. \u0415\u0441\u043b\u0438 \u0437\u0430\u0433\u043b\u044f\u043d\u0443\u0442\u044c \u0432 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 <em>NSTask<\/em>, \u0442\u043e \u044d\u0442\u043e\u0442 \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u044b\u0439 \u043a\u043b\u0430\u0441\u0441, \u043a\u0430\u043a \u0438 <em>system()<\/em> \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d, \u043a \u0441\u043e\u0436\u0430\u043b\u0435\u043d\u0438\u044e, \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0430 MacOS. \u0422\u0435\u043f\u0435\u0440\u044c \u0443 \u043d\u0430\u0441 \u0432\u0441\u044f \u043d\u0430\u0434\u0435\u0436\u0434\u0430  \u043d\u0430 <em>posix_spawn()<\/em>, \u043a\u043e\u0442\u043e\u0440\u0430\u044f, \u043a \u043d\u0430\u0448\u0435\u0439 \u0443\u0434\u0430\u0447\u0435, \u0435\u0441\u0442\u044c \u0432 iOS SDK, \u043e \u0447\u0435\u043c \u0438 \u0433\u043e\u0432\u043e\u0440\u044f\u0442 \u043c\u0430\u043a\u0440\u043e\u0441\u044b \u0432 \u0438\u0441\u0445\u043e\u0434\u043d\u0438\u043a\u0430\u0445 \u044d\u0442\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 <a href=\"https:\/\/github.com\/apple\/darwin-xnu\/blob\/main\/libsyscall\/wrappers\/spawn\/spawn.h\" rel=\"noopener noreferrer nofollow\">https:\/\/github.com\/apple\/darwin-xnu\/blob\/main\/libsyscall\/wrappers\/spawn\/spawn.h<\/a> :<\/p>\n<pre><code class=\"cpp\">int posix_spawn(pid_t * __restrict, const char * __restrict,     const posix_spawn_file_actions_t *,     const posix_spawnattr_t * __restrict,     char *const __argv[__restrict],     char *const __envp[__restrict]) __API_AVAILABLE(macos(10.5), ios(2.0)) __SPI_AVAILABLE(watchos(2.0), tvos(9.0), bridgeos(1.0));<\/code><\/pre>\n<ul>\n<li>\n<p>\u0414\u043b\u044f \u043f\u0440\u043e\u0434\u0432\u0438\u043d\u0443\u0442\u044b\u0445 \u0445\u0430\u0446\u043a\u0435\u0440\u043e\u0432, \u0435\u0441\u0442\u044c \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f, \u0447\u0442\u043e <em>NSTask<\/em> \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044f iOS SDK, \u043f\u0440\u043e\u0441\u0442\u043e Apple \u0443\u0431\u0440\u0430\u043b \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e\u0431 \u044d\u0442\u043e\u043c \u043a\u043b\u0430\u0441\u0441\u0435 \u0438\u0437 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u0447\u043d\u044b\u0445 \u0444\u0430\u0439\u043b\u043e\u0432, \u0447\u0442\u043e\u0431\u044b \u0438\u043c \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043d\u0443\u0436\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u044d\u0442\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430 \u0432 \u0432\u0430\u0448 \u043f\u0440\u043e\u0435\u043a\u0442 (\u043c\u043e\u0436\u043d\u043e \u0441\u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441 MacOS Foundation SDK \u0438 \u0447\u0443\u0442\u044c \u043f\u043e\u0434\u043f\u0440\u0430\u0432\u0438\u0442\u044c).<\/p>\n<\/li>\n<\/ul>\n<p>\u041f\u0440\u043e\u0434\u043e\u043b\u0436\u0430\u0435\u043c. \u0427\u0435\u043c \u0434\u043e\u043b\u044c\u0448\u0435 \u044f \u0441\u043c\u043e\u0442\u0440\u044e \u043d\u0430 \u044d\u0442\u0443 \u0444\u0443\u043d\u043a\u0446\u0438\u044e, \u0442\u0435\u043c \u0431\u043e\u043b\u044c\u0448\u0435 \u043f\u043e\u043d\u0438\u043c\u0430\u044e, \u0447\u0442\u043e \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u043f\u043e\u043d\u0438\u043c\u0430\u044e. \u0415\u0441\u043b\u0438 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u043d\u0430 \u0441 \u043a\u043e\u043d\u0432\u0435\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0435 \u0432 Swift \u044f\u0437\u044b\u043a API \u044d\u0442\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u0442\u043e \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f \u0435\u0449\u0435 \u043d\u0435\u043f\u043e\u043d\u044f\u0442\u043d\u0435\u0435:<\/p>\n<pre><code class=\"swift\">public func posix_spawn(     _: UnsafeMutablePointer&lt;pid_t&gt;!,     _: UnsafePointer&lt;CChar&gt;!,      _: UnsafePointer&lt;posix_spawn_file_actions_t?&gt;!,      _: UnsafePointer&lt;posix_spawnattr_t?&gt;!,      _ __argv: UnsafePointer&lt;UnsafeMutablePointer&lt;CChar&gt;?&gt;!,      _ __envp: UnsafePointer&lt;UnsafeMutablePointer&lt;CChar&gt;?&gt;!     ) -&gt; Int32<\/code><\/pre>\n<p>\u0412 \u043e\u0431\u0449\u0435\u043c, \u0438\u0434\u0435\u043c \u0441\u0430\u043c\u044b\u043c \u043f\u0440\u043e\u0441\u0442\u044b\u043c \u0441\u043f\u043e\u0441\u043e\u0431\u043e\u043c, \u0438\u0434\u0435\u043c \u043d\u0430 Github \u0438 \u043f\u044b\u0442\u0430\u0435\u043c\u0441\u044f \u043d\u0430\u0439\u0442\u0438 \u043f\u0440\u0438\u043c\u0435\u0440\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u044d\u0442\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u043d\u0430 Swift \u044f\u0437\u044b\u043a\u0435 \u0438 \u0431\u0435\u0440\u0435\u043c \u043f\u0435\u0440\u0432\u044b\u0439 \u043f\u043e\u043f\u0430\u0432\u0448\u0438\u0439\u0441\u044f \u0440\u0430\u0431\u043e\u0447\u0438\u0439 \u043f\u0440\u0438\u043c\u0435\u0440. \u0423 \u043c\u0435\u043d\u044f \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0441\u044f \u0442\u0430\u043a\u043e\u0439 \u043a\u043e\u0434:<\/p>\n<pre><code class=\"swift\">struct CliTool {      static func runCommand(_ command: String) throws -&gt; Int32 {         var pid: pid_t = 0         var status = Int32(0)         let args = [\"sh\", \"-c\", command]         let envs = [String]()         try withCStrings(args) { cArgs in             try withCStrings(envs) { cEnvs in                 status = posix_spawn(&amp;pid, \"\/bin\/sh\", nil, nil, cArgs, cEnvs)                 if status == 0 {                     if waitpid(pid, &amp;status, 0) == -1 {                         throw RunCommandError.WaitPIDError                     }                 } else {                     throw RunCommandError.POSIXSpawnError(status)                 }             }         }         return status     }      enum RunCommandError: Error {         case WaitPIDError         case POSIXSpawnError(Int32)     } }<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u0443\u0437\u043d\u0430\u0442\u044c \u0432\u0435\u0440\u0441\u0438\u044e Xcode \u043d\u0430 \u0445\u043e\u0441\u0442 \u043c\u0430\u0448\u0438\u043d\u0435:<\/p>\n<pre><code class=\"swift\">\/\/ \u0412\u0441\u0435\u0433\u0434\u0430 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c \u043d\u0430 \u0444\u043e\u043d\u043e\u0432\u043e\u043c \u043f\u043e\u0442\u043e\u043a\u0435 DispatchQueue.global().async {     do {         try CliTool.runCommand(\"xcodebuild -version\")     } catch {         print(error)     } }<\/code><\/pre>\n<p>\u0418 \u0432 \u043a\u043e\u043d\u0441\u043e\u043b\u0438 Xcode \u0432\u0438\u0434\u0438\u043c \u0437\u0430\u0432\u0435\u0442\u043d\u044b\u0435:<\/p>\n<blockquote>\n<p>Xcode 15.4<br \/>Build version 15F31d<\/p>\n<\/blockquote>\n<p>\u041f\u0440\u043e\u0432\u0435\u0440\u0438\u043c, \u043a\u0430\u043a\u0438\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b:<\/p>\n<pre><code class=\"swift\">try CliTool.runCommand(\"export\")<\/code><\/pre>\n<p>\u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c:<\/p>\n<pre><code class=\"bash\">export OLDPWD export PWD=\"\/\" export SHLVL=\"1\"<\/code><\/pre>\n<p>\u041f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u0443\u0437\u043d\u0430\u0442\u044c \u0441\u043f\u0438\u0441\u043e\u043a \u0444\u0430\u0439\u043b\u043e\u0432 \u0432 $HOME \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438:<\/p>\n<pre><code class=\"swift\">try CliTool.runCommand(\"ls $HOME\")<\/code><\/pre>\n<p>\u0418 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0441\u043f\u0438\u0441\u043e\u043a \u0438\u0437 \u043a\u043e\u0440\u043d\u0435\u0432\u043e\u0439 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 MacOS, \u044d\u0442\u043e \u043d\u0435 \u0442\u043e \u0447\u0442\u043e \u043c\u044b \u043e\u0436\u0438\u0434\u0430\u0435\u043c. \u041d\u0443\u0436\u043d\u043e \u0432\u044b\u0441\u0442\u0430\u0432\u0438\u0442\u044c HOME \u043d\u0430\u0448\u0435\u0433\u043e MacOS \u044e\u0437\u0435\u0440\u0430 \u043f\u0440\u0435\u0436\u0434\u0435 \u0447\u0435\u043c \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u043a\u043e\u043c\u0430\u043d\u0434\u0443, \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u043f\u0440\u0430\u0432\u0438\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u044e <em>runCommand<\/em>, \u0433\u0434\u0435 \u0432\u044b\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f:<\/p>\n<pre><code class=\"swift\">let iOSUserENV = [     \"export LANG=en_US.UTF-8\",     \"export LC_ALL=en_US.UTF-8\",     \"export LC_CTYPE=UTF-8\",     \"export USER=\\(FileManager.default.temporaryDirectory.pathComponents[2])\", \/\/ \u044e\u0437\u0435\u0440\u0430 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u043c \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0438     \"export HOME=\/Users\/$USER\" ].joined(separator: \";\") let args = [\"sh\", \"-c\", \"\\(iOSUserENV);\\(command)\"]<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0435\u0441\u043b\u0438 \u043f\u043e\u0432\u0442\u043e\u0440\u0438\u0442\u044c \u043a\u043e\u043c\u0430\u043d\u0434\u0443, \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u0436\u0435\u043b\u0430\u0435\u043c\u044b\u0439 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442.<\/p>\n<p>\u0415\u0449\u0435 \u044d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442, \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0441\u043a\u0440\u0438\u043f \u0438 \u0435\u0433\u043e \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c:<\/p>\n<pre><code class=\"swift\">try CliTool.runCommand(\"cd $HOME\/Downloads\/;echo date &gt; 123.sh;chmod +x .\/123.sh;.\/123.sh\")<\/code><\/pre>\n<p>\u041e\u0431\u043d\u0430\u0440\u0443\u0436\u0438\u0432\u0430\u0435\u043c, \u0447\u0442\u043e \u0445\u043e\u0441\u0442 \u043c\u0430\u0448\u0438\u043d\u0430 \u043d\u0430\u043c \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0434\u0435\u043b\u0430\u0442\u044c \u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0432\u0441\u0451 \u0447\u0442\u043e \u0443\u0433\u043e\u0434\u043d\u043e \u0433\u0434\u0435 \u043d\u0435 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f <em>root<\/em> \u043f\u0430\u0440\u043e\u043b\u044c \u0438\u043b\u0438 \u043a\u0430\u043a\u0438\u0445 \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u0447\u043d\u044b\u0445 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u0434\u043b\u044f \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f.<\/p>\n<p>\u0412\u0435\u0440\u043d\u0435\u043c\u0441\u044f \u0441\u043d\u043e\u0432\u0430 \u043a \u0442\u0435\u043c\u0435 \u0441\u0442\u0430\u0442\u044c\u0438 \u0438, \u043d\u0430\u043a\u043e\u043d\u0435\u0446, \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u043a\u043e\u043c\u0430\u043d\u0434\u0443 \u043d\u0430\u0448\u0435\u043c\u0443 \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u0443. \u041d\u043e, \u0441\u043d\u0430\u0447\u0430\u043b\u0430, \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u043c \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0430 \u043b\u0438 \u043d\u0430\u043c <em>simctl<\/em> \u0443\u0442\u0438\u043b\u0438\u0442\u0430 \u0438\u0437 \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u0430. \u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c:<\/p>\n<pre><code class=\"swift\">try CliTool.runCommand(\"xcrun simctl --version\")<\/code><\/pre>\n<p>\u0438 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c:<\/p>\n<pre><code class=\"bash\">@(#)PROGRAM:simctl  PROJECT:CoreSimulator-993.7<\/code><\/pre>\n<p>\u0417\u043d\u0430\u0447\u0438\u0442 \u043d\u0430\u043c \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0430 <em>simctl<\/em>. \u0418 \u0442\u0435\u043f\u0435\u0440\u044c \u043f\u0440\u043e\u0431\u0443\u0435\u043c \u0434\u043e\u043b\u0433\u043e\u0436\u0434\u0430\u043d\u043d\u044b\u0439 \u0437\u0430\u043f\u0443\u0441\u043a \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u0430 \u0438\u0437 \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u0430:<\/p>\n<pre><code class=\"swift\">try CliTool.runCommand(\"xcrun simctl boot 322438F1-8B66-468E-A1DD-8285BEDB6235\")<\/code><\/pre>\n<p>\u0438, \u043a \u0441\u043e\u0436\u0430\u043b\u0435\u043d\u0438\u044e, \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u043e\u0448\u0438\u0431\u043a\u0443:<\/p>\n<blockquote>\n<p>simctl[16681:584185] Error Domain=NSPOSIXErrorDomain Code=61 &#171;Connection refused&#187; UserInfo={NSLocalizedDescription=Unable to lookup com.apple.CoreSimulator.CoreSimulatorService (993.7) in the bootstrap.  This can happen if running with a sandbox profile.  When running with a sandbox profile, \/Library\/Developer\/PrivateFrameworks\/CoreSimulator.framework\/XPCServices\/com.apple.CoreSimulator.CoreSimulatorService.xpc must be owned by root, not group writable, and not world writable.  See . isXBSChroot(): NO, XBS_IS_CHROOTED: (null)}<\/p>\n<\/blockquote>\n<p>\u041f\u043e \u0442\u0435\u043a\u0441\u0442\u0443 \u043e\u0448\u0438\u0431\u043a\u0438 \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u043f\u043e\u043d\u044f\u0442\u043d\u043e, \u0447\u0442\u043e \u043d\u0430\u0448 \u044e\u0437\u0435\u0440 <em>bash<\/em> \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u043d\u0435 \u0441\u043e\u0432\u0441\u0435\u043c \u044e\u0437\u0435\u0440 \u0445\u043e\u0441\u0442 \u043c\u0430\u0448\u0438\u043d\u044b \u0438, \u043a \u0442\u043e\u043c\u0443 \u0436\u0435, \u0437\u0430\u043f\u0443\u0449\u0435\u043d \u0432 \u0440\u0435\u0436\u0438\u043c\u0435 \u043f\u0435\u0441\u043e\u0447\u043d\u0438\u0446\u044b. <em>whoami<\/em> \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442, \u0447\u0442\u043e \u043c\u044b \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u043e\u0442 501 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f, \u0442\u0430\u043a \u0436\u0435 \u043e\u043d \u043d\u0435 \u0437\u043d\u0430\u0435\u0442 \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0438 \u043e \u043d\u0430\u0448\u0435\u043c \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u043c \u0445\u043e\u0441\u0442 \u043c\u0430\u0448\u0438\u043d\u044b \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435, \u043d\u0438 \u043e <em>root<\/em> \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435. \u041a\u043e\u0433\u0434\u0430 \u044f \u043f\u044b\u0442\u0430\u043b\u0441\u044f \u043f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u044e\u0437\u0435\u0440\u0430, \u0442\u043e \u043f\u043e\u043b\u0443\u0447\u0430\u043b \u043e\u0448\u0438\u0431\u043a\u0443:<\/p>\n<pre><code class=\"bash\">sudo: you do not exist in the passwd database<\/code><\/pre>\n<p>\u041a \u0441\u043e\u0436\u0430\u043b\u0435\u043d\u0438\u044e, \u043d\u0430 \u0434\u0430\u043d\u043d\u043e\u043c \u044d\u0442\u0430\u043f\u0435 \u043c\u044b \u0437\u0430\u0448\u043b\u0438 \u0432 \u0442\u0443\u043f\u0438\u043a, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u043d\u0430\u043c \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043f\u0440\u0430\u0432, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u0434\u0430\u0432\u0430\u0442\u044c \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u0443 \u0438\u0437 \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u0430. \u041d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u043a\u0430\u043a-\u0442\u043e \u0440\u0430\u0441\u0448\u0438\u0440\u0438\u0442\u044c \u043f\u0440\u0430\u0432\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0438\u043b\u0438 \u043a\u0430\u043a\u0438\u043c-\u0442\u043e \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u043f\u0440\u043e\u043a\u0438\u043d\u0443\u0442\u044c \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u043c\u0443 \u044e\u0437\u0435\u0440\u0443 \u043d\u0430\u0448\u0435\u0439 \u0445\u043e\u0441\u0442 \u043c\u0430\u0448\u0438\u043d\u044b. \u0418 \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u043f\u043e\u0434\u0443\u043c\u0430\u0432, \u044f \u0440\u0435\u0448\u0438\u043b \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u0439 \u0441\u0435\u0440\u0432\u0435\u0440 \u043d\u0430 \u0445\u043e\u0441\u0442 \u043c\u0430\u0448\u0438\u043d\u0435, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u0435\u0440\u0435\u043d\u0430\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0432 <em>sh<\/em>. \u0414\u043b\u044f \u043f\u0440\u043e\u0441\u0442\u043e\u0442\u044b \u044f \u0432\u0437\u044f\u043b \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0441\u0435\u0440\u0432\u0435\u0440 \u043d\u0430 <em>ruby<\/em>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0443\u0436\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b \u0432 \u0434\u0440\u0443\u0433\u0438\u0445 \u044d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u0430\u0445:<\/p>\n<details class=\"spoiler\">\n<summary>\u041a\u043e\u0434 \u0441\u0435\u0440\u0432\u0435\u0440\u0430<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"ruby\"># file proxy-server.rb  require 'webrick'  class MyServlet &lt; WEBrick::HTTPServlet::AbstractServlet   def do_GET (request, response)     response.body = 'OK'     response.status = 200      case request.path       when '\/shutdown'         Thread.new do           @server.shutdown         end       else         command = request.query[\"command\"]         if command != nil           Thread.new do             puts \"system(#{command})\"             puts system(*%W[#{command}])           end         end     end   end end  server = WEBrick::HTTPServer.new(:Port =&gt; 59123) server.mount '\/', MyServlet  trap('INT') { server.shutdown } server.start<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u0441\u0435\u0440\u0432\u0435\u0440 \u043a\u043e\u043c\u0430\u043d\u0434\u043e\u0439:<\/p>\n<pre><code class=\"bash\">ruby proxy-server.rb [2024-12-23 11:31:13] INFO  WEBrick 1.7.0 [2024-12-23 11:31:13] INFO  ruby 3.1.3 (2022-11-24) [arm64-darwin21] [2024-12-23 11:31:13] INFO  WEBrick::HTTPServer#start: pid=41537 port=59123<\/code><\/pre>\n<p>\u0418\u0437 \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u0430 \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c \u0441\u0435\u0440\u0432\u0435\u0440 \u0431\u0443\u0434\u0435\u043c \u0447\u0435\u0440\u0435\u0437 <em>curl<\/em> \u0443\u0442\u0438\u043b\u0438\u0442\u0443 \u0445\u043e\u0441\u0442 \u043c\u0430\u0448\u0438\u043d\u044b. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043d\u043e\u0432\u0443\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u044e:<\/p>\n<pre><code class=\"swift\">static func runCurl(_ command: String, port: String = \"59123\") throws -&gt; Int32 {     var path = \"http:\/\/localhost:\\(port)\/?command=\\(command)\"     path = path.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) ?? path     path = path.replacingOccurrences(of: \";\", with: \"%3B\")     return try Self.runCommand(\"curl \\(path)\") }<\/code><\/pre>\n<p>\u041f\u0440\u043e\u0431\u0443\u0435\u043c \u0435\u0449\u0435 \u0440\u0430\u0437 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440 \u0438\u0437 \u0434\u0440\u0443\u0433\u043e\u0433\u043e \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u0430:<\/p>\n<pre><code class=\"swift\">try CliTool.runCurl(\"xcrun simctl boot 322438F1-8B66-468E-A1DD-8285BEDB6235\")<\/code><\/pre>\n<p>\u0412 \u043b\u043e\u0433\u0430\u0445 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0432\u0438\u0434\u0438\u043c, \u0447\u0442\u043e \u043a\u043e\u043c\u0430\u043d\u0434\u0430 \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u043b\u0430\u0441\u044c \u043d\u0430 \u0445\u043e\u0441\u0442 \u043c\u0430\u0448\u0438\u043d\u0435:<\/p>\n<pre><code class=\"bash\">[2024-12-14 19:34:28] INFO  WEBrick 1.7.0 [2024-12-14 19:34:28] INFO  ruby 3.1.3 (2022-11-24) [arm64-darwin21] [2024-12-14 19:34:28] INFO  WEBrick::HTTPServer#start: pid=17662 port=59123 ::1 - - [14\/Dec\/2024:19:37:21 +07] \"GET \/?command=xcrun%20simctl%20boot%20322438F1-8B66-468E-A1DD-8285BEDB6235 HTTP\/1.1\" 200 2 - -&gt; \/?command=xcrun%20simctl%20boot%20322438F1-8B66-468E-A1DD-8285BEDB6235 system(xcrun simctl boot 322438F1-8B66-468E-A1DD-8285BEDB6235)<\/code><\/pre>\n<p>\u0438 \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0438\u0432\u0430\u0435\u043c, \u0447\u0442\u043e \u043d\u043e\u0432\u044b\u0439 \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043b\u0441\u044f.<\/p>\n<h2>\u0418\u0442\u043e\u0433\u0438<\/h2>\n<p>\u0412\u043d\u0438\u043c\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u0447\u0438\u0442\u0430\u0442\u0435\u043b\u044c \u043c\u043e\u0436\u0435\u0442 \u0441\u043f\u0440\u043e\u0441\u0438\u0442\u044c, \u0430 \u0437\u0430\u0447\u0435\u043c \u043d\u0430\u043c \u044d\u0442\u043e \u0432\u043e\u043e\u0431\u0449\u0435 \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u044c\u0441\u044f, \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u043e\u043c \u0438\u0437 \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u0430 ? \u042f \u043f\u0440\u0438\u0434\u0443\u043c\u0430\u043b \u0442\u0435\u043e\u0440\u0435\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0441\u043f\u0438\u0441\u043e\u043a, \u0433\u0434\u0435 \u043d\u0430\u043c \u044d\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u0438\u0433\u043e\u0434\u0438\u0442\u044c\u0441\u044f:<\/p>\n<ol>\n<li>\n<p>\u0423\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u043e\u043c \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u0442\u0435\u0441\u0442\u043e\u0432<\/p>\n<\/li>\n<\/ol>\n<p>\u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0432\u043e \u0432\u0440\u0435\u043c\u044f UI \u0442\u0435\u0441\u0442\u0430 \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440 \u0437\u0430\u0432\u0438\u0441 (\u0433\u043b\u0430\u0432\u043d\u044b\u0439 \u043f\u043e\u0442\u043e\u043a \u0437\u0430\u043b\u043e\u0447\u0438\u043b\u0441\u044f) \u0438\u043b\u0438 \u043a\u0430\u043a\u0438\u0435-\u0442\u043e \u0434\u0440\u0443\u0433\u0438\u0435 \u0440\u0435\u0434\u043a\u0438\u0435 \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u044b\u0435 \u043f\u0440\u0438\u0447\u0438\u043d\u044b \u0438\u0437-\u0437\u0430 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440 \u0441\u0442\u0430\u043b \u0432\u0432\u0435\u0441\u0442\u0438 \u0441\u0435\u0431\u044f \u043d\u0435\u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e, \u043c\u043e\u0436\u043d\u043e \u0435\u0433\u043e \u043f\u043e\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u0442\u044c \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u043f\u0440\u044f\u043c \u0438\u0437 \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u0430 (\u0434\u0430, \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0441\u0430\u043c\u043e\u0433\u043e \u0441\u0435\u0431\u044f \u0438 \u044d\u0442\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442).<\/p>\n<ol start=\"2\">\n<li>\n<p>\u0421\u0438\u043c\u0443\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c app \u043b\u0438\u043d\u043a \u0432\u043e \u0432\u0440\u0435\u043c\u044f UI \u0442\u0435\u0441\u0442\u0430<\/p>\n<\/li>\n<\/ol>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440:<\/p>\n<pre><code class=\"swift\">func testAppLinkFlow() throws {     app.launch()     let simulatorUUID = FileManager.default.temporaryDirectory.pathComponents[7]     try CliTool.runCurl(\"xcrun simctl openurl \\(simulatorUUID) app-scheme:\/\/path\/to\")     verifyUI() }<\/code><\/pre>\n<ol start=\"3\">\n<li>\n<p>\u041f\u043e\u0441\u043b\u0430\u0442\u044c \u043f\u0443\u0448 \u0432\u043e \u0432\u0440\u0435\u043c\u044f UI \u0442\u0435\u0441\u0442\u0430<\/p>\n<\/li>\n<\/ol>\n<pre><code class=\"swift\">func testPushFlow() throws {     app.launch()     let simulatorUUID = FileManager.default.temporaryDirectory.pathComponents[7]     try CliTool.runCurl(\"xcrun simctl push \\(simulatorUUID) com.my.app - &lt;&lt;&lt; \\\"{\\\\\\\"aps\\\\\\\":{\\\\\\\"alert\\\\\\\":{\\\\\\\"body\\\\\\\":\\\\\\\"Body Title\\\\\\\",\\\\\\\"title\\\\\\\":\\\\\\\"Alert Title\\\\\\\"}}}\\\"\")     tapPush()     verifyUI() }<\/code><\/pre>\n<ol start=\"4\">\n<li>\n<p>\u0418\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044f \u0441 \u0434\u0440\u0443\u0433\u0438\u043c\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u043c\u0438<\/p>\n<\/li>\n<\/ol>\n<p>\u0412\u043e \u0432\u0440\u0435\u043c\u044f \u0442\u0435\u0441\u0442\u0430 \u0443\u0434\u0430\u043b\u0438\u0442\u044c\/\u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u0438.<\/p>\n<h2>\u041c\u0438\u043d\u0438 \u0434\u0435\u043c\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435<\/h2>\n<details class=\"spoiler\">\n<summary>\u0412\u0438\u0434\u0435\u043e<\/summary>\n<div class=\"spoiler__content\">\n<div class=\"tm-iframe_temp\" data-src=\"https:\/\/embedd.srv.habr.com\/iframe\/67690aa4ca01a46b4ccc8672\" data-style=\"\" id=\"67690aa4ca01a46b4ccc8672\" width=\"\"><\/div>\n<\/p>\n<\/div>\n<\/details>\n<hr\/>\n<p>\u0421\u043f\u0430\u0441\u0438\u0431\u043e, \u0447\u0442\u043e \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u043b\u0438.<\/p>\n<\/p>\n<\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/868846\/\"> https:\/\/habr.com\/ru\/articles\/868846\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u041a\u0430\u043a \u043c\u044b \u0437\u043d\u0430\u0435\u043c, \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u043e\u043c \u043c\u043e\u0436\u043d\u043e \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0438\u0442\u044c \u0438\u0437 \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u043b\u0430, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f <em>simctl<\/em> \u0443\u0442\u0438\u043b\u0438\u0442\u0443, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0432\u043c\u0435\u0441\u0442\u0435 \u0441 Xcode \u0438 \u0440\u0430\u0441\u043f\u043e\u043b\u0430\u0433\u0430\u0435\u0442\u0441\u044f \u043f\u043e \u043f\u0443\u0442\u0438:<\/p>\n<pre><code class=\"bash\">Xcode.app\/Contents\/Developer\/usr\/bin\/simctl<\/code><\/pre>\n<p>\u0415\u0441\u043b\u0438 \u0438\u0437 \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u043b\u0430 \u0432\u044b\u0437\u0432\u0430\u0442\u044c <em>simctl<\/em>, \u0442\u043e, \u0441\u043a\u043e\u0440\u0435\u0435 \u0432\u0441\u0435\u0433\u043e, \u0432\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u0435 \u043e\u0448\u0438\u0431\u043a\u0443:<\/p>\n<pre><code class=\"bash\">\"command not found: simctl\"<\/code><\/pre>\n<p>\u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c proxy \u0443\u0442\u0438\u043b\u0438\u0442\u0443 <em>xcrun<\/em>, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u0435\u0440\u0435\u043d\u0430\u043f\u0440\u0430\u0432\u0438\u0442 \u043e\u0431\u0440\u0430\u0449\u0435\u043d\u0438\u0435 \u043a <em>simctl<\/em>, \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u0443\u044e \u0432 Xcode \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e (\u0447\u0442\u043e\u0431\u044b \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c Xcode \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e, \u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c xcode-select \u0443\u0442\u0438\u043b\u0438\u0442\u0443 \u0441 \u043f\u0440\u0430\u0432\u0430\u043c\u0438 root) \u0438\u043b\u0438 \u0436\u0435 \u043c\u043e\u0436\u043d\u043e \u0432 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f \u0440\u0430\u0441\u0448\u0438\u0440\u0438\u0442\u044c PATH, \u0447\u0442\u043e\u0431\u044b \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0435 \u0442\u0430\u043a\u0436\u0435 \u0441\u043c\u043e\u0442\u0440\u0435\u043b\u043e \u0438 \u0432 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044e:<\/p>\n<pre><code class=\"bash\">\/Applications\/Xcode.app\/Contents\/Developer\/usr\/bin\/<\/code><\/pre>\n<p>\u0412\u044b\u0437\u043e\u0432\u0435\u043c <em>simctl<\/em> \u0435\u0449\u0435 \u0440\u0430\u0437, \u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f <em>xcrun<\/em>, \u0438 \u0443\u0431\u0435\u0434\u0438\u043c\u0441\u044f, \u0447\u0442\u043e \u0432\u044b\u0437\u043e\u0432 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442:<\/p>\n<pre><code class=\"bash\">xcrun simctl --version @(#)PROGRAM:simctl  PROJECT:CoreSimulator-993.7<\/code><\/pre>\n<p>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f <em>simctl<\/em>, \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0443\u0437\u043d\u0430\u0442\u044c \u043a\u0430\u043a\u0438\u0435 Xcode \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440 \u0440\u0430\u043d\u0442\u0430\u0439\u043c\u044b \u0443 \u043d\u0430\u0441 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u044b \u0438 \u043a\u0430\u043a\u0438\u0435 \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u044b \u0437\u0430 \u043a\u0430\u0436\u0434\u044b\u043c \u0440\u0430\u043d\u0442\u0430\u0439\u043c\u043e\u043c \u0437\u0430\u043a\u0440\u0435\u043f\u043b\u0435\u043d\u044b:<\/p>\n<pre><code class=\"bash\">xcrun simctl list devices  == Devices == -- iOS 16.4 -- -- iOS 17.2 -- -- iOS 17.5 --     iPhone 15 (FDFE4922-31B3-45C2-920E-CB7D157438D8) (Shutdown)      iPhone 15 1 (322438F1-8B66-468E-A1DD-8285BEDB6235) (Shutdown)  -- iOS 18.2 --     iPhone 16 1 (EB373B43-A9D5-4186-9ED3-721FBBB025E6) (Booted)      iPhone 16 Pro (0457CF4E-0D34-4F10-8EE3-C9DE90CDC7F8) (Shutdown)      iPhone 16 (B67A0BE4-83D6-4423-B022-AC4F82F583FD) (Booted) <\/code><\/pre>\n<p>\u0417\u043d\u0430\u044f UUID \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u0430, \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u043e\u043c \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0432\u0441\u0451 \u0442\u043e\u0439 \u0436\u0435 <em>simctl<\/em> \u0443\u0442\u0438\u043b\u0438\u0442\u044b. \u041c\u043e\u0436\u043d\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440, \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u0432\u0435\u0440\u0448\u0430\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u0443 \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u0430, \u043c\u043e\u0436\u043d\u043e \u0443\u0434\u0430\u043b\u0438\u0442\u044c \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440, \u043c\u043e\u0436\u043d\u043e \u0442\u0430\u043a\u0436\u0435 \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043a\u043b\u043e\u043d \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u0430. \u0412\u0441\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0443\u0437\u043d\u0430\u0442\u044c, \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0432 \u043a\u043e\u043c\u0430\u043d\u0434\u0443:<\/p>\n<pre><code class=\"bash\">xcrun simctl help<\/code><\/pre>\n<p>\u0412\u0435\u0440\u043d\u0435\u043c\u0441\u044f \u043a \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0443 \u0441\u0442\u0430\u0442\u044c\u0438. \u0422\u0435\u043f\u0435\u0440\u044c \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f \u0431\u043e\u043b\u0435\u0435 \u043c\u0435\u043d\u0435\u0435 \u043f\u043e\u043d\u044f\u0442\u043d\u043e, \u0447\u0442\u043e \u043d\u0443\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c, \u0447\u0442\u043e\u0431\u044b \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u043e\u043c \u0438\u0437 \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u0430. \u041d\u0443\u0436\u043d\u043e \u043a\u0430\u043a\u0438\u043c-\u0442\u043e \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u0438\u0437 \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u0430 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c bash \u043a\u043e\u043c\u0430\u043d\u0434\u0443 (xcrun simctl &#8230;) \u043d\u0430 \u0445\u043e\u0441\u0442 \u043c\u0430\u0448\u0438\u043d\u0435, \u0442\u043e \u0435\u0441\u0442\u044c \u043d\u0430 MacOS, \u0433\u0434\u0435 \u0437\u0430\u043f\u0443\u0449\u0435\u043d \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440.<\/p>\n<p>\u041d\u043e \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u044e \u043d\u0430\u0447\u0430\u0442\u044c \u0441 \u043f\u0440\u043e\u0441\u0442\u043e\u0433\u043e \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u0432 \u043a\u0430\u043a\u043e\u043c \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0438 \u0437\u0430\u043f\u0443\u0449\u0435\u043d \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440 \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0445\u043e\u0441\u0442 \u043c\u0430\u0448\u0438\u043d\u044b. \u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043f\u0443\u0441\u0442\u043e\u0435 iOS \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0438 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043c \u0435\u0433\u043e \u043d\u0430 iOS \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u0435. \u0412\u0441\u0435 \u043f\u0440\u0438\u043c\u0435\u0440\u044b \u043a\u043e\u0434\u0430 \u0431\u0443\u0434\u0435\u043c \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u0432\u043d\u0443\u0442\u0440\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f iOS \u0441\u0438\u0441\u0442\u0435\u043c\u043e\u0439 \u043f\u0440\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f:<\/p>\n<pre><code class=\"swift\">func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -&gt; Bool { }<\/code><\/pre>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c, \u0447\u0442\u043e \u043d\u0430\u043c \u0432\u044b\u0432\u0435\u0434\u0435\u0442 \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u043e\u0435 iOS API \u0434\u043b\u044f \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438:<\/p>\n<pre><code class=\"swift\">let dir = FileManager.default.temporaryDirectory print(dir)<\/code><\/pre>\n<p>\u0412\u044b\u0434\u0430\u0441\u0442 \u0432\u044b\u0432\u043e\u0434 \u0432 Xcode \u043a\u043e\u043d\u0441\u043e\u043b\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0433\u043e \u0432\u0438\u0434\u0430:<\/p>\n<blockquote>\n<p>file:\/\/\/Users\/user\/Library\/Developer\/CoreSimulator\/Devices\/FDFE4922-31B3-45C2-920E-CB7D157438D8\/data\/Containers\/Data\/Application\/ED9B6B5F-F62D-4452-B72D-A1A3260F19F3\/tmp\/<\/p>\n<\/blockquote>\n<p>\u041c\u044b \u0442\u0430\u043a\u0436\u0435 \u044d\u0442\u0443 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044e \u043c\u043e\u0436\u0435\u043c \u043e\u0442\u043a\u0440\u044b\u0442\u044c \u0438 \u043d\u0430 \u0445\u043e\u0441\u0442 \u043c\u0430\u0448\u0438\u043d\u0435 \u043f\u0440\u043e\u0441\u0442\u043e \u0432 Finder \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438.<\/p>\n<p>\u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u044d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442 &#8212; \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0444\u0430\u0439\u043b \u0432 $HOME\/Downloads \u044e\u0437\u0435\u0440 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438, \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u043f\u0440\u0430\u0432\u0430 \u043d\u0430 \u0437\u0430\u043f\u0438\u0441\u044c. \u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u043f\u0440\u0438\u043c\u0435\u0440:<\/p>\n<pre><code class=\"swift\"> do {     try \"Hello Habr!\".write(to: URL(fileURLWithPath: \"\/Users\/user\/Downloads\/habr-hello.txt\"), atomically: true, encoding: .utf8) } catch {     print(error) }<\/code><\/pre>\n<p>\u0412 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0435 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0443 \u043d\u0430\u0441 \u0432 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 \/Downloads \u0441\u043e\u0437\u0434\u0430\u0441\u0442\u0441\u044f \u0444\u0430\u0439\u043b habr-hello.txt, \u0438\u043d\u044b\u043c\u0438 \u0441\u043b\u043e\u0432\u0430\u043c\u0438 \u043c\u044b \u043c\u043e\u0436\u0435\u043c, \u043a\u0430\u043a \u043c\u0438\u043d\u0438\u043c\u0443\u043c, \u043c\u0430\u043d\u0438\u043f\u0443\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0444\u0430\u0439\u043b\u0430\u043c\u0438 \u043d\u0430 \u0445\u043e\u0441\u0442 \u0441\u0438\u0441\u0442\u0435\u043c\u0435 \u0441 write \u0443\u0440\u043e\u0432\u043d\u0435\u043c \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u0438\u0437 \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u0430.<\/p>\n<p>\u0413\u0434\u0435 \u044d\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u0438\u0433\u043e\u0434\u0438\u0442\u044c\u0441\u044f:<\/p>\n<ol>\n<li>\n<p>\u042d\u0442\u0438\u043c \u0430\u043a\u0442\u0438\u0432\u043d\u043e \u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f Snapshot Testing \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438. \u041e\u043d\u0438 \u0434\u0435\u043b\u0430\u044e\u0442 \u0441\u043d\u0430\u043f\u0448\u043e\u0442 \u044d\u043a\u0440\u0430\u043d\u0430 \u0438\u043b\u0438 \u0432\u044c\u044e\u0448\u043a\u0438 \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u043f\u0440\u043e\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u044f \u0442\u0435\u0441\u0442\u0430 \u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u044e\u0442 \u0435\u0433\u043e \u043d\u0430 \u0434\u0438\u0441\u043a \u0445\u043e\u0441\u0442 \u043c\u0430\u0448\u0438\u043d\u044b \u0440\u044f\u0434\u043e\u043c \u0441 \u0444\u0430\u0439\u043b\u043e\u043c \u0442\u0435\u0441\u0442\u043e\u0432. \u0412 \u043a\u043e\u0434\u0435 \u044d\u0442\u043e \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442, \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e, \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<\/p>\n<\/li>\n<\/ol>\n<pre><code class=\"swift\">func testSnapshotScreen() throws {     let view = UIView()     let image = UIGraphicsImageRenderer(size: view.bounds.size).image { _ in         view.drawHierarchy(in: view.bounds, afterScreenUpdates: true)     }     let jpeg = image.jpegData(compressionQuality: 1)!     let url = URL(fileURLWithPath: #filePath)         .deletingLastPathComponent()         .appendingPathComponent(#function.replacingOccurrences(of: \"()\", with: \"\"))         .appendingPathExtension(for: .jpeg)     try jpeg.write(to: url) }<\/code><\/pre>\n<p>\u041f\u043e\u0441\u043b\u0435 \u043f\u0440\u043e\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u044f \u0442\u0435\u0441\u0442\u0430, \u0440\u044f\u0434\u043e\u043c \u0441 Swift\/ObjC \u0444\u0430\u0439\u043b\u043e\u043c \u0441 \u0442\u0435\u0441\u0442\u043e\u043c, \u043f\u043e\u044f\u0432\u0438\u0442\u0441\u044f \u0444\u0430\u0439\u043b \u0441\u043d\u0430\u043f\u0448\u043e\u0442\u0430 <em>testSnapshotScreen.jpeg<\/em>.<\/p>\n<ol start=\"2\">\n<li>\n<p>\u0415\u0441\u043b\u0438 \u0432\u044b \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442\u0435 \u0441 \u0431\u0430\u0437\u043e\u0439 \u0434\u0430\u043d\u043d\u044b\u0445, \u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0444\u0430\u0439\u043b \u0431\u0430\u0437\u044b \u0434\u0430\u043d\u043d\u044b\u0445 \u0447\u0435\u0440\u0435\u0437 MacOS Desktop \u043f\u043e\u043b\u043d\u043e\u0446\u0435\u043d\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0441 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u043c\u0438 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u0438 \u0437\u0430\u0442\u0435\u043c \u044d\u0442\u0443 \u0431\u0430\u0437\u0443 \u0434\u0430\u043d\u043d\u044b\u0445 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0442\u044c \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u0437\u0430\u043f\u0443\u0449\u0435\u043d\u043d\u043e\u0435 \u043d\u0430 \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u0435.<\/p>\n<\/li>\n<\/ol>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0441\u043d\u043e\u0432\u0430 \u043f\u0435\u0440\u0435\u0439\u0434\u0435\u043c \u043a \u0441\u0443\u0442\u0438 \u0441\u0430\u043c\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438.<\/p>\n<p>\u0427\u0442\u043e\u0431\u044b \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c <em>bash<\/em> \u043a\u043e\u043c\u0430\u043d\u0434\u0443 \u0438\u0437 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <em>posix<\/em> \u0444\u0443\u043d\u043a\u0446\u0438\u044e <em>system()<\/em>, \u043d\u043e, \u043a \u0441\u043e\u0436\u0430\u043b\u0435\u043d\u0438\u044e, \u043e\u043d\u0430 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0430 \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f MacOS SDK, \u043e \u0447\u0435\u043c \u043d\u0430\u043c \u0433\u043e\u0432\u043e\u0440\u044f\u0442 \u043c\u0430\u043a\u0440\u043e\u0441\u044b \u0432\u043e\u043a\u0440\u0443\u0433 \u043d\u0435\u0435:<\/p>\n<pre><code class=\"cpp\">__swift_unavailable(\"Use posix_spawn APIs or NSTask instead. (On iOS, process spawning is unavailable.)\") __API_AVAILABLE(macos(10.0)) __IOS_PROHIBITED __WATCHOS_PROHIBITED __TVOS_PROHIBITED int system(const char * ) __DARWIN_ALIAS_C(system);<\/code><\/pre>\n<p>\u0411\u043e\u043b\u0435\u0435 \u0442\u043e\u0433\u043e, \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0432 \u043c\u0430\u043a\u0440\u043e\u0441\u0435 \u043d\u0430\u043c \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u0435\u0442 \u0432\u043c\u0435\u0441\u0442\u043e <em>system()<\/em> \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0438\u043b\u0438 <em>posix_spawn()<\/em> \u0438\u0437 Darwin SDK, \u0438\u043b\u0438, \u0437\u043d\u0430\u043a\u043e\u043c\u0443\u044e \u043c\u043d\u043e\u0433\u0438\u043c \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430\u043c, <em>NSTask<\/em> (\u043a\u043b\u0430\u0441\u0441 <em>Process<\/em> \u0432 Swift) \u0438\u0437 \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u043e\u0439 Foundation \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438. \u0415\u0441\u043b\u0438 \u0437\u0430\u0433\u043b\u044f\u043d\u0443\u0442\u044c \u0432 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 <em>NSTask<\/em>, \u0442\u043e \u044d\u0442\u043e\u0442 \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u044b\u0439 \u043a\u043b\u0430\u0441\u0441, \u043a\u0430\u043a \u0438 <em>system()<\/em> \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d, \u043a \u0441\u043e\u0436\u0430\u043b\u0435\u043d\u0438\u044e, \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0430 MacOS. \u0422\u0435\u043f\u0435\u0440\u044c \u0443 \u043d\u0430\u0441 \u0432\u0441\u044f \u043d\u0430\u0434\u0435\u0436\u0434\u0430  \u043d\u0430 <em>posix_spawn()<\/em>, \u043a\u043e\u0442\u043e\u0440\u0430\u044f, \u043a \u043d\u0430\u0448\u0435\u0439 \u0443\u0434\u0430\u0447\u0435, \u0435\u0441\u0442\u044c \u0432 iOS SDK, \u043e \u0447\u0435\u043c \u0438 \u0433\u043e\u0432\u043e\u0440\u044f\u0442 \u043c\u0430\u043a\u0440\u043e\u0441\u044b \u0432 \u0438\u0441\u0445\u043e\u0434\u043d\u0438\u043a\u0430\u0445 \u044d\u0442\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 <a href=\"https:\/\/github.com\/apple\/darwin-xnu\/blob\/main\/libsyscall\/wrappers\/spawn\/spawn.h\" rel=\"noopener noreferrer nofollow\">https:\/\/github.com\/apple\/darwin-xnu\/blob\/main\/libsyscall\/wrappers\/spawn\/spawn.h<\/a> :<\/p>\n<pre><code class=\"cpp\">int posix_spawn(pid_t * __restrict, const char * __restrict,     const posix_spawn_file_actions_t *,     const posix_spawnattr_t * __restrict,     char *const __argv[__restrict],     char *const __envp[__restrict]) __API_AVAILABLE(macos(10.5), ios(2.0)) __SPI_AVAILABLE(watchos(2.0), tvos(9.0), bridgeos(1.0));<\/code><\/pre>\n<ul>\n<li>\n<p>\u0414\u043b\u044f \u043f\u0440\u043e\u0434\u0432\u0438\u043d\u0443\u0442\u044b\u0445 \u0445\u0430\u0446\u043a\u0435\u0440\u043e\u0432, \u0435\u0441\u0442\u044c \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f, \u0447\u0442\u043e <em>NSTask<\/em> \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044f iOS SDK, \u043f\u0440\u043e\u0441\u0442\u043e Apple \u0443\u0431\u0440\u0430\u043b \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e\u0431 \u044d\u0442\u043e\u043c \u043a\u043b\u0430\u0441\u0441\u0435 \u0438\u0437 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u0447\u043d\u044b\u0445 \u0444\u0430\u0439\u043b\u043e\u0432, \u0447\u0442\u043e\u0431\u044b \u0438\u043c \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043d\u0443\u0436\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u044d\u0442\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430 \u0432 \u0432\u0430\u0448 \u043f\u0440\u043e\u0435\u043a\u0442 (\u043c\u043e\u0436\u043d\u043e \u0441\u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441 MacOS Foundation SDK \u0438 \u0447\u0443\u0442\u044c \u043f\u043e\u0434\u043f\u0440\u0430\u0432\u0438\u0442\u044c).<\/p>\n<\/li>\n<\/ul>\n<p>\u041f\u0440\u043e\u0434\u043e\u043b\u0436\u0430\u0435\u043c. \u0427\u0435\u043c \u0434\u043e\u043b\u044c\u0448\u0435 \u044f \u0441\u043c\u043e\u0442\u0440\u044e \u043d\u0430 \u044d\u0442\u0443 \u0444\u0443\u043d\u043a\u0446\u0438\u044e, \u0442\u0435\u043c \u0431\u043e\u043b\u044c\u0448\u0435 \u043f\u043e\u043d\u0438\u043c\u0430\u044e, \u0447\u0442\u043e \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u043f\u043e\u043d\u0438\u043c\u0430\u044e. \u0415\u0441\u043b\u0438 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u043d\u0430 \u0441 \u043a\u043e\u043d\u0432\u0435\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0435 \u0432 Swift \u044f\u0437\u044b\u043a API \u044d\u0442\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u0442\u043e \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f \u0435\u0449\u0435 \u043d\u0435\u043f\u043e\u043d\u044f\u0442\u043d\u0435\u0435:<\/p>\n<pre><code class=\"swift\">public func posix_spawn(     _: UnsafeMutablePointer&lt;pid_t&gt;!,     _: UnsafePointer&lt;CChar&gt;!,      _: UnsafePointer&lt;posix_spawn_file_actions_t?&gt;!,      _: UnsafePointer&lt;posix_spawnattr_t?&gt;!,      _ __argv: UnsafePointer&lt;UnsafeMutablePointer&lt;CChar&gt;?&gt;!,      _ __envp: UnsafePointer&lt;UnsafeMutablePointer&lt;CChar&gt;?&gt;!     ) -&gt; Int32<\/code><\/pre>\n<p>\u0412 \u043e\u0431\u0449\u0435\u043c, \u0438\u0434\u0435\u043c \u0441\u0430\u043c\u044b\u043c \u043f\u0440\u043e\u0441\u0442\u044b\u043c \u0441\u043f\u043e\u0441\u043e\u0431\u043e\u043c, \u0438\u0434\u0435\u043c \u043d\u0430 Github \u0438 \u043f\u044b\u0442\u0430\u0435\u043c\u0441\u044f \u043d\u0430\u0439\u0442\u0438 \u043f\u0440\u0438\u043c\u0435\u0440\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u044d\u0442\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u043d\u0430 Swift \u044f\u0437\u044b\u043a\u0435 \u0438 \u0431\u0435\u0440\u0435\u043c \u043f\u0435\u0440\u0432\u044b\u0439 \u043f\u043e\u043f\u0430\u0432\u0448\u0438\u0439\u0441\u044f \u0440\u0430\u0431\u043e\u0447\u0438\u0439 \u043f\u0440\u0438\u043c\u0435\u0440. \u0423 \u043c\u0435\u043d\u044f \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0441\u044f \u0442\u0430\u043a\u043e\u0439 \u043a\u043e\u0434:<\/p>\n<pre><code class=\"swift\">struct CliTool {      static func runCommand(_ command: String) throws -&gt; Int32 {         var pid: pid_t = 0         var status = Int32(0)         let args = [\"sh\", \"-c\", command]         let envs = [String]()         try withCStrings(args) { cArgs in             try withCStrings(envs) { cEnvs in                 status = posix_spawn(&amp;pid, \"\/bin\/sh\", nil, nil, cArgs, cEnvs)                 if status == 0 {                     if waitpid(pid, &amp;status, 0) == -1 {                         throw RunCommandError.WaitPIDError                     }                 } else {                     throw RunCommandError.POSIXSpawnError(status)                 }             }         }         return status     }      enum RunCommandError: Error {         case WaitPIDError         case POSIXSpawnError(Int32)     } }<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u0443\u0437\u043d\u0430\u0442\u044c \u0432\u0435\u0440\u0441\u0438\u044e Xcode \u043d\u0430 \u0445\u043e\u0441\u0442 \u043c\u0430\u0448\u0438\u043d\u0435:<\/p>\n<pre><code class=\"swift\">\/\/ \u0412\u0441\u0435\u0433\u0434\u0430 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c \u043d\u0430 \u0444\u043e\u043d\u043e\u0432\u043e\u043c \u043f\u043e\u0442\u043e\u043a\u0435 DispatchQueue.global().async {     do {         try CliTool.runCommand(\"xcodebuild -version\")     } catch {         print(error)     } }<\/code><\/pre>\n<p>\u0418 \u0432 \u043a\u043e\u043d\u0441\u043e\u043b\u0438 Xcode \u0432\u0438\u0434\u0438\u043c \u0437\u0430\u0432\u0435\u0442\u043d\u044b\u0435:<\/p>\n<blockquote>\n<p>Xcode 15.4<br \/>Build version 15F31d<\/p>\n<\/blockquote>\n<p>\u041f\u0440\u043e\u0432\u0435\u0440\u0438\u043c, \u043a\u0430\u043a\u0438\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b:<\/p>\n<pre><code class=\"swift\">try CliTool.runCommand(\"export\")<\/code><\/pre>\n<p>\u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c:<\/p>\n<pre><code class=\"bash\">export OLDPWD export PWD=\"\/\" export SHLVL=\"1\"<\/code><\/pre>\n<p>\u041f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u0443\u0437\u043d\u0430\u0442\u044c \u0441\u043f\u0438\u0441\u043e\u043a \u0444\u0430\u0439\u043b\u043e\u0432 \u0432 $HOME \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438:<\/p>\n<pre><code class=\"swift\">try CliTool.runCommand(\"ls $HOME\")<\/code><\/pre>\n<p>\u0418 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0441\u043f\u0438\u0441\u043e\u043a \u0438\u0437 \u043a\u043e\u0440\u043d\u0435\u0432\u043e\u0439 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 MacOS, \u044d\u0442\u043e \u043d\u0435 \u0442\u043e \u0447\u0442\u043e \u043c\u044b \u043e\u0436\u0438\u0434\u0430\u0435\u043c. \u041d\u0443\u0436\u043d\u043e \u0432\u044b\u0441\u0442\u0430\u0432\u0438\u0442\u044c HOME \u043d\u0430\u0448\u0435\u0433\u043e MacOS \u044e\u0437\u0435\u0440\u0430 \u043f\u0440\u0435\u0436\u0434\u0435 \u0447\u0435\u043c \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u043a\u043e\u043c\u0430\u043d\u0434\u0443, \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u043f\u0440\u0430\u0432\u0438\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u044e <em>runCommand<\/em>, \u0433\u0434\u0435 \u0432\u044b\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f:<\/p>\n<pre><code class=\"swift\">let iOSUserENV = [     \"export LANG=en_US.UTF-8\",     \"export LC_ALL=en_US.UTF-8\",     \"export LC_CTYPE=UTF-8\",     \"export USER=\\(FileManager.default.temporaryDirectory.pathComponents[2])\", \/\/ \u044e\u0437\u0435\u0440\u0430 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u043c \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0438     \"export HOME=\/Users\/$USER\" ].joined(separator: \";\") let args = [\"sh\", \"-c\", \"\\(iOSUserENV);\\(command)\"]<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0435\u0441\u043b\u0438 \u043f\u043e\u0432\u0442\u043e\u0440\u0438\u0442\u044c \u043a\u043e\u043c\u0430\u043d\u0434\u0443, \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u0436\u0435\u043b\u0430\u0435\u043c\u044b\u0439 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442.<\/p>\n<p>\u0415\u0449\u0435 \u044d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442, \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0441\u043a\u0440\u0438\u043f \u0438 \u0435\u0433\u043e \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c:<\/p>\n<pre><code class=\"swift\">try CliTool.runCommand(\"cd $HOME\/Downloads\/;echo date &gt; 123.sh;chmod +x .\/123.sh;.\/123.sh\")<\/code><\/pre>\n<p>\u041e\u0431\u043d\u0430\u0440\u0443\u0436\u0438\u0432\u0430\u0435\u043c, \u0447\u0442\u043e \u0445\u043e\u0441\u0442 \u043c\u0430\u0448\u0438\u043d\u0430 \u043d\u0430\u043c \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0434\u0435\u043b\u0430\u0442\u044c \u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0432\u0441\u0451 \u0447\u0442\u043e \u0443\u0433\u043e\u0434\u043d\u043e \u0433\u0434\u0435 \u043d\u0435 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f <em>root<\/em> \u043f\u0430\u0440\u043e\u043b\u044c \u0438\u043b\u0438 \u043a\u0430\u043a\u0438\u0445 \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u0447\u043d\u044b\u0445 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u0434\u043b\u044f \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f.<\/p>\n<p>\u0412\u0435\u0440\u043d\u0435\u043c\u0441\u044f \u0441\u043d\u043e\u0432\u0430 \u043a \u0442\u0435\u043c\u0435 \u0441\u0442\u0430\u0442\u044c\u0438 \u0438, \u043d\u0430\u043a\u043e\u043d\u0435\u0446, \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u043a\u043e\u043c\u0430\u043d\u0434\u0443 \u043d\u0430\u0448\u0435\u043c\u0443 \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u0443. \u041d\u043e, \u0441\u043d\u0430\u0447\u0430\u043b\u0430, \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u043c \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0430 \u043b\u0438 \u043d\u0430\u043c <em>simctl<\/em> \u0443\u0442\u0438\u043b\u0438\u0442\u0430 \u0438\u0437 \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u0430. \u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c:<\/p>\n<pre><code class=\"swift\">try CliTool.runCommand(\"xcrun simctl --version\")<\/code><\/pre>\n<p>\u0438 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c:<\/p>\n<pre><code class=\"bash\">@(#)PROGRAM:simctl  PROJECT:CoreSimulator-993.7<\/code><\/pre>\n<p>\u0417\u043d\u0430\u0447\u0438\u0442 \u043d\u0430\u043c \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0430 <em>simctl<\/em>. \u0418 \u0442\u0435\u043f\u0435\u0440\u044c \u043f\u0440\u043e\u0431\u0443\u0435\u043c \u0434\u043e\u043b\u0433\u043e\u0436\u0434\u0430\u043d\u043d\u044b\u0439 \u0437\u0430\u043f\u0443\u0441\u043a \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u0430 \u0438\u0437 \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u0430:<\/p>\n<pre><code class=\"swift\">try CliTool.runCommand(\"xcrun simctl boot 322438F1-8B66-468E-A1DD-8285BEDB6235\")<\/code><\/pre>\n<p>\u0438, \u043a \u0441\u043e\u0436\u0430\u043b\u0435\u043d\u0438\u044e, \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u043e\u0448\u0438\u0431\u043a\u0443:<\/p>\n<blockquote>\n<p>simctl[16681:584185] Error Domain=NSPOSIXErrorDomain Code=61 &#171;Connection refused&#187; UserInfo={NSLocalizedDescription=Unable to lookup com.apple.CoreSimulator.CoreSimulatorService (993.7) in the bootstrap.  This can happen if running with a sandbox profile.  When running with a sandbox profile, \/Library\/Developer\/PrivateFrameworks\/CoreSimulator.framework\/XPCServices\/com.apple.CoreSimulator.CoreSimulatorService.xpc must be owned by root, not group writable, and not world writable.  See . isXBSChroot(): NO, XBS_IS_CHROOTED: (null)}<\/p>\n<\/blockquote>\n<p>\u041f\u043e \u0442\u0435\u043a\u0441\u0442\u0443 \u043e\u0448\u0438\u0431\u043a\u0438 \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u043f\u043e\u043d\u044f\u0442\u043d\u043e, \u0447\u0442\u043e \u043d\u0430\u0448 \u044e\u0437\u0435\u0440 <em>bash<\/em> \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u043d\u0435 \u0441\u043e\u0432\u0441\u0435\u043c \u044e\u0437\u0435\u0440 \u0445\u043e\u0441\u0442 <\/p>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-443083","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/443083","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=443083"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/443083\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=443083"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=443083"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=443083"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}