{"id":343681,"date":"2023-01-09T09:04:10","date_gmt":"2023-01-09T09:04:10","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=343681"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=343681","title":{"rendered":"<span>AVFoundation \u2014 \u043f\u0438\u0448\u0435\u043c \u043f\u0440\u043e\u0441\u0442\u0435\u0439\u0448\u0443\u044e \u0444\u043e\u0442\u043e\u043a\u0430\u043c\u0435\u0440\u0443<\/span>"},"content":{"rendered":"<div><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<h2>Hello World!<\/h2>\n<p>\u0412\u0441\u0435\u043c \u043f\u0440\u0438\u0432\u0435\u0442, \u043c\u0435\u043d\u044f \u0437\u043e\u0432\u0443\u0442 \u042d\u043c\u0438\u043b\u044c. \u042f <u>\u043c\u043b\u0430\u0434\u0448\u0438\u0439<\/u> iOS \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0432 &#171;3\u0414 \u041f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0430&#187; (\u0434\u0436\u0443\u043d\u0438\u043e\u0440 \u043f\u0438\u0448\u0435\u0442 \u0441\u0442\u0430\u0442\u044c\u044e, \u0434\u0430\u0434\u0430 \u044f) \u0438 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043c\u0435\u0441\u044f\u0446\u0435\u0432 \u043d\u0430\u0437\u0430\u0434 \u044f \u0441\u0442\u043e\u043b\u043a\u043d\u0443\u043b\u0441\u044f \u0441 \u043a\u0430\u043c\u0435\u0440\u043e\u0439 \u043d\u0430 <a href=\"https:\/\/developer.apple.com\/documentation\/avfoundation\" rel=\"noopener noreferrer nofollow\">AVFoundation<\/a>: \u043c\u043d\u0435 \u043d\u0443\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043a\u0430\u043c\u0435\u0440\u0435 \u043e\u043f\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u044b\u0439 \u0437\u0443\u043c \u0441 1.0\u0445 \u0434\u043e 0.5\u0445, \u0435\u0441\u043b\u0438 \u043a\u0430\u043c\u0435\u0440\u0430 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0442\u0430\u043a\u043e\u0439 \u0437\u0443\u043c. \u041c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u043e\u0432 \u044f \u043d\u0430\u0448\u0435\u043b \u043e\u0447\u0435\u043d\u044c \u043c\u043d\u043e\u0433\u043e, \u043f\u043e\u043f\u0440\u0430\u043a\u0442\u0438\u043a\u043e\u0432\u0430\u043b\u0441\u044f \u043d\u0430 \u0442\u0435\u0441\u0442\u043e\u0432\u043e\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0435, \u0432\u044b\u0432\u0435\u0440\u0438\u043b \u043b\u0443\u0447\u0448\u0443\u044e \u0444\u043e\u0440\u043c\u0443\u043b\u0443 \u0434\u043b\u044f \u0437\u0443\u043c\u0430 \u0438 \u0438\u043d\u0442\u0435\u0433\u0440\u0438\u0440\u043e\u0432\u0430\u043b \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u0432 \u043f\u0440\u043e\u0434. \u041f\u043e\u0441\u043b\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0437\u0430\u0434\u0430\u0447\u0438 \u044f \u0437\u0430\u043c\u0435\u0442\u0438\u043b, \u0447\u0442\u043e \u043d\u0435 \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u043b \u043d\u0438 \u043e\u0434\u043d\u043e\u0433\u043e \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u0430 \u043d\u0430 \u0440\u0443\u0441\u0441\u043a\u043e\u043c, \u043a\u0440\u043e\u043c\u0435 \u043e\u0434\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438 \u043d\u0430 \u0425\u0430\u0431\u0440\u0435, \u0434\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0439 2013 \u0433\u043e\u0434\u043e\u043c. \u0421\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u044d\u0442\u043e \u043d\u0430\u0431\u043b\u044e\u0434\u0435\u043d\u0438\u0435 \u0438 \u043d\u0430\u0432\u0435\u043b\u043e \u043c\u0435\u043d\u044f \u043d\u0430 \u043c\u044b\u0441\u043b\u044c \u043e \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u0438 \u0441\u0432\u043e\u0435\u0439 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438 \u043e\u0431 AVFoundation &#8212; \u043a\u0430\u043c\u0435\u0440\u0435. \u042f \u0440\u0435\u0448\u0438\u043b \u043d\u0430\u0447\u0430\u0442\u044c \u0441 \u043f\u0440\u043e\u0435\u043a\u0442\u0430, \u043d\u0430 \u0431\u0430\u0437\u0435 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043c\u044b \u0441\u0435\u0433\u043e\u0434\u043d\u044f \u0441 \u0432\u0430\u043c\u0438 \u0438\u0437\u0443\u0447\u0438\u043c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 AVFoundation \u043d\u0430 \u043b\u043e\u043d\u0435 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u043a\u0430\u043c\u0435\u0440\u043e\u0439 (\u0430 \u0432\u043e\u043e\u0431\u0449\u0435 \u0442\u0430\u043c \u043c\u043e\u0436\u043d\u043e \u0435\u0449\u0435 \u0438 \u0441\u043e \u0437\u0432\u0443\u043a\u043e\u043c \u043f\u043e\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c). \u042d\u0442\u043e \u043c\u043e\u044f \u043f\u0435\u0440\u0432\u0430\u044f \u0441\u0442\u0430\u0442\u044c\u044f, \u043d\u043e \u044f \u043d\u0435 \u0431\u0443\u0434\u0443 \u043f\u0440\u043e\u0441\u0438\u0442\u044c \u0432\u0430\u0441 \u043e\u0442\u043d\u0435\u0441\u0442\u0438\u0441\u044c \u043a \u043d\u0435\u0439 \u0441\u043d\u0438\u0441\u0445\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e. \u0414\u0443\u043c\u0430\u044e, \u044d\u0442\u043e\u0442 \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043b\u0435\u0437\u0435\u043d \u043d\u043e\u0432\u0438\u0447\u043a\u0430\u043c \u0438 \u0434\u0436\u0443\u043d\u0430\u043c, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0438\u043a\u043e\u0433\u0434\u0430 \u043d\u0435 \u0441\u0442\u0430\u043b\u043a\u0438\u0432\u0430\u043b\u0438\u0441\u044c \u0441 AVFoundation \u0438 \u043d\u0435 \u0437\u043d\u0430\u044e\u0442, \u043a\u0430\u043a\u0430\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043f\u043e \u044d\u0442\u043e\u0439 \u0442\u0435\u043c\u0435 \u0440\u0435\u0430\u043b\u044c\u043d\u043e \u0433\u043e\u0434\u043d\u0430.<\/p>\n<p>\u041d\u0443 \u0447\u0442\u043e \u0436, \u043f\u043e\u0435\u0445\u0430\u043b\u0438.<\/p>\n<p>\u041f\u043e\u043b\u043d\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442: <a href=\"https:\/\/github.com\/Wtclrsnd\/RealTrapCamera\" rel=\"noopener noreferrer nofollow\">https:\/\/github.com\/Wtclrsnd\/RealTrapCamera<\/a> <\/p>\n<p><strong>\u041d\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u044f<\/strong><\/p>\n<ul>\n<li>\n<p>\u0427\u0442\u043e \u0442\u0430\u043a\u043e\u0435 AVFoundation<\/p>\n<\/li>\n<li>\n<p>\u041f\u0438\u0448\u0435\u043c UI<\/p>\n<\/li>\n<li>\n<p>AVCaptureSession, inputs, outputs, AVCaptureDevice<\/p>\n<\/li>\n<li>\n<p>PreviewLayer<\/p>\n<\/li>\n<li>\n<p>\u041f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u043c\u0435\u0436\u0434\u0443 \u0444\u0440\u043e\u043d\u0442\u0430\u043b\u044c\u043d\u043e\u0439 \u0438 \u0437\u0430\u0434\u043d\u0435\u0439 \u043a\u0430\u043c\u0435\u0440\u0430\u043c\u0438<\/p>\n<\/li>\n<li>\n<p>\u041f\u0440\u043e\u0441\u0438\u043c \u0443 \u0422\u0438\u043c\u043e\u0448\u0438 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u043d\u0430 \u0441\u044a\u0435\u043c\u043a\u0443<\/p>\n<\/li>\n<li>\n<p>AVCapturePhotoCaptureDelegate &#8212; \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u0444\u043e\u0442\u043e<\/p>\n<\/li>\n<li>\n<p>PinchToZoom<\/p>\n<\/li>\n<li>\n<p>\u0411\u043e\u043d\u0443\u0441: Haptics \u043f\u043e \u043d\u0430\u0436\u0430\u0442\u0438\u044e \u043a\u043d\u043e\u043f\u043a\u0438<\/p>\n<\/li>\n<li>\n<p>\u0417\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u0438 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0438<\/p>\n<\/li>\n<\/ul>\n<h2>\u0427\u0442\u043e \u0442\u0430\u043a\u043e\u0435 AVFoundation?<\/h2>\n<p>\u041f\u0440\u043e\u0446\u0438\u0442\u0438\u0440\u0443\u044e Apple: <em>AVFoundation &#8212; \u044d\u0442\u043e \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0430\u0443\u0434\u0438\u043e\u0432\u0438\u0437\u0443\u0430\u043b\u044c\u043d\u044b\u043c\u0438 \u043c\u0435\u0434\u0438\u0430\u0444\u0430\u0439\u043b\u0430\u043c\u0438 \u043d\u0430 iOS, macOS, watchOS \u0438 tvOS. \u0411\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f AVFoundation \u043c\u043e\u0436\u043d\u043e \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u044c, <u>\u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c<\/u> \u0438 \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0444\u0430\u0439\u043b\u044b QuickTime \u0438 \u0444\u0430\u0439\u043b\u044b MPEG-4, \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u044c \u043f\u043e\u0442\u043e\u043a\u0438 HLS \u0438 \u0432\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0442\u044c \u043c\u043e\u0449\u043d\u0443\u044e \u043c\u0443\u043b\u044c\u0442\u0438\u043c\u0435\u0434\u0438\u0439\u043d\u0443\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0432 \u0441\u0432\u043e\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f.<\/em><\/p>\n<p>\u041a\u0430\u043a \u0441\u0442\u0430\u043b\u043e \u043f\u043e\u043d\u044f\u0442\u043d\u043e \u0438\u0437 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f, AVFoundation \u044d\u0442\u043e \u0448\u0438\u0440\u043e\u043a\u043e\u043f\u0440\u043e\u0444\u0438\u043b\u044c\u043d\u044b\u0439 \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a \u0441 \u0431\u043e\u043b\u044c\u0448\u0438\u043c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e\u043c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0435\u0439, \u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u0445\u043e\u0434\u0438\u0442 \u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0444\u043e\u0442\u043e \u0438 \u0432\u0438\u0434\u0435\u043e, \u043d\u0430 \u0447\u0435\u043c \u043c\u044b \u0441\u0435\u0433\u043e\u0434\u043d\u044f \u0441 \u0432\u0430\u043c\u0438 \u0438 \u0441\u043a\u043e\u043d\u0446\u0435\u043d\u0442\u0440\u0438\u0440\u0443\u0435\u043c\u0441\u044f. \u0424\u043e\u0442\u043e \u0438 \u0432\u0438\u0434\u0435\u043e \u043a\u0430\u043c\u0435\u0440\u044b &#8212; \u0441\u0430\u043c\u044b\u0439 \u0447\u0430\u0441\u0442\u044b\u0439 \u043a\u0435\u0439\u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f AVFoundation. <\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/3d5\/3b6\/067\/3d53b6067c3c96c520a0cab3c474a37f.webp\" alt=\"\u0418\u0441\u0442\u043e\u0447\u043d\u0438\u043a: https:\/\/medium.com\/@divya.nayak\/learning-avfoundation-part-1-c761aad183ad\" title=\"\u0418\u0441\u0442\u043e\u0447\u043d\u0438\u043a: https:\/\/medium.com\/@divya.nayak\/learning-avfoundation-part-1-c761aad183ad\" width=\"1658\" height=\"1165\"\/><figcaption>\u0418\u0441\u0442\u043e\u0447\u043d\u0438\u043a: https:\/\/medium.com\/@divya.nayak\/learning-avfoundation-part-1-c761aad183ad<\/figcaption><\/figure>\n<p>\u041f\u043e\u0434 AVFoundation &#171;\u043b\u0435\u0436\u0430\u0442&#187; CoreAudio, CoreMedia &#8212; \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u044f \u0433\u043e\u0432\u043e\u0440\u044f\u0442 \u0441\u0430\u043c\u0438 \u0437\u0430 \u0441\u0435\u0431\u044f. \u0410 \u0442\u0430\u043a\u0436\u0435 CoreAnimation \u0434\u043b\u044f \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0438\u0435\u0440\u0430\u0440\u0445\u0438\u0438 \u0432\u0438\u0434\u0435\u043e \u0438 \u043f\u0440\u0435\u0437\u0435\u043d\u0442\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0433\u043e \u0441\u043b\u043e\u044f. <\/p>\n<p>\u0423\u0433\u043b\u0443\u0431\u0438\u043c\u0441\u044f \u0432 \u0442\u0435\u043c\u0443 \u0441\u044a\u0435\u043c\u043e\u043a \u0444\u043e\u0442\u043e. \u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u044e \u0432\u0430\u043c \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u043a\u043b\u0430\u0441\u0441\u044b AVFoundation, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0449\u0438\u0435\u0441\u044f \u0434\u043b\u044f \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u043a\u0430\u043c\u0435\u0440:<\/p>\n<ul>\n<li>\n<p><a href=\"https:\/\/developer.apple.com\/documentation\/avfoundation\/avcapturedevice\" rel=\"noopener noreferrer nofollow\">AVCaptureDevice<\/a> &#8212; \u043a\u043b\u0430\u0441\u0441, \u044f\u0432\u043b\u044f\u044e\u0449\u0438\u0439\u0441\u044f \u043f\u0440\u044f\u043c\u044b\u043c API \u043a \u043a\u0430\u043c\u0435\u0440\u0435 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430<\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/developer.apple.com\/documentation\/avfoundation\/avcapturedeviceinput\" rel=\"noopener noreferrer nofollow\">AVCaptureDeviceInput<\/a> &#8212; \u043f\u0440\u043e\u0432\u043e\u0434\u0438\u0442 \u0434\u0430\u043d\u043d\u044b\u0435 \u043e\u0442 \u043a\u0430\u043c\u0435\u0440\u044b<\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/developer.apple.com\/documentation\/avfoundation\/avcaptureoutput\" rel=\"noopener noreferrer nofollow\">AVCaptureOutput<\/a> &#8212; \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0442\u043d\u044b\u0439 \u043a\u043b\u0430\u0441\u0441, \u043e\u0442\u0432\u0435\u0447\u0430\u044e\u0449\u0438\u0439 \u0437\u0430 \u0432\u044b\u0432\u043e\u0434 \u043a\u0430\u0440\u0442\u0438\u043d\u043a\u0438 \u043d\u0430 \u044d\u043a\u0440\u0430\u043d. \u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0435\u0433\u043e \u0441\u0430\u0431\u043a\u043b\u0430\u0441\u0441 &#8212; <a href=\"https:\/\/developer.apple.com\/documentation\/avfoundation\/avcapturephotooutput\" rel=\"noopener noreferrer nofollow\">AVCapturePhotoOutput<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/developer.apple.com\/documentation\/avfoundation\/avcapturesession\" rel=\"noopener noreferrer nofollow\">AVCaptureSession<\/a> &#8212; \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u0435\u0442 \u0441\u0432\u044f\u0437\u044c \u043c\u0435\u0436\u0434\u0443 \u0438\u043d\u043f\u0443\u0442\u043e\u043c \u0438 \u0430\u0443\u0442\u043f\u0443\u0442\u043e\u043c \u043a\u0430\u043c\u0435\u0440\u044b \u0438 \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u0437\u0430 \u0440\u0430\u0431\u043e\u0442\u0443 \u043a\u0430\u043c\u0435\u0440\u044b \u0432 \u0446\u0435\u043b\u043e\u043c.<\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/developer.apple.com\/documentation\/avfoundation\/avcapturevideopreviewlayer\" rel=\"noopener noreferrer nofollow\">AVCaptureVideoPreviewLayer<\/a> &#8212; \u0441\u0430\u0431\u043a\u043b\u0430\u0441\u0441 CALayer, \u0432\u044b\u0432\u043e\u0434\u044f\u0449\u0438\u0439 \u043d\u0430 \u044d\u043a\u0440\u0430\u043d \u0432\u0438\u0434\u0435\u043e \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0441 \u043d\u0430\u0448\u0435\u0433\u043e \u0434\u0435\u0432\u0430\u0439\u0441\u0430<\/p>\n<\/li>\n<\/ul>\n<p>\u0422\u0430\u043a\u0436\u0435 \u0441\u0435\u0433\u043e\u0434\u043d\u044f \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u043a\u043b\u0430\u0441\u0441\u044b:<\/p>\n<ul>\n<li>\n<p>\u00a0<a href=\"https:\/\/developer.apple.com\/documentation\/avfoundation\/avcapturedevice\/discoverysession\" rel=\"noopener noreferrer nofollow\">AVCaptureDevice.DiscoverySession<\/a> &#8212; \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u0447\u0435\u0441\u043a\u0438\u0439 CaptureDevice \u0434\u043b\u044f \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430 &#8212; \u0434\u0432\u043e\u0439\u043d\u044b\u0435 \u0438 \u0442\u0440\u043e\u0439\u043d\u044b\u0435 \u043a\u0430\u043c\u0435\u0440\u044b, \u0438\u043b\u0438 \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0434\u043d\u0443 \u0438\u0437 \u043d\u0438\u0445<\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/developer.apple.com\/documentation\/avfoundation\/avcapturephotosettings\" rel=\"noopener noreferrer nofollow\">AVCapturePhotoSettings<\/a> &#8212; \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043a\u0430\u043c\u0435\u0440\u044b \u0434\u043b\u044f \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0433\u043e \u0441\u043d\u0438\u043c\u043a\u0430 <\/p>\n<\/li>\n<\/ul>\n<h2>\u041f\u0438\u0448\u0435\u043c UI<\/h2>\n<p>\u041d\u0435 \u0431\u0443\u0434\u0443 \u0434\u043e\u043b\u0433\u043e \u043e\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0442\u044c\u0441\u044f \u0442\u0443\u0442. \u042f \u0441\u0434\u0435\u043b\u0430\u043b \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441, \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u043f\u043e\u0445\u043e\u0436\u0438\u0439 \u043d\u0430 \u043a\u0430\u043c\u0435\u0440\u0443 \u043e\u0442 Apple, \u043d\u043e \u0441\u043e \u0441\u0432\u043e\u0438\u043c \u043b\u044e\u0431\u0438\u043c\u044b\u043c \u0444\u0438\u043e\u043b\u0435\u0442\u043e\u0432\u044b\u043c \u043e\u0442\u0442\u0435\u043d\u043a\u043e\u043c. <\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/807\/3ab\/bfd\/8073abbfd7da2fbda922962122dd0273.PNG\" alt=\"\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u043d\u0430\u0448\u0435\u0439 \u043a\u0430\u043c\u0435\u0440\u044b\" title=\"\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u043d\u0430\u0448\u0435\u0439 \u043a\u0430\u043c\u0435\u0440\u044b\" width=\"1170\" height=\"2532\"\/><figcaption>\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u043d\u0430\u0448\u0435\u0439 \u043a\u0430\u043c\u0435\u0440\u044b<\/figcaption><\/figure>\n<p>\u0412\u0435\u0440\u0445\u043d\u0438\u0439 \u0438 \u043d\u0438\u0436\u043d\u0438\u0439 \u0431\u0430\u0440\u044b \u0438 \u0432\u0441\u0435 UI \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b \u0432\u044b\u0434\u0435\u043b\u0435\u043d\u044b \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0435 \u043a\u043b\u0430\u0441\u0441\u044b &#8212; <code>BottomBarView<\/code>, <code>LastPhotoView<\/code>, <code>CaptureImageButton<\/code> \u0438 <code>TopBarView<\/code>. \u0410 \u0442\u0430\u043a\u0436\u0435 \u0432\u044b\u043d\u0435\u0441 \u0441\u0432\u043e\u0439 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u0446\u0432\u0435\u0442 \u0434\u043b\u044f \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432 \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u0444\u0430\u0439\u043b (<code>Lavanda.swift<\/code>). \u0414\u043b\u044f \u043a\u043d\u043e\u043f\u043e\u043a \u043f\u043e\u0432\u043e\u0440\u043e\u0442\u0430 \u043a\u0430\u043c\u0435\u0440\u044b \u0438 \u0432\u0441\u043f\u044b\u0448\u043a\u0438 \u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b <a href=\"https:\/\/developer.apple.com\/sf-symbols\/\" rel=\"noopener noreferrer nofollow\">SFSymbols<\/a> \u0438 \u0441\u0442\u043e\u043b\u043a\u043d\u0443\u043b\u0441\u044f \u0441 \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u044c\u044e \u0432 \u0438\u0445 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 &#8212; \u0440\u0430\u0437\u043c\u0435\u0440 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0439, \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u0438\u0437 SF, \u043d\u0443\u0436\u043d\u043e \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0442\u044c \u0442\u043e\u0447\u043d\u043e \u043a\u0430\u043a \u0448\u0440\u0438\u0444\u0442\u044b.<\/p>\n<p>\u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0430 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442 <code>withConfiguration<\/code><\/p>\n<pre><code class=\"swift\">button.setImage(UIImage(systemName: \"arrow.triangle.2.circlepath\", withConfiguration: UIImage.SymbolConfiguration.init(pointSize: 25)), for: .normal)<\/code><\/pre>\n<p>\u041f\u043e\u0441\u043b\u0435 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u0438 \u0441\u0435\u0442\u0430\u043f\u0430 \u0431\u0430\u0440\u043e\u0432 \u043d\u0430 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0435, \u043d\u0430\u043c \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u043f\u0440\u043e\u0432\u0435\u0441\u0442\u0438 \u0434\u0435\u043b\u0435\u0433\u0430\u0442 \u043e\u0442 \u043a\u043d\u043e\u043f\u043e\u043a \u0441\u044a\u0435\u043c\u043a\u0438 \u0438 \u0441\u043c\u0435\u043d\u044b \u0444\u0440\u043e\u043d\u0442\u0430\u043b\u044c\u043d\u043e\u0439 \u0438 \u0442\u044b\u043b\u044c\u043d\u043e\u0439 \u043a\u0430\u043c\u0435\u0440:<\/p>\n<pre><code class=\"swift\">protocol BottomBarDelegate: AnyObject {\u00a0\u00a0 \u00a0  \u00a0 \u00a0 func switchCamera()  \u00a0 \u00a0 func takePhoto() }<\/code><\/pre>\n<p>\u041f\u043e\u0434\u043f\u0438\u0448\u0435\u043c <code>CamViewController<\/code> \u043f\u043e\u0434 \u0434\u0435\u043b\u0435\u0433\u0430\u0442\u0430, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c <code>CameraService<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0441\u0442\u0443\u043f\u0430\u0442\u044c \u0432 \u0440\u043e\u043b\u0438 \u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044f \u0432\u0441\u0435\u0439 \u043b\u043e\u0433\u0438\u043a\u0438. \u041f\u0440\u043e\u043a\u0438\u043d\u0435\u043c <code>CameraService<\/code> \u0432 \u0438\u043d\u0438\u0442 \u043d\u0430\u0448\u0435\u0433\u043e \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430:<\/p>\n<pre><code class=\"swift\">init(cameraService: CameraService) {  \u00a0 \u00a0 \u00a0 \u00a0 self.cameraService = cameraService  \u00a0 \u00a0 \u00a0 \u00a0 super.init(nibName: nil, bundle: nil) }<\/code><\/pre>\n<p>\u0412\u044b\u0437\u043e\u0432\u0435\u043c \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440 \u0441 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u043c \u0432 \u0438\u043d\u0438\u0442\u0435 \u0447\u0435\u0440\u0435\u0437 \u043c\u0435\u0442\u043e\u0434 <code>SceneDelegate<\/code>, \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0438 \u0443\u0432\u0438\u0434\u0438\u043c, \u0447\u0442\u043e \u0432\u0441\u0435 \u0433\u043e\u0442\u043e\u0432\u043e! \u0422\u0430\u043a\u0438 \u043f\u0435\u0440\u0435\u0439\u0434\u0435\u043c \u043a \u0441\u0430\u043c\u043e\u043c\u0443 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e\u043c\u0443 &#8212; \u043b\u043e\u0433\u0438\u043a\u0435 \u0441\u0435\u0440\u0432\u0438\u0441\u0430.<\/p>\n<h2>AVCaptureSession, inputs, outputs, AVCaptureDevice<\/h2>\n<p>\u0417\u0430\u0439\u0434\u0435\u043c \u0432 CameraService. \u041f\u0435\u0440\u0432\u043e\u0435 \u0447\u0442\u043e \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u0441\u0434\u0435\u043b\u0430\u0442\u044c &#8212; \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0432\u0432\u043e\u0434\u044b (\u0438\u043d\u043f\u0443\u0442\u044b) \u0432\u044b\u0432\u043e\u0434\u044b (\u0430\u0443\u0442\u043f\u0443\u0442\u044b) \u0438 \u0441\u0430\u043c\u0443 \u0441\u0435\u0441\u0441\u0438\u044e. \u0414\u043e\u0431\u0430\u0432\u0438\u043c \u043d\u0443\u0436\u043d\u044b\u0435 \u043f\u0440\u043e\u043f\u0435\u0440\u0442\u0438 \u0432 \u043d\u0430\u0447\u0430\u043b\u043e \u043a\u043b\u0430\u0441\u0441\u0430:<\/p>\n<pre><code class=\"swift\">    private var captureDevice: AVCaptureDevice?     private var backCamera: AVCaptureDevice?     private var frontCamera: AVCaptureDevice?      private var backInput: AVCaptureInput!     private var frontInput: AVCaptureInput!     private let cameraQueue = DispatchQueue(label: \"com.shpeklord.CapturingModelQueue\")      private var startZoom: CGFloat = 2.0     private let zoomLimit: CGFloat = 10.0      private var backCameraOn = true      weak var delegate: CameraServiceDelegate?      let captureSession = AVCaptureSession()     let photoOutput = AVCapturePhotoOutput()<\/code><\/pre>\n<p><code>captureDevice<\/code> &#8212; <strong>\u0442\u0435\u043a\u0443\u0449\u0430\u044f \u043a\u0430\u043c\u0435\u0440\u0430<\/strong>, \u0441 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0432 \u0434\u0430\u043d\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442. \u041c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0437\u0430\u0434\u043d\u0435\u0439 \u0438\u043b\u0438 \u0444\u0440\u043e\u043d\u0442\u0430\u043b\u044c\u043d\u043e\u0439.<\/p>\n<p><code>backCamera<\/code>  &#8212; \u043d\u0430\u0448\u0430 <strong>\u0437\u0430\u0434\u043d\u044f\u044f \u043a\u0430\u043c\u0435\u0440\u0430<\/strong>, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0441\u0435\u0442\u0430\u043f\u0438\u0442\u044c \u0447\u0435\u0440\u0435\u0437 DiscoverySession \u0447\u0443\u0442\u044c \u043f\u043e\u0437\u0436\u0435 <\/p>\n<p><code>frontCamera<\/code> &#8212; <strong>\u0444\u0440\u043e\u043d\u0442\u0430\u043b\u044c\u043d\u0430\u044f \u043a\u0430\u043c\u0435\u0440\u0430<\/strong><\/p>\n<p><code>backInput<\/code> &#8212; <strong>\u0438\u043d\u043f\u0443\u0442<\/strong> \u0434\u043b\u044f \u0437\u0430\u0434\u043d\u0435\u0439 \u043a\u0430\u043c\u0435\u0440\u044b<\/p>\n<p><code>frontInput<\/code> &#8212; <strong>\u0438\u043d\u043f\u0443\u0442<\/strong> \u0434\u043b\u044f \u0444\u0440\u043e\u043d\u0442\u0430\u043b\u044c\u043d\u043e\u0439 \u043a\u0430\u043c\u0435\u0440\u044b<\/p>\n<p><code>captureSession<\/code> &#8212; <strong>\u0441\u0435\u0441\u0441\u0438\u044f<\/strong>, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043c\u044b \u0441\u0435\u0439\u0447\u0430\u0441 \u0431\u0443\u0434\u0435\u043c \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c<\/p>\n<p><code>photoOutput<\/code> &#8212; <strong>\u0430\u0443\u0442\u043f\u0443\u0442<\/strong>, \u0441 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435<\/p>\n<figure class=\"bordered\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/getpro\/habr\/upload_files\/ba3\/2aa\/c61\/ba32aac61b6bed6563569e92fd49e99c.jpeg\" alt=\"\u041f\u043e\u0434\u0441\u0430\u0441\u044b \u043e\u0446\u0435\u043d\u044f\u0442\" title=\"\u041f\u043e\u0434\u0441\u0430\u0441\u044b \u043e\u0446\u0435\u043d\u044f\u0442\" width=\"512\" height=\"512\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/ba3\/2aa\/c61\/ba32aac61b6bed6563569e92fd49e99c.jpeg\" data-blurred=\"true\"\/><figcaption>\u041f\u043e\u0434\u0441\u0430\u0441\u044b \u043e\u0446\u0435\u043d\u044f\u0442<\/figcaption><\/figure>\n<p><em>\u0422\u0430\u043a\u0436\u0435 \u044f \u0441\u043e\u0437\u0434\u0430\u043b \u0431\u0443\u043b\u0435\u0432\u0443 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e, \u0433\u0440\u0430\u043d\u0438\u0446\u044b \u0437\u0443\u043c\u0430 \u0438 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u0443\u044e \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u0434\u043b\u044f \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 \u0441\u0435\u0441\u0441\u0438\u0438, \u043f\u043e\u0442\u0440\u0435\u0431\u043d\u043e\u0441\u0442\u044c \u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043e\u0431\u044a\u044f\u0441\u043d\u044e \u0447\u0443\u0442\u044c \u043f\u043e\u0437\u0436\u0435..<\/em>.<\/p>\n<p>\u0414\u0430\u043b\u0435\u0435 \u0437\u0430\u0439\u043c\u0435\u043c\u0441\u044f \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435\u043c \u0434\u0435\u0432\u0430\u0439\u0441\u0430. \u0422\u0443\u0442 \u0432 \u0438\u0433\u0440\u0443 \u0432\u0441\u0442\u0443\u043f\u0430\u0435\u0442 DiscoverySession! \u041d\u0430\u0448\u0430 \u0437\u0430\u0434\u0430\u0447\u0430 &#8212; \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u043a \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044e \u0438\u043c\u0435\u043d\u043d\u043e \u0442\u043e\u0442 \u0434\u0435\u0432\u0430\u0439\u0441, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u043d\u0430\u0448\u0438\u043c \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e\u043c. \u0415\u0441\u043b\u0438 \u0432\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043d\u0430 iPhone Pro, \u0442\u043e \u0432\u044b \u0445\u043e\u0442\u0438\u0442\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0442\u0440\u043e\u0439\u043d\u0443\u044e \u043a\u0430\u043c\u0435\u0440\u0443. \u041d\u0430 \u043d\u0435-pro \u0442\u0435\u043b\u0435\u0444\u043e\u043d\u0435 \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f \u043a\u0430\u043c\u0435\u0440\u0430 \u0441 \u0443\u043b\u044c\u0442\u0440\u0430\u0448\u0438\u0440\u0438\u043a\u043e\u043c, \u0430 \u043d\u0430 \u0431\u043e\u043b\u0435\u0435 \u0441\u0442\u0430\u0440\u044b\u0445 \u043c\u043e\u0434\u0435\u043b\u044f\u0445 \u0441 \u043e\u0434\u043d\u0438\u043c \u0448\u0438\u0440\u0438\u043a\u043e\u043c \u0438\u043b\u0438 \u0448\u0438\u0440\u0438\u043a\u043e\u043c\/\u0442\u0435\u043b\u0435\u0432\u0438\u043a\u043e\u043c, \u0432\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u0435 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0439 AVCaptureDevice. \u0411\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f DiscoverySession \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0431\u044b\u0441\u0442\u0440\u043e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c \u0442\u0438\u043f \u043a\u0430\u043c\u0435\u0440\u044b \u043d\u0430 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0435 \u0438 \u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0435\u0433\u043e \u043a \u0430\u0443\u0442\u043f\u0443\u0442\u0443. \u0412\u0438\u0434\u044b \u043a\u0430\u043c\u0435\u0440:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/d76\/65d\/ecb\/d7665decbfcd1f36d598cdd657bb0236.png\" alt=\"\u0418\u0441\u0442\u043e\u0447\u043d\u0438\u043a - https:\/\/developer.apple.com\/documentation\/avfoundation\/avcapturedevice\/devicetype\" title=\"\u0418\u0441\u0442\u043e\u0447\u043d\u0438\u043a - https:\/\/developer.apple.com\/documentation\/avfoundation\/avcapturedevice\/devicetype\" width=\"1544\" height=\"1088\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/d76\/65d\/ecb\/d7665decbfcd1f36d598cdd657bb0236.png\"\/><figcaption>\u0418\u0441\u0442\u043e\u0447\u043d\u0438\u043a &#8212; https:\/\/developer.apple.com\/documentation\/avfoundation\/avcapturedevice\/devicetype<\/figcaption><\/figure>\n<p>\u0424\u0443\u043d\u043a\u0446\u0438\u044f \u043f\u043e\u0438\u0441\u043a\u0430 \u043d\u0443\u0436\u043d\u043e\u0439 \u043a\u0430\u043c\u0435\u0440\u044b \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0442\u0430\u043a:<\/p>\n<pre><code class=\"swift\">private func currentDevice() -> AVCaptureDevice? {  \u00a0 \u00a0 \u00a0 \u00a0 let discoverySession = AVCaptureDevice.DiscoverySession(deviceTypes: [.builtInTripleCamera, .builtInDualWideCamera, .builtInDualCamera, .builtInWideAngleCamera],                                                                  mediaType: .video,                                                                  position: .back) \u00a0 \u00a0 \u00a0 \u00a0 guard let device = discoverySession.devices.first  \u00a0 \u00a0 \u00a0 \u00a0 else { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return nil \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 if device.deviceType == .builtInDualCamera || device.deviceType == .builtInWideAngleCamera { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 startZoom = 1.0 \/\/ \u043e\u0431 \u044d\u0442\u043e\u043c \u0447\u0443\u0442\u044c \u043f\u043e\u0437\u0436\u0435 \u00a0 \u00a0 \u00a0 \u00a0 }  \u00a0 \u00a0 \u00a0 \u00a0 return device  }<\/code><\/pre>\n<p>\u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0430 \u0441\u0442\u0440\u043e\u043a\u0443 \u043d\u043e\u043c\u0435\u0440 3: \u043c\u044b \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0438\u043b\u0438 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0435 \u0434\u0435\u0432\u0430\u0439\u0441\u044b \u0432 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u043e\u043c \u043f\u043e\u0440\u044f\u0434\u043a\u0435. \u0415\u0441\u043b\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f iPhone Pro, \u043f\u0435\u0440\u0432\u043e\u0439 \u0432 \u043c\u0430\u0441\u0441\u0438\u0432\u0435 \u043e\u043a\u0430\u0436\u0435\u0442\u0441\u044f \u0442\u0440\u043e\u0439\u043d\u0430\u044f \u043a\u0430\u043c\u0435\u0440\u0430. iPhone 11-14 &#8212; \u043a\u0430\u043c\u0435\u0440\u0430 \u0441 \u0443\u043b\u044c\u0442\u0440\u0430\u0448\u0438\u0440\u0438\u043a\u043e\u043c. iPhone X\/XS &#8212; \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u043a\u0430\u043c\u0435\u0440\u0443 \u0441 \u0442\u0435\u043b\u0435\u0432\u0438\u043a\u043e\u043c. \u0410 \u043d\u0430 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u043c \u043c\u0435\u0441\u0442\u0435 \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0438\u043b\u0430\u0441\u044c \u043f\u0440\u043e\u0441\u0442\u0430\u044f \u0448\u0438\u0440\u043e\u043a\u043e\u0443\u0433\u043e\u043b\u044c\u043d\u0430\u044f \u043a\u0430\u043c\u0435\u0440\u0430, \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0430\u044f \u0432 <u>\u043a\u0430\u0436\u0434\u043e\u043c<\/u> \u0434\u0435\u0432\u0430\u0439\u0441\u0435. \u0422\u0430\u043a\u0436\u0435 \u0445\u043e\u0447\u0443 \u043e\u0442\u043c\u0435\u0442\u0438\u0442\u044c, \u0447\u0442\u043e 2 \u0438 3 \u043a\u0430\u043c\u0435\u0440\u044b \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b \u0434\u043b\u044f iPhone Pro.<\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c, \u043a\u043e\u0433\u0434\u0430 \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0438 CaptureDevice, \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0447\u0430\u0442\u044c \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0443 \u0438\u043d\u043f\u0443\u0442\u043e\u0432:<\/p>\n<pre><code class=\"swift\">private func setupInputs() {  \u00a0 \u00a0 \u00a0 \u00a0 backCamera = currentDevice() \/\/ \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u044b\u0439 \u0434\u0435\u0432\u0430\u0439\u0441 \u0437\u0430\u0434\u043d\u0435\u0439 \u043a\u0430\u043c\u0435\u0440\u044b \u00a0 \u00a0 \u00a0 \u00a0 frontCamera = AVCaptureDevice.default(.builtInWideAngleCamera, for: .video, position: .front) \/\/ \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u0444\u0440\u043e\u043d\u0442\u0430\u043b\u043a\u0443  \u00a0 \u00a0 \u00a0 \u00a0 guard let backCamera = backCamera, \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 let frontCamera = frontCamera \u00a0 \u00a0 \u00a0 \u00a0 else { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return \u00a0 \u00a0 \u00a0 \u00a0 }  \u00a0 \u00a0 \u00a0 \u00a0 do { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 backInput = try AVCaptureDeviceInput(device: backCamera)  \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 guard captureSession.canAddInput(backInput) else { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 }  \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 frontInput = try AVCaptureDeviceInput(device: frontCamera)  \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 guard captureSession.canAddInput(frontInput) else { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 } catch { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 fatalError(\"could not connect camera\") \u00a0 \u00a0 \u00a0 \u00a0 }  \u00a0 \u00a0 \u00a0 \u00a0 captureDevice = backCamera \/\/ \u0441\u0435\u0442\u0430\u043f\u0438\u043c \u0437\u0430\u0434\u043d\u044e\u044e \u043a\u0430\u043c\u0435\u0440\u0443  \u00a0 \u00a0 \u00a0 \u00a0 captureSession.addInput(backInput) \/\/ \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0438\u043d\u043f\u0443\u0442 \u043a \u0441\u0435\u0441\u0441\u0438\u0438 \u00a0 \u00a0 \u00a0 \u00a0 if backCamera.deviceType == .builtInDualWideCamera || backCamera.deviceType == .builtInTripleCamera { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 updateZoom(scale: startZoom) \/\/ \u043e\u0431 \u044d\u0442\u043e\u043c \u0447\u0443\u0442\u044c \u043f\u043e\u0437\u0436\u0435 \u00a0 \u00a0 \u00a0 \u00a0 }  \u00a0}<\/code><\/pre>\n<p>\u0421\u0435\u0442\u0430\u043f\u0438\u043c \u0430\u0443\u0442\u043f\u0443\u0442:<\/p>\n<pre><code class=\"swift\">private func setupOutput() {  \u00a0 \u00a0 \u00a0 \u00a0 guard captureSession.canAddOutput(photoOutput) else { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return \u00a0 \u00a0 \u00a0 \u00a0 }  \u00a0 \u00a0 \u00a0 \u00a0 photoOutput.isHighResolutionCaptureEnabled = true \u00a0 \u00a0 \u00a0 \u00a0 photoOutput.maxPhotoQualityPrioritization = .balanced \u00a0 \u00a0 \u00a0 \u00a0 captureSession.addOutput(photoOutput) }<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c, \u043a\u043e\u0433\u0434\u0430 \u043c\u044b \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u0438\u043b\u0438 \u0441\u0435\u0442\u0430\u043f \u0438\u043d\u043f\u0443\u0442\u043e\u0432 \u0438 \u0430\u0443\u0442\u043f\u0443\u0442\u043e\u0432, \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043d\u0430\u0447\u0430\u0442\u044c \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e \u043d\u0430\u0448\u0435\u0439 AVCaptureSession. \u0414\u0435\u043b\u0430\u0435\u043c \u043c\u044b \u044d\u0442\u043e \u043d\u0430 \u0444\u043e\u043d\u043e\u0432\u043e\u043c \u043f\u043e\u0442\u043e\u043a\u0435, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e <code>captureSession.startRunning()<\/code> \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0431\u043b\u043e\u043a\u0438\u0440\u0443\u044e\u0449\u0438\u043c \u0432\u044b\u0437\u043e\u0432\u043e\u043c \u0438 \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c \u0435\u0433\u043e \u043d\u0430 \u0433\u043b\u0430\u0432\u043d\u043e\u0439 \u043e\u0447\u0435\u0440\u0435\u0434\u0438 \u043d\u0435 \u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u043f\u043e \u043f\u0440\u0438\u0447\u0438\u043d\u0435 \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u0440\u0430\u0431\u043e\u0442\u044b \u0432\u0441\u0435\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0434\u043e \u0442\u043e\u0433\u043e \u043c\u043e\u043c\u0435\u043d\u0442\u0430 \u043a\u0430\u043a \u0441\u0435\u0441\u0441\u0438\u044f \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u0441\u044f.<\/p>\n<p>\u0424\u0443\u043d\u043a\u0446\u0438\u044f \u0441\u0435\u0442\u0430\u043f\u0430 \u0441\u0435\u0441\u0441\u0438\u0438:<\/p>\n<pre><code class=\"swift\">private func setupAndStartCaptureSession() {  \u00a0 \u00a0 \u00a0 \u00a0 cameraQueue.async { [weak self] in \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 self?.captureSession.beginConfiguration() \/\/ \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u043c \u0441\u0435\u0441\u0441\u0438\u044e \u0434\u043b\u044f \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 if let canSetSessionPreset = self?.captureSession.canSetSessionPreset(.photo), canSetSessionPreset { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 self?.captureSession.sessionPreset = .photo \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \/\/ \u0434\u0435\u043b\u0430\u0435\u043c \u043f\u0440\u0435\u0441\u0435\u0442 \u0434\u043b\u044f \u0444\u043e\u0442\u043e\u0433\u0440\u0430\u0444\u0438\u0439 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 self?.captureSession.automaticallyConfiguresCaptureDeviceForWideColor = true \/\/ \u0441\u0442\u0430\u0432\u0438\u043c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0446\u0432\u0435\u0442\u043e\u0432\u043e\u0433\u043e \u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0441\u0442\u0432\u0430 RGB \u043d\u0430\u0448\u0435\u0439 \u043a\u0430\u043c\u0435\u0440\u043e\u0439  \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 self?.setupInputs() \/\/ \u043e\u043f\u0430\u043d\u044c\u043a\u0438, \u0447\u0442\u043e-\u0442\u043e \u0437\u043d\u0430\u043a\u043e\u043c\u043e\u0435 ;) \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 self?.setupOutput()\u00a0               self?.captureSession.commitConfiguration() \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 self?.captureSession.startRunning() \/\/ \u0442\u043e\u0442 \u0441\u0430\u043c\u044b\u0439 \u0431\u043b\u043e\u043a\u0438\u0440\u0443\u044e\u0449\u0438\u0439 \u0432\u044b\u0437\u043e\u0432 \u00a0 \u00a0 \u00a0 \u00a0 } }<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0432\u044b\u0437\u043e\u0432\u0435\u043c <code>setupAndStartCaptureSession()<\/code> \u0432 \u0438\u043d\u0438\u0442\u0435 \u043d\u0430\u0448\u0435\u0433\u043e <code>CameraManager<\/code>. \u0414\u043e \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u043f\u0440\u0435\u0432\u044c\u044e \u043e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u0432\u0441\u0435\u0433\u043e \u043b\u0438\u0448\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0448\u0430\u0433\u043e\u0432.<\/p>\n<h2>PreviewLayer<\/h2>\n<p>\u041f\u043e\u0436\u0430\u043b\u0443\u0439, \u0441\u0430\u043c\u0430\u044f \u043f\u0440\u043e\u0441\u0442\u0430\u044f \u0447\u0430\u0441\u0442\u044c \u0441\u0435\u0442\u0430\u043f\u0430 \u043a\u0430\u043c\u0435\u0440\u044b &#8212; \u0432\u044b\u0432\u043e\u0434 \u043f\u0440\u0435\u0432\u044c\u044e. \u0417\u0430\u0439\u0434\u0435\u043c \u0432 CamViewController \u0438 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043d\u043e\u0432\u044b\u0439 \u043f\u0440\u0438\u0432\u0430\u0442\u043d\u044b\u0439 \u043c\u0435\u0442\u043e\u0434.<\/p>\n<pre><code class=\"swift\">private func setupPreviewLayer() {         let previewLayer = AVCaptureVideoPreviewLayer(session: cameraService.captureSession) as AVCaptureVideoPreviewLayer          previewLayer.frame = view.bounds         previewLayer.videoGravity = .resizeAspectFill         view.layer.addSublayer(previewLayer) } <\/code><\/pre>\n<p>\u0418\u0437 \u043d\u0435\u0437\u043d\u0430\u043a\u043e\u043c\u043e\u0433\u043e \u0438 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e\u0433\u043e \u0437\u0434\u0435\u0441\u044c \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u043c\u0435\u0442\u0438\u0442\u044c \u043f\u0440\u043e\u043f\u0435\u0440\u0442\u0438 <a href=\"https:\/\/developer.apple.com\/documentation\/avfoundation\/avcapturevideopreviewlayer\/1386708-videogravity\" rel=\"noopener noreferrer nofollow\">videoGravity<\/a>, \u043e\u0442\u0432\u0435\u0447\u0430\u044e\u0449\u0430\u044f \u0437\u0430 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0432\u0438\u0434\u0435\u043e \u0432 \u043d\u0430\u0448\u0435\u043c \u043b\u0435\u0435\u0440\u0435. \u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u044b <code>contentMode<\/code> \u0432 UIVew. \u041c\u044b \u0432\u044b\u0431\u0440\u0430\u043b\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0443 <code>.resizeAspectFill<\/code> \u0434\u043b\u044f \u0442\u043e\u0433\u043e \u0447\u0442\u043e\u0431\u044b \u043b\u0435\u0435\u0440 \u0437\u0430\u043d\u0438\u043c\u0430\u043b \u0432\u0441\u044e \u043f\u043b\u043e\u0449\u0430\u0434\u044c \u044d\u043a\u0440\u0430\u043d\u0430. <\/p>\n<h2>\u041f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u043c\u0435\u0436\u0434\u0443 \u0444\u0440\u043e\u043d\u0442\u0430\u043b\u044c\u043d\u043e\u0439 \u0438 \u0437\u0430\u0434\u043d\u0435\u0439 \u043a\u0430\u043c\u0435\u0440\u0430\u043c\u0438<\/h2>\n<p>\u041f\u043e\u043c\u043d\u0438\u0442\u0435 \u0431\u0443\u043b\u0435\u0432\u0443 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e \u043f\u0440\u043e\u043f\u0435\u0440\u0442\u0438 CameraService? \u041d\u0430\u0441\u0442\u0430\u043b\u043e \u0435\u0435 \u0432\u0440\u0435\u043c\u044f. \u041a\u0430\u043a \u0432\u044b \u0443\u0436\u0435 \u043c\u043e\u0433\u043b\u0438 \u043f\u043e\u043d\u044f\u0442\u044c \u043f\u043e \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u044e, \u043e\u043d\u0430 \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u0437\u0430 \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u0443\u044e \u043d\u0430 \u0434\u0430\u043d\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u043a\u0430\u043c\u0435\u0440\u0443. \u041f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u043c\u0435\u0436\u0434\u0443 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u0438 \u0444\u0440\u043e\u043d\u0442\u0430\u043b\u044c\u043d\u043e\u0439 \u043a\u0430\u043c\u0435\u0440\u043e\u0439 \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435\u043c \u0438\u043d\u043f\u0443\u0442\u043e\u0432. \u0412\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0430 \u043a\u043e\u0434:<\/p>\n<pre><code class=\"swift\">func switchCameraInput() {         captureSession.beginConfiguration()         if backCameraOn {             captureSession.removeInput(backInput)             captureSession.addInput(frontInput)             captureDevice = frontCamera             backCameraOn = false         } else {             captureSession.removeInput(frontInput)             captureSession.addInput(backInput)             captureDevice = backCamera             backCameraOn = true             updateZoom(scale: startZoom) \/\/ \u043e\u0431 \u044d\u0442\u043e\u043c \u0447\u0443\u0442\u044c \u043f\u043e\u0437\u0436\u0435         }          photoOutput.connections.first?.videoOrientation = .portrait         photoOutput.connections.first?.isVideoMirrored = !backCameraOn         captureSession.commitConfiguration() }<\/code><\/pre>\n<p>\u0414\u0443\u043c\u0430\u044e, \u043f\u043e\u043d\u044f\u0442\u043d\u043e \u0447\u0442\u043e \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0432 \u0432\u0435\u0442\u043a\u0430\u0445 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u0430 If. \u0418\u0437 \u043d\u0435\u0437\u043d\u0430\u043a\u043e\u043c\u043e\u0433\u043e \u0442\u0443\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u0432\u0435 \u043f\u0440\u0435\u0434\u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0435 \u0441\u0442\u0440\u043e\u0447\u043a\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043e\u0442\u0432\u0435\u0447\u0430\u044e\u0442 \u0437\u0430 \u043e\u0440\u0438\u0435\u043d\u0442\u0430\u0446\u0438\u044e \u043d\u0430\u0448\u0438\u0445 \u0444\u043e\u0442\u043e (\u043c\u044b \u0432\u044b\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c \u043f\u043e\u0440\u0442\u0440\u0435\u0442\u043d\u0443\u044e, \u0442\u043e \u0435\u0441\u0442\u044c \u0432\u0435\u0440\u0442\u0438\u043a\u0430\u043b\u044c\u043d\u0443\u044e) \u0438 isVideoMirrored \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u0437\u0430 \u043e\u0442\u0437\u0435\u0440\u043a\u0430\u043b\u0438\u0432\u0430\u043d\u0438\u0435 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0432\u0435\u0440\u0442\u0438\u043a\u0430\u043b\u044c\u043d\u043e\u0439 \u043e\u0441\u0438. \u041d\u0443\u0436\u043d\u043e \u044d\u0442\u043e \u0434\u043b\u044f \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e\u0433\u043e \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u043f\u0440\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 \u0444\u0440\u043e\u043d\u0442\u0430\u043b\u044c\u043d\u043e\u0439 \u043a\u0430\u043c\u0435\u0440\u044b. \u0424\u0443\u043d\u043a\u0446\u0438\u044f \u043d\u0435 \u043f\u0440\u0438\u0432\u0430\u0442\u043d\u0430, \u043f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u0438\u0437 CamViewController.<\/p>\n<pre><code class=\"swift\">extension CamViewController: BottomBarDelegate {      func switchCamera() {         cameraService.switchCameraInput()     } }<\/code><\/pre>\n<p>\u0414\u0430\u043d\u043d\u0430\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0438\u0437 \u0434\u0435\u043b\u0435\u0433\u0430\u0442\u0430 \u043d\u0438\u0436\u043d\u0435\u0433\u043e \u0431\u0430\u0440\u0430 \u043f\u043e \u043d\u0430\u0436\u0430\u0442\u0438\u044e \u043a\u043d\u043e\u043f\u043a\u0438 \u0441\u043c\u0435\u043d\u044b \u043a\u0430\u043c\u0435\u0440.<\/p>\n<h2>\u041f\u0440\u043e\u0441\u0438\u043c \u0443 \u0422\u0438\u043c\u043e\u0448\u0438 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u043d\u0430 \u0441\u044a\u0435\u043c\u043a\u0443<\/h2>\n<p>\u041a\u0430\u043a \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0434\u0435\u043b\u0430\u0442\u044c \u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0442\u044c \u0444\u043e\u0442\u043e, \u0435\u0441\u043b\u0438 \u043d\u0430\u0448\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043d\u0435 \u0438\u043c\u0435\u0435\u0442 \u043f\u0440\u0430\u0432 \u043d\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u043a\u0430\u043c\u0435\u0440\u044b \u0438 \u0433\u0430\u043b\u0435\u0440\u0435\u0438? \u041d\u0443\u0436\u043d\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0438\u0442\u044c \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u043d\u0430 \u0441\u044a\u0435\u043c\u043a\u0443 \u0443 iOS. \u0414\u0435\u043b\u0430\u0435\u0442\u0441\u044f \u044d\u0442\u043e \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u043e &#8212; \u0447\u0435\u0440\u0435\u0437 info.plist<\/p>\n<p>\u041d\u0430\u043c \u043d\u0443\u0436\u043d\u044b \u0434\u0432\u0430 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u044f. \u0412\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0430 \u0441\u043a\u0440\u0438\u043d\u0448\u043e\u0442.<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/d4a\/72c\/4db\/d4a72c4db38619eae5f044bb995998f8.png\" width=\"1062\" height=\"656\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/d4a\/72c\/4db\/d4a72c4db38619eae5f044bb995998f8.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0414\u0430\u043b\u0435\u0435, \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u043f\u0440\u043e\u043f\u0438\u0441\u0430\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u044f \u043d\u0430 \u0441\u044a\u0435\u043c\u043a\u0443 \u0443 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f:<\/p>\n<pre><code class=\"swift\">private func checkPermissions() {         let cameraAuthStatus =  AVCaptureDevice.authorizationStatus(for: AVMediaType.video)         switch cameraAuthStatus {         case .authorized:             return         case .denied:             abort()         case .notDetermined:             AVCaptureDevice.requestAccess(for: AVMediaType.video, completionHandler:                                             { (authorized) in                 if(!authorized){                     abort()                 }             })         case .restricted:             abort()         @unknown default:             fatalError()         } }<\/code><\/pre>\n<h2>AVCapturePhotoCaptureDelegate &#8212; \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u0444\u043e\u0442\u043e<\/h2>\n<p>\u041c\u044b \u043f\u043b\u0430\u0432\u043d\u043e \u043f\u0440\u0438\u0431\u043b\u0438\u0436\u0430\u0435\u043c\u0441\u044f \u043a \u0444\u0438\u043d\u0430\u043b\u0443. \u041d\u0430 \u043e\u0447\u0435\u0440\u0435\u0434\u0438 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u0434\u0435\u043b\u0435\u0433\u0430\u0442\u0430 \u0444\u043e\u0442\u043e\u043a\u0430\u043c\u0435\u0440\u044b. \u0414\u043e\u0431\u0430\u0432\u0438\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u043a\u043e\u0434 \u0432 \u043a\u043e\u043d\u0435\u0446 CameraService:<\/p>\n<pre><code class=\"swift\">extension CameraService: AVCapturePhotoCaptureDelegate {      func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) {         guard error == nil else {             print(\"Fail to capture photo: \\(String(describing: error))\")             return         }         guard let imageData = photo.fileDataRepresentation() else {             return         }         guard let image = UIImage(data: imageData) else {             return         }          DispatchQueue.main.async {             self.delegate?.setPhoto(image: image) \/\/ \u0441\u0435\u0442\u0438\u043c \u0444\u043e\u0442\u043e \u043d\u0430 \u043f\u0440\u0435\u0432\u044c\u044e \u043d\u0438\u0436\u043d\u0435\u0433\u043e \u0431\u0430\u0440\u0430             UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil) \/\/ \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c \u0441\u0434\u0435\u043b\u0430\u043d\u043d\u043e\u0435 \u0444\u043e\u0442\u043e \u0432 \u0433\u0430\u043b\u0435\u0440\u0435\u044e         }     } }<\/code><\/pre>\n<p>\u0414\u0430\u043d\u043d\u0430\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0431\u0443\u0434\u0435\u0442 \u0441\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u043a\u0430\u0436\u0434\u044b\u0439 \u0440\u0430\u0437, \u043a\u043e\u0433\u0434\u0430 \u043c\u044b \u043d\u0430\u0436\u043c\u0435\u043c \u043a\u043d\u043e\u043f\u043a\u0443 \u0437\u0430\u0442\u0432\u043e\u0440\u0430. \u0421\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u043a\u043e\u0434 \u0441\u0430\u043c\u043e\u0439 \u0433\u043b\u0430\u0432\u043d\u043e\u0439 \u043a\u043d\u043e\u043f\u043a\u0438:<\/p>\n<pre><code class=\"swift\">func takePhoto() {         let photoSettings = AVCapturePhotoSettings()         photoSettings.isHighResolutionPhotoEnabled = true         photoSettings.flashMode = topBar.isTorchOn ? .on : .off         cameraService.photoOutput.capturePhoto(with: photoSettings, delegate: cameraService) }<\/code><\/pre>\n<p>\u041f\u043e\u0433\u043e\u0432\u043e\u0440\u0438\u043c \u043e\u0431 <a href=\"https:\/\/developer.apple.com\/documentation\/avfoundation\/avcapturephotosettings\" rel=\"noopener noreferrer nofollow\">AVCapturePhotoSettings<\/a>. \u042d\u0442\u043e\u0442 \u043a\u043b\u0430\u0441\u0441 \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u0437\u0430 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043d\u0430\u0448\u0435\u0439 \u043a\u0430\u043c\u0435\u0440\u044b \u0432 \u043c\u043e\u043c\u0435\u043d\u0442 \u043d\u0430\u0436\u0430\u0442\u0438\u044f \u043d\u0430 \u043a\u043d\u043e\u043f\u043a\u0443. \u041d\u0430 \u043a\u0430\u0436\u0434\u044b\u0439 \u0432\u044b\u0437\u043e\u0432 \u043a\u0430\u043c\u0435\u0440\u044b \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u043d\u043e\u0432\u044b\u0439 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 AVCapturePhotoSettings. <u>\u041f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043d\u0435\u043b\u044c\u0437\u044f.<\/u> \u0412 \u0434\u0430\u043d\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043c\u044b \u0441\u0435\u0442\u0438\u043c \u0432\u044b\u0441\u043e\u043a\u043e\u0435 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u043a\u0430\u0440\u0442\u0438\u043d\u043a\u0438 \u0438 \u0432\u043a\u043b\/\u0432\u044b\u043a\u043b \u0432\u0441\u043f\u044b\u0448\u043a\u0438, \u0437\u0430 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u0431\u0443\u043b\u0435\u0432\u0430 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0430\u044f \u0432 \u0442\u043e\u043f \u0431\u0430\u0440\u0435. \u0414\u0430\u043b\u0435\u0435 \u043c\u044b \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c \u043c\u0435\u0442\u043e\u0434 <code>capturePhoto<\/code> \u0438 \u043f\u0440\u043e\u043a\u0438\u0434\u044b\u0432\u0430\u0435\u043c \u0442\u0443\u0434\u0430 \u043d\u0430\u0448\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0438 \u043a\u0430\u043c\u0435\u0440\u0430 \u0441\u0435\u0440\u0432\u0438\u0441 \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0433\u043e \u043e\u0431\u044a\u0435\u043a\u0442\u0430. \u0412\u044b\u0437\u043e\u0432 <code>capturePhoto<\/code> \u0442\u0440\u0438\u0433\u0433\u0435\u0440\u0438\u0442 \u043c\u0435\u0442\u043e\u0434 <code>photoOutput<\/code> \u0432 \u0441\u0435\u0440\u0432\u0438\u0441\u0435, \u043e\u0442\u043a\u0443\u0434\u0430 \u043c\u044b \u0438 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0444\u043e\u0442\u043e.<\/p>\n<h2>PinchToZoom<\/h2>\n<p>\u041d\u0430\u0441\u0442\u0430\u043b\u043e \u0432\u0440\u0435\u043c\u044f \u043f\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u043d\u0430\u0448\u0435\u0439 \u043a\u0430\u043c\u0435\u0440\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043f\u0440\u0438\u0431\u043b\u0438\u0436\u0430\u0442\u044c \u0438 \u043e\u0442\u0434\u0430\u043b\u044f\u0442\u044c. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043d\u0430\u043c \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f <a href=\"https:\/\/developer.apple.com\/documentation\/uikit\/uipinchgesturerecognizer\" rel=\"noopener noreferrer nofollow\">UIPinchGestureRecognizer<\/a>. \u041f\u043e\u0441\u0442\u0430\u0432\u0438\u043c \u0435\u0433\u043e \u0432 CamViewController:<\/p>\n<pre><code class=\"swift\">private func setupZoomRecognizer() {         let zoomRecognizer = UIPinchGestureRecognizer()         zoomRecognizer.addTarget(self, action: #selector(didPinch(_:)))         view.addGestureRecognizer(zoomRecognizer) }  @objc private func didPinch(_ recognizer: UIPinchGestureRecognizer) {         if recognizer.state == .changed {             cameraService.setZoom(scale: recognizer.scale)         } }<\/code><\/pre>\n<p><code>didPinch<\/code>  \u043e\u0431\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f \u043a \u0441\u0435\u0440\u0432\u0438\u0441\u0443. \u041f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0438\u043c\u043f\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044e <code>setZoom<\/code> \u0438 \u043f\u0440\u0438\u0432\u0430\u0442\u043d\u044b\u0439 <code>updateZoom<\/code> \u0432 \u0441\u0435\u0440\u0432\u0438\u0441\u0435:<\/p>\n<pre><code class=\"swift\">func setZoom(scale: CGFloat) {         guard let zoomFactor = captureDevice?.videoZoomFactor else {             return         }         var newScaleFactor: CGFloat = 0          newScaleFactor = (scale &lt; 1.0         ? (zoomFactor - pow(zoomLimit, 1.0 - scale))         : (zoomFactor + pow(zoomLimit, (scale - 1.0) \/ 2.0)))          newScaleFactor = minMaxZoom(zoomFactor * scale)         updateZoom(scale: newScaleFactor) }  private func minMaxZoom(_ factor: CGFloat) -> CGFloat { min(max(factor, 1.0), zoomLimit) }  private func updateZoom(scale: CGFloat) {         do {             defer { captureDevice?.unlockForConfiguration() }             try captureDevice?.lockForConfiguration()             captureDevice?.videoZoomFactor = scale         } catch {             print(error.localizedDescription)         } }<\/code><\/pre>\n<p>\u0417\u0434\u0435\u0441\u044c \u0438 \u0432\u0441\u0442\u0443\u043f\u0430\u044e\u0442 \u0432 \u0438\u0433\u0440\u0443 <code>startZoom<\/code> \u0438 <code>zoomLimit.<\/code>\u041f\u0440\u0438 \u0441\u0435\u0442\u0435 \u043a\u0430\u043c\u0435\u0440\u044b \u043c\u044b \u0441\u0442\u0430\u0432\u0438\u043b\u0438 <code>startZoom<\/code> \u043d\u0430 2.0, \u0435\u0441\u043b\u0438 \u043a\u0430\u043c\u0435\u0440\u0430 \u043e\u0431\u043b\u0430\u0434\u0430\u043b\u0430 \u0443\u043b\u044c\u0442\u0440\u0430\u0448\u0438\u0440\u0438\u043a\u043e\u043c \u0438 1.0 \u0432\u043e \u0432\u0441\u0435\u0445 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0445 \u0441\u043b\u0443\u0447\u0430\u044f\u0445. \u0414\u0435\u043b\u043e \u0432 \u0442\u043e\u043c \u0447\u0442\u043e \u043a\u0430\u043c\u0435\u0440\u044b \u0441 \u0443\u043b\u044c\u0442\u0440\u0430\u0448\u0438\u0440\u0438\u043a\u043e\u043c \u0441\u0442\u0430\u0432\u044f\u0442 \u0437\u0443\u043c 0.5 (\u0432 \u043a\u043e\u0434\u0435 1.0) \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e,  \u0430 \u043d\u0430\u043c \u0431\u044b \u0445\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0442\u044c \u043a\u0430\u043c\u0435\u0440\u0443 \u043d\u0430 \u0437\u0443\u043c\u0435 1.0. <\/p>\n<p>\u041a\u043e\u0434 \u0432\u044b\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0437\u0443\u043c\u0430 \u0432\u0435\u0441\u044c\u043c\u0430 \u043f\u0440\u043e\u0441\u0442: \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0441\u043a\u0435\u0439\u043b \u0440\u0435\u043a\u043e\u0433\u043d\u0430\u0439\u0437\u0435\u0440\u0430, \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u043c \u0432 \u043a\u0430\u043a\u0443\u044e \u0441\u0442\u043e\u0440\u043e\u043d\u0443 \u0431\u044b\u043b \u0441\u0434\u0435\u043b\u0430\u043d \u0436\u0435\u0441\u0442 (\u043c\u0435\u043d\u044c\u0448\u0435 1.0 &#8212; \u0436\u0435\u0441\u0442 \u043d\u0430 \u0443\u043c\u0435\u043d\u044c\u0448\u0435\u043d\u0438\u0435) \u0438 \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0445\u0430\u0440\u0430\u043a\u0442\u0435\u0440\u0430 \u0436\u0435\u0441\u0442\u0430, \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u043c \u0440\u0430\u0441\u0441\u0447\u0435\u0442 \u043d\u043e\u0432\u043e\u0433\u043e \u0444\u0430\u043a\u0442\u043e\u0440\u0430. \u0414\u0430\u043b\u044c\u0448\u0435 \u043c\u044b \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0432\u0430\u0435\u043c \u043d\u043e\u0432\u044b\u0439 \u0444\u0430\u043a\u0442\u043e\u0440 \u0444\u0443\u043d\u043a\u0446\u0438\u0435\u0439 <code>minMaxZoom<\/code> \u0438 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c \u0431\u043e\u043b\u0435\u0435 \u043d\u0438\u0437\u043a\u043e\u0443\u0440\u0432\u043d\u0435\u0432\u0443\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u044e <code>updateZoom<\/code>, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u0432 \u0441\u0435\u0431\u044f \u043d\u043e\u0432\u044b\u0439 \u0444\u0430\u043a\u0442\u043e\u0440 \u0438 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e \u0441\u0435\u0442\u0438\u0442 \u0435\u0433\u043e \u0434\u0435\u0432\u0430\u0439\u0441\u0443. \u0421\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u043d\u0430 \u044d\u0442\u043e\u043c \u0432\u0441\u0435. <\/p>\n<h2>\u0411\u043e\u043d\u0443\u0441: Haptics \u043f\u043e \u043d\u0430\u0436\u0430\u0442\u0438\u044e \u043a\u043d\u043e\u043f\u043a\u0438<\/h2>\n<p>\u041a\u0430\u043a \u0436\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043f\u043e\u0439\u043c\u0435\u0442 \u0447\u0442\u043e \u043e\u043d \u0441\u0434\u0435\u043b\u0430\u043b \u0444\u043e\u0442\u043e? \u041c\u043e\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u044e, \u043d\u043e \u043c\u044b \u0441\u0435\u0433\u043e\u0434\u043d\u044f \u0441\u043e\u0431\u0440\u0430\u043b\u0438\u0441\u044c \u043d\u0435 \u0437\u0430 \u044d\u0442\u0438\u043c. \u042f \u0440\u0435\u0448\u0438\u043b \u043e\u043f\u043e\u0432\u0435\u0449\u0430\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u043e \u0444\u0430\u043a\u0442\u0435 \u0441\u044a\u0435\u043c\u043a\u0438 \u0442\u0430\u043a\u0442\u0438\u043b\u044c\u043d\u044b\u043c \u043e\u0442\u043a\u043b\u0438\u043a\u043e\u043c \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430. \u0412 \u043a\u043e\u0434\u0435 \u043a\u043d\u043e\u043f\u043a\u0438 \u0437\u0430\u0442\u0432\u043e\u0440\u0430 \u0438 \u0441\u043c\u0435\u043d\u044b \u043a\u0430\u043c\u0435\u0440 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u044b:<\/p>\n<pre><code class=\"swift\">let generator = UIImpactFeedbackGenerator(style: .medium) generator.impactOccurred()<\/code><\/pre>\n<p><code>.medium<\/code> \u0434\u043b\u044f \u043a\u043d\u043e\u043f\u043a\u0438 \u0437\u0430\u0442\u0432\u043e\u0440\u0430 \u0438 <code>.light<\/code> \u0434\u043b\u044f \u0441\u043c\u0435\u043d\u044b \u043a\u0430\u043c\u0435\u0440. \u041f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043e Haptics \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0447\u0438\u0442\u0430\u0442\u044c <a href=\"https:\/\/www.hackingwithswift.com\/example-code\/uikit\/how-to-generate-haptic-feedback-with-uifeedbackgenerator\" rel=\"noopener noreferrer nofollow\">\u0437\u0434\u0435\u0441\u044c<\/a>.<\/p>\n<h2>\u0417\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u0438 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0438<\/h2>\n<p>\u0421\u0435\u0433\u043e\u0434\u043d\u044f \u043c\u044b \u0441 \u0432\u0430\u043c\u0438 \u0441\u043e\u0437\u0434\u0430\u043b\u0438 \u043f\u0440\u043e\u0441\u0442\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0441 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c\u044e \u0441\u043d\u0438\u043c\u0430\u0442\u044c \u043d\u0430 \u0444\u0440\u043e\u043d\u0442\u0430\u043b\u043a\u0443 \u0438 \u0437\u0430\u0434\u043d\u044e\u044e \u043a\u0430\u043c\u0435\u0440\u044b, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0441\u043e \u0432\u0441\u043f\u044b\u0448\u043a\u043e\u0439 \u0438 \u0437\u0443\u043c\u043e\u043c. \u042d\u0442\u043e\u0433\u043e \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u0430 \u0434\u043e\u043b\u0436\u043d\u043e \u0445\u0432\u0430\u0442\u0438\u0442\u044c \u043d\u0430 \u0442\u043e \u0447\u0442\u043e\u0431\u044b \u0432\u0432\u0435\u0441\u0442\u0438 \u0432 \u043a\u0443\u0440\u0441 \u0434\u0435\u043b\u0430 \u0442\u0435\u0445, \u043a\u0442\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0430\u0447\u0430\u043b \u0440\u0430\u0431\u043e\u0442\u0443 \u0441 AVFoundation. \u0411\u0443\u0434\u0443 \u0431\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u0435\u043d \u043b\u044e\u0431\u043e\u043c\u0443 \u0444\u0438\u0434\u0431\u044d\u043a\u0443, \u0441\u043f\u0430\u0441\u0438\u0431\u043e \u0437\u0430 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435. <\/p>\n<p><strong>\u0418\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0438<\/strong>:<\/p>\n<ul>\n<li>\n<p><a href=\"https:\/\/www.objc.io\/issues\/21-camera-and-photos\/camera-capture-on-ios\/\" rel=\"noopener noreferrer nofollow\"><u>\u0421\u0442\u0430\u0442\u044c\u044f \u043f\u043e AVFoundation \u043e\u0442 objc.io<\/u><\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/developer.apple.com\/tutorials\/sample-apps\/capturingphotos-camerapreview\" rel=\"noopener noreferrer nofollow\"><u>\u041e\u0431\u0443\u0447\u0430\u044e\u0449\u0430\u044f \u0441\u0442\u0430\u0442\u044c\u044f \u043e\u0442 Apple (SwiftUI)<\/u><\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/developer.apple.com\/documentation\/avfoundation\/capture_setup\/avcam_building_a_camera_app\" rel=\"noopener noreferrer nofollow\"><u>\u0415\u0449\u0435 \u043e\u0434\u0438\u043d \u0442\u0443\u0442\u043e\u0440\u0438\u0430\u043b \u043e\u0442 Apple<\/u><\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/medium.com\/@rafal.grodzinski\/avfoundation-quick-start-part-1-4-introduction-and-session-setup-371897321205\" rel=\"noopener noreferrer nofollow\"><u>\u0421\u0435\u0440\u0438\u044f \u0441\u0442\u0430\u0442\u0435\u0439 \u043d\u0430 \u043c\u0435\u0434\u0438\u0443\u043c\u0435 1\u00a0<\/u><\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/medium.com\/@rizwanm\/https-medium-com-rizwanm-swift-camera-part-1-c38b8b773b2\" rel=\"noopener noreferrer nofollow\"><u>\u0421\u0435\u0440\u0438\u044f \u0441\u0442\u0430\u0442\u0435\u0439 \u043d\u0430 \u043c\u0435\u0434\u0438\u0443\u043c\u0435 2<\/u><\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/medium.com\/@barbulescualex\/making-a-custom-camera-in-ios-ea44e3087563\" rel=\"noopener noreferrer nofollow\">\u0415\u0449\u0435 \u043e\u0434\u043d\u0430 \u0441\u0442\u0430\u0442\u044c\u044f \u043d\u0430 \u043c\u0435\u0434\u0438\u0443\u043c\u0435<\/a><\/p>\n<\/li>\n<\/ul>\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\/post\/709558\/\"> https:\/\/habr.com\/ru\/post\/709558\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<h2>Hello World!<\/h2>\n<p>\u0412\u0441\u0435\u043c \u043f\u0440\u0438\u0432\u0435\u0442, \u043c\u0435\u043d\u044f \u0437\u043e\u0432\u0443\u0442 \u042d\u043c\u0438\u043b\u044c. \u042f <u>\u043c\u043b\u0430\u0434\u0448\u0438\u0439<\/u> iOS \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0432 &#171;3\u0414 \u041f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0430&#187; (\u0434\u0436\u0443\u043d\u0438\u043e\u0440 \u043f\u0438\u0448\u0435\u0442 \u0441\u0442\u0430\u0442\u044c\u044e, \u0434\u0430\u0434\u0430 \u044f) \u0438 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043c\u0435\u0441\u044f\u0446\u0435\u0432 \u043d\u0430\u0437\u0430\u0434 \u044f \u0441\u0442\u043e\u043b\u043a\u043d\u0443\u043b\u0441\u044f \u0441 \u043a\u0430\u043c\u0435\u0440\u043e\u0439 \u043d\u0430 <a href=\"https:\/\/developer.apple.com\/documentation\/avfoundation\" rel=\"noopener noreferrer nofollow\">AVFoundation<\/a>: \u043c\u043d\u0435 \u043d\u0443\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043a\u0430\u043c\u0435\u0440\u0435 \u043e\u043f\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u044b\u0439 \u0437\u0443\u043c \u0441 1.0\u0445 \u0434\u043e 0.5\u0445, \u0435\u0441\u043b\u0438 \u043a\u0430\u043c\u0435\u0440\u0430 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0442\u0430\u043a\u043e\u0439 \u0437\u0443\u043c. \u041c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u043e\u0432 \u044f \u043d\u0430\u0448\u0435\u043b \u043e\u0447\u0435\u043d\u044c \u043c\u043d\u043e\u0433\u043e, \u043f\u043e\u043f\u0440\u0430\u043a\u0442\u0438\u043a\u043e\u0432\u0430\u043b\u0441\u044f \u043d\u0430 \u0442\u0435\u0441\u0442\u043e\u0432\u043e\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0435, \u0432\u044b\u0432\u0435\u0440\u0438\u043b \u043b\u0443\u0447\u0448\u0443\u044e \u0444\u043e\u0440\u043c\u0443\u043b\u0443 \u0434\u043b\u044f \u0437\u0443\u043c\u0430 \u0438 \u0438\u043d\u0442\u0435\u0433\u0440\u0438\u0440\u043e\u0432\u0430\u043b \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u0432 \u043f\u0440\u043e\u0434. \u041f\u043e\u0441\u043b\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0437\u0430\u0434\u0430\u0447\u0438 \u044f \u0437\u0430\u043c\u0435\u0442\u0438\u043b, \u0447\u0442\u043e \u043d\u0435 \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u043b \u043d\u0438 \u043e\u0434\u043d\u043e\u0433\u043e \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u0430 \u043d\u0430 \u0440\u0443\u0441\u0441\u043a\u043e\u043c, \u043a\u0440\u043e\u043c\u0435 \u043e\u0434\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438 \u043d\u0430 \u0425\u0430\u0431\u0440\u0435, \u0434\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0439 2013 \u0433\u043e\u0434\u043e\u043c. \u0421\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u044d\u0442\u043e \u043d\u0430\u0431\u043b\u044e\u0434\u0435\u043d\u0438\u0435 \u0438 \u043d\u0430\u0432\u0435\u043b\u043e \u043c\u0435\u043d\u044f \u043d\u0430 \u043c\u044b\u0441\u043b\u044c \u043e \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u0438 \u0441\u0432\u043e\u0435\u0439 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438 \u043e\u0431 AVFoundation &#8212; \u043a\u0430\u043c\u0435\u0440\u0435. \u042f \u0440\u0435\u0448\u0438\u043b \u043d\u0430\u0447\u0430\u0442\u044c \u0441 \u043f\u0440\u043e\u0435\u043a\u0442\u0430, \u043d\u0430 \u0431\u0430\u0437\u0435 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043c\u044b \u0441\u0435\u0433\u043e\u0434\u043d\u044f \u0441 \u0432\u0430\u043c\u0438 \u0438\u0437\u0443\u0447\u0438\u043c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 AVFoundation \u043d\u0430 \u043b\u043e\u043d\u0435 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u043a\u0430\u043c\u0435\u0440\u043e\u0439 (\u0430 \u0432\u043e\u043e\u0431\u0449\u0435 \u0442\u0430\u043c \u043c\u043e\u0436\u043d\u043e \u0435\u0449\u0435 \u0438 \u0441\u043e \u0437\u0432\u0443\u043a\u043e\u043c \u043f\u043e\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c). \u042d\u0442\u043e \u043c\u043e\u044f \u043f\u0435\u0440\u0432\u0430\u044f \u0441\u0442\u0430\u0442\u044c\u044f, \u043d\u043e \u044f \u043d\u0435 \u0431\u0443\u0434\u0443 \u043f\u0440\u043e\u0441\u0438\u0442\u044c \u0432\u0430\u0441 \u043e\u0442\u043d\u0435\u0441\u0442\u0438\u0441\u044c \u043a \u043d\u0435\u0439 \u0441\u043d\u0438\u0441\u0445\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e. \u0414\u0443\u043c\u0430\u044e, \u044d\u0442\u043e\u0442 \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043b\u0435\u0437\u0435\u043d \u043d\u043e\u0432\u0438\u0447\u043a\u0430\u043c \u0438 \u0434\u0436\u0443\u043d\u0430\u043c, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0438\u043a\u043e\u0433\u0434\u0430 \u043d\u0435 \u0441\u0442\u0430\u043b\u043a\u0438\u0432\u0430\u043b\u0438\u0441\u044c \u0441 AVFoundation \u0438 \u043d\u0435 \u0437\u043d\u0430\u044e\u0442, \u043a\u0430\u043a\u0430\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043f\u043e \u044d\u0442\u043e\u0439 \u0442\u0435\u043c\u0435 \u0440\u0435\u0430\u043b\u044c\u043d\u043e \u0433\u043e\u0434\u043d\u0430.<\/p>\n<p>\u041d\u0443 \u0447\u0442\u043e \u0436, \u043f\u043e\u0435\u0445\u0430\u043b\u0438.<\/p>\n<p>\u041f\u043e\u043b\u043d\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442: <a href=\"https:\/\/github.com\/Wtclrsnd\/RealTrapCamera\" rel=\"noopener noreferrer nofollow\">https:\/\/github.com\/Wtclrsnd\/RealTrapCamera<\/a> <\/p>\n<p><strong>\u041d\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u044f<\/strong><\/p>\n<ul>\n<li>\n<p>\u0427\u0442\u043e \u0442\u0430\u043a\u043e\u0435 AVFoundation<\/p>\n<\/li>\n<li>\n<p>\u041f\u0438\u0448\u0435\u043c UI<\/p>\n<\/li>\n<li>\n<p>AVCaptureSession, inputs, outputs, AVCaptureDevice<\/p>\n<\/li>\n<li>\n<p>PreviewLayer<\/p>\n<\/li>\n<li>\n<p>\u041f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u043c\u0435\u0436\u0434\u0443 \u0444\u0440\u043e\u043d\u0442\u0430\u043b\u044c\u043d\u043e\u0439 \u0438 \u0437\u0430\u0434\u043d\u0435\u0439 \u043a\u0430\u043c\u0435\u0440\u0430\u043c\u0438<\/p>\n<\/li>\n<li>\n<p>\u041f\u0440\u043e\u0441\u0438\u043c \u0443 \u0422\u0438\u043c\u043e\u0448\u0438 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u043d\u0430 \u0441\u044a\u0435\u043c\u043a\u0443<\/p>\n<\/li>\n<li>\n<p>AVCapturePhotoCaptureDelegate &#8212; \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u0444\u043e\u0442\u043e<\/p>\n<\/li>\n<li>\n<p>PinchToZoom<\/p>\n<\/li>\n<li>\n<p>\u0411\u043e\u043d\u0443\u0441: Haptics \u043f\u043e \u043d\u0430\u0436\u0430\u0442\u0438\u044e \u043a\u043d\u043e\u043f\u043a\u0438<\/p>\n<\/li>\n<li>\n<p>\u0417\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u0438 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0438<\/p>\n<\/li>\n<\/ul>\n<h2>\u0427\u0442\u043e \u0442\u0430\u043a\u043e\u0435 AVFoundation?<\/h2>\n<p>\u041f\u0440\u043e\u0446\u0438\u0442\u0438\u0440\u0443\u044e Apple: <em>AVFoundation &#8212; \u044d\u0442\u043e \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0430\u0443\u0434\u0438\u043e\u0432\u0438\u0437\u0443\u0430\u043b\u044c\u043d\u044b\u043c\u0438 \u043c\u0435\u0434\u0438\u0430\u0444\u0430\u0439\u043b\u0430\u043c\u0438 \u043d\u0430 iOS, macOS, watchOS \u0438 tvOS. \u0411\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f AVFoundation \u043c\u043e\u0436\u043d\u043e \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u044c, <u>\u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c<\/u> \u0438 \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0444\u0430\u0439\u043b\u044b QuickTime \u0438 \u0444\u0430\u0439\u043b\u044b MPEG-4, \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u044c \u043f\u043e\u0442\u043e\u043a\u0438 HLS \u0438 \u0432\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0442\u044c \u043c\u043e\u0449\u043d\u0443\u044e \u043c\u0443\u043b\u044c\u0442\u0438\u043c\u0435\u0434\u0438\u0439\u043d\u0443\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0432 \u0441\u0432\u043e\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f.<\/em><\/p>\n<p>\u041a\u0430\u043a \u0441\u0442\u0430\u043b\u043e \u043f\u043e\u043d\u044f\u0442\u043d\u043e \u0438\u0437 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f, AVFoundation \u044d\u0442\u043e \u0448\u0438\u0440\u043e\u043a\u043e\u043f\u0440\u043e\u0444\u0438\u043b\u044c\u043d\u044b\u0439 \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a \u0441 \u0431\u043e\u043b\u044c\u0448\u0438\u043c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e\u043c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0435\u0439, \u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u0445\u043e\u0434\u0438\u0442 \u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0444\u043e\u0442\u043e \u0438 \u0432\u0438\u0434\u0435\u043e, \u043d\u0430 \u0447\u0435\u043c \u043c\u044b \u0441\u0435\u0433\u043e\u0434\u043d\u044f \u0441 \u0432\u0430\u043c\u0438 \u0438 \u0441\u043a\u043e\u043d\u0446\u0435\u043d\u0442\u0440\u0438\u0440\u0443\u0435\u043c\u0441\u044f. \u0424\u043e\u0442\u043e \u0438 \u0432\u0438\u0434\u0435\u043e \u043a\u0430\u043c\u0435\u0440\u044b &#8212; \u0441\u0430\u043c\u044b\u0439 \u0447\u0430\u0441\u0442\u044b\u0439 \u043a\u0435\u0439\u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f AVFoundation. <\/p>\n<figure class=\"full-width\"><figcaption>\u0418\u0441\u0442\u043e\u0447\u043d\u0438\u043a: https:\/\/medium.com\/@divya.nayak\/learning-avfoundation-part-1-c761aad183ad<\/figcaption><\/figure>\n<p>\u041f\u043e\u0434 AVFoundation &#171;\u043b\u0435\u0436\u0430\u0442&#187; CoreAudio, CoreMedia &#8212; \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u044f \u0433\u043e\u0432\u043e\u0440\u044f\u0442 \u0441\u0430\u043c\u0438 \u0437\u0430 \u0441\u0435\u0431\u044f. \u0410 \u0442\u0430\u043a\u0436\u0435 CoreAnimation \u0434\u043b\u044f \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0438\u0435\u0440\u0430\u0440\u0445\u0438\u0438 \u0432\u0438\u0434\u0435\u043e \u0438 \u043f\u0440\u0435\u0437\u0435\u043d\u0442\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0433\u043e \u0441\u043b\u043e\u044f. <\/p>\n<p>\u0423\u0433\u043b\u0443\u0431\u0438\u043c\u0441\u044f \u0432 \u0442\u0435\u043c\u0443 \u0441\u044a\u0435\u043c\u043e\u043a \u0444\u043e\u0442\u043e. \u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u044e \u0432\u0430\u043c \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u043a\u043b\u0430\u0441\u0441\u044b AVFoundation, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0449\u0438\u0435\u0441\u044f \u0434\u043b\u044f \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u043a\u0430\u043c\u0435\u0440:<\/p>\n<ul>\n<li>\n<p><a href=\"https:\/\/developer.apple.com\/documentation\/avfoundation\/avcapturedevice\" rel=\"noopener noreferrer nofollow\">AVCaptureDevice<\/a> &#8212; \u043a\u043b\u0430\u0441\u0441, \u044f\u0432\u043b\u044f\u044e\u0449\u0438\u0439\u0441\u044f \u043f\u0440\u044f\u043c\u044b\u043c API \u043a \u043a\u0430\u043c\u0435\u0440\u0435 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430<\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/developer.apple.com\/documentation\/avfoundation\/avcapturedeviceinput\" rel=\"noopener noreferrer nofollow\">AVCaptureDeviceInput<\/a> &#8212; \u043f\u0440\u043e\u0432\u043e\u0434\u0438\u0442 \u0434\u0430\u043d\u043d\u044b\u0435 \u043e\u0442 \u043a\u0430\u043c\u0435\u0440\u044b<\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/developer.apple.com\/documentation\/avfoundation\/avcaptureoutput\" rel=\"noopener noreferrer nofollow\">AVCaptureOutput<\/a> &#8212; \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0442\u043d\u044b\u0439 \u043a\u043b\u0430\u0441\u0441, \u043e\u0442\u0432\u0435\u0447\u0430\u044e\u0449\u0438\u0439 \u0437\u0430 \u0432\u044b\u0432\u043e\u0434 \u043a\u0430\u0440\u0442\u0438\u043d\u043a\u0438 \u043d\u0430 \u044d\u043a\u0440\u0430\u043d. \u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0435\u0433\u043e \u0441\u0430\u0431\u043a\u043b\u0430\u0441\u0441 &#8212; <a href=\"https:\/\/developer.apple.com\/documentation\/avfoundation\/avcapturephotooutput\" rel=\"noopener noreferrer nofollow\">AVCapturePhotoOutput<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/developer.apple.com\/documentation\/avfoundation\/avcapturesession\" rel=\"noopener noreferrer nofollow\">AVCaptureSession<\/a> &#8212; \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u0435\u0442 \u0441\u0432\u044f\u0437\u044c \u043c\u0435\u0436\u0434\u0443 \u0438\u043d\u043f\u0443\u0442\u043e\u043c \u0438 \u0430\u0443\u0442\u043f\u0443\u0442\u043e\u043c \u043a\u0430\u043c\u0435\u0440\u044b \u0438 \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u0437\u0430 \u0440\u0430\u0431\u043e\u0442\u0443 \u043a\u0430\u043c\u0435\u0440\u044b \u0432 \u0446\u0435\u043b\u043e\u043c.<\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/developer.apple.com\/documentation\/avfoundation\/avcapturevideopreviewlayer\" rel=\"noopener noreferrer nofollow\">AVCaptureVideoPreviewLayer<\/a> &#8212; \u0441\u0430\u0431\u043a\u043b\u0430\u0441\u0441 CALayer, \u0432\u044b\u0432\u043e\u0434\u044f\u0449\u0438\u0439 \u043d\u0430 \u044d\u043a\u0440\u0430\u043d \u0432\u0438\u0434\u0435\u043e \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0441 \u043d\u0430\u0448\u0435\u0433\u043e \u0434\u0435\u0432\u0430\u0439\u0441\u0430<\/p>\n<\/li>\n<\/ul>\n<p>\u0422\u0430\u043a\u0436\u0435 \u0441\u0435\u0433\u043e\u0434\u043d\u044f \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u043a\u043b\u0430\u0441\u0441\u044b:<\/p>\n<ul>\n<li>\n<p>\u00a0<a href=\"https:\/\/developer.apple.com\/documentation\/avfoundation\/avcapturedevice\/discoverysession\" rel=\"noopener noreferrer nofollow\">AVCaptureDevice.DiscoverySession<\/a> &#8212; \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u0447\u0435\u0441\u043a\u0438\u0439 CaptureDevice \u0434\u043b\u044f \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430 &#8212; \u0434\u0432\u043e\u0439\u043d\u044b\u0435 \u0438 \u0442\u0440\u043e\u0439\u043d\u044b\u0435 \u043a\u0430\u043c\u0435\u0440\u044b, \u0438\u043b\u0438 \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0434\u043d\u0443 \u0438\u0437 \u043d\u0438\u0445<\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/developer.apple.com\/documentation\/avfoundation\/avcapturephotosettings\" rel=\"noopener noreferrer nofollow\">AVCapturePhotoSettings<\/a> &#8212; \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043a\u0430\u043c\u0435\u0440\u044b \u0434\u043b\u044f \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0433\u043e \u0441\u043d\u0438\u043c\u043a\u0430 <\/p>\n<\/li>\n<\/ul>\n<h2>\u041f\u0438\u0448\u0435\u043c UI<\/h2>\n<p>\u041d\u0435 \u0431\u0443\u0434\u0443 \u0434\u043e\u043b\u0433\u043e \u043e\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0442\u044c\u0441\u044f \u0442\u0443\u0442. \u042f \u0441\u0434\u0435\u043b\u0430\u043b \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441, \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u043f\u043e\u0445\u043e\u0436\u0438\u0439 \u043d\u0430 \u043a\u0430\u043c\u0435\u0440\u0443 \u043e\u0442 Apple, \u043d\u043e \u0441\u043e \u0441\u0432\u043e\u0438\u043c \u043b\u044e\u0431\u0438\u043c\u044b\u043c \u0444\u0438\u043e\u043b\u0435\u0442\u043e\u0432\u044b\u043c \u043e\u0442\u0442\u0435\u043d\u043a\u043e\u043c. <\/p>\n<figure class=\"full-width\"><figcaption>\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u043d\u0430\u0448\u0435\u0439 \u043a\u0430\u043c\u0435\u0440\u044b<\/figcaption><\/figure>\n<p>\u0412\u0435\u0440\u0445\u043d\u0438\u0439 \u0438 \u043d\u0438\u0436\u043d\u0438\u0439 \u0431\u0430\u0440\u044b \u0438 \u0432\u0441\u0435 UI \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b \u0432\u044b\u0434\u0435\u043b\u0435\u043d\u044b \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0435 \u043a\u043b\u0430\u0441\u0441\u044b &#8212; <code>BottomBarView<\/code>, <code>LastPhotoView<\/code>, <code>CaptureImageButton<\/code> \u0438 <code>TopBarView<\/code>. \u0410 \u0442\u0430\u043a\u0436\u0435 \u0432\u044b\u043d\u0435\u0441 \u0441\u0432\u043e\u0439 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u0446\u0432\u0435\u0442 \u0434\u043b\u044f \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432 \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u0444\u0430\u0439\u043b (<code>Lavanda.swift<\/code>). \u0414\u043b\u044f \u043a\u043d\u043e\u043f\u043e\u043a \u043f\u043e\u0432\u043e\u0440\u043e\u0442\u0430 \u043a\u0430\u043c\u0435\u0440\u044b \u0438 \u0432\u0441\u043f\u044b\u0448\u043a\u0438 \u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b <a href=\"https:\/\/developer.apple.com\/sf-symbols\/\" rel=\"noopener noreferrer nofollow\">SFSymbols<\/a> \u0438 \u0441\u0442\u043e\u043b\u043a\u043d\u0443\u043b\u0441\u044f \u0441 \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u044c\u044e \u0432 \u0438\u0445 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 &#8212; \u0440\u0430\u0437\u043c\u0435\u0440 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0439, \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u0438\u0437 SF, \u043d\u0443\u0436\u043d\u043e \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0442\u044c \u0442\u043e\u0447\u043d\u043e \u043a\u0430\u043a \u0448\u0440\u0438\u0444\u0442\u044b.<\/p>\n<p>\u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0430 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442 <code>withConfiguration<\/code><\/p>\n<pre><code class=\"swift\">button.setImage(UIImage(systemName: \"arrow.triangle.2.circlepath\", withConfiguration: UIImage.SymbolConfiguration.init(pointSize: 25)), for: .normal)<\/code><\/pre>\n<p>\u041f\u043e\u0441\u043b\u0435 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u0438 \u0441\u0435\u0442\u0430\u043f\u0430 \u0431\u0430\u0440\u043e\u0432 \u043d\u0430 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0435, \u043d\u0430\u043c \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u043f\u0440\u043e\u0432\u0435\u0441\u0442\u0438 \u0434\u0435\u043b\u0435\u0433\u0430\u0442 \u043e\u0442 \u043a\u043d\u043e\u043f\u043e\u043a \u0441\u044a\u0435\u043c\u043a\u0438 \u0438 \u0441\u043c\u0435\u043d\u044b \u0444\u0440\u043e\u043d\u0442\u0430\u043b\u044c\u043d\u043e\u0439 \u0438 \u0442\u044b\u043b\u044c\u043d\u043e\u0439 \u043a\u0430\u043c\u0435\u0440:<\/p>\n<pre><code class=\"swift\">protocol BottomBarDelegate: AnyObject {\u00a0\u00a0 \u00a0  \u00a0 \u00a0 func switchCamera()  \u00a0 \u00a0 func takePhoto() }<\/code><\/pre>\n<p>\u041f\u043e\u0434\u043f\u0438\u0448\u0435\u043c <code>CamViewController<\/code> \u043f\u043e\u0434 \u0434\u0435\u043b\u0435\u0433\u0430\u0442\u0430, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c <code>CameraService<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0441\u0442\u0443\u043f\u0430\u0442\u044c \u0432 \u0440\u043e\u043b\u0438 \u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044f \u0432\u0441\u0435\u0439 \u043b\u043e\u0433\u0438\u043a\u0438. \u041f\u0440\u043e\u043a\u0438\u043d\u0435\u043c <code>CameraService<\/code> \u0432 \u0438\u043d\u0438\u0442 \u043d\u0430\u0448\u0435\u0433\u043e \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430:<\/p>\n<pre><code class=\"swift\">init(cameraService: CameraService) {  \u00a0 \u00a0 \u00a0 \u00a0 self.cameraService = cameraService  \u00a0 \u00a0 \u00a0 \u00a0 super.init(nibName: nil, bundle: nil) }<\/code><\/pre>\n<p>\u0412\u044b\u0437\u043e\u0432\u0435\u043c \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440 \u0441 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u043c \u0432 \u0438\u043d\u0438\u0442\u0435 \u0447\u0435\u0440\u0435\u0437 \u043c\u0435\u0442\u043e\u0434 <code>SceneDelegate<\/code>, \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0438 \u0443\u0432\u0438\u0434\u0438\u043c, \u0447\u0442\u043e \u0432\u0441\u0435 \u0433\u043e\u0442\u043e\u0432\u043e! \u0422\u0430\u043a\u0438 \u043f\u0435\u0440\u0435\u0439\u0434\u0435\u043c \u043a \u0441\u0430\u043c\u043e\u043c\u0443 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e\u043c\u0443 &#8212; \u043b\u043e\u0433\u0438\u043a\u0435 \u0441\u0435\u0440\u0432\u0438\u0441\u0430.<\/p>\n<h2>AVCaptureSession, inputs, outputs, AVCaptureDevice<\/h2>\n<p>\u0417\u0430\u0439\u0434\u0435\u043c \u0432 CameraService. \u041f\u0435\u0440\u0432\u043e\u0435 \u0447\u0442\u043e \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u0441\u0434\u0435\u043b\u0430\u0442\u044c &#8212; \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0432\u0432\u043e\u0434\u044b (\u0438\u043d\u043f\u0443\u0442\u044b) \u0432\u044b\u0432\u043e\u0434\u044b (\u0430\u0443\u0442\u043f\u0443\u0442\u044b) \u0438 \u0441\u0430\u043c\u0443 \u0441\u0435\u0441\u0441\u0438\u044e. \u0414\u043e\u0431\u0430\u0432\u0438\u043c \u043d\u0443\u0436\u043d\u044b\u0435 \u043f\u0440\u043e\u043f\u0435\u0440\u0442\u0438 \u0432 \u043d\u0430\u0447\u0430\u043b\u043e \u043a\u043b\u0430\u0441\u0441\u0430:<\/p>\n<pre><code class=\"swift\">    private var captureDevice: AVCaptureDevice?     private var backCamera: AVCaptureDevice?     private var frontCamera: AVCaptureDevice?      private var backInput: AVCaptureInput!     private var frontInput: AVCaptureInput!     private let cameraQueue = DispatchQueue(label: \"com.shpeklord.CapturingModelQueue\")      private var startZoom: CGFloat = 2.0     private let zoomLimit: CGFloat = 10.0      private var backCameraOn = true      weak var delegate: CameraServiceDelegate?      let captureSession = AVCaptureSession()     let photoOutput = AVCapturePhotoOutput()<\/code><\/pre>\n<p><code>captureDevice<\/code> &#8212; <strong>\u0442\u0435\u043a\u0443\u0449\u0430\u044f \u043a\u0430\u043c\u0435\u0440\u0430<\/strong>, \u0441 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0432 \u0434\u0430\u043d\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442. \u041c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0437\u0430\u0434\u043d\u0435\u0439 \u0438\u043b\u0438 \u0444\u0440\u043e\u043d\u0442\u0430\u043b\u044c\u043d\u043e\u0439.<\/p>\n<p><code>backCamera<\/code>  &#8212; \u043d\u0430\u0448\u0430 <strong>\u0437\u0430\u0434\u043d\u044f\u044f \u043a\u0430\u043c\u0435\u0440\u0430<\/strong>, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0441\u0435\u0442\u0430\u043f\u0438\u0442\u044c \u0447\u0435\u0440\u0435\u0437 DiscoverySession \u0447\u0443\u0442\u044c \u043f\u043e\u0437\u0436\u0435 <\/p>\n<p><code>frontCamera<\/code> &#8212; <strong>\u0444\u0440\u043e\u043d\u0442\u0430\u043b\u044c\u043d\u0430\u044f \u043a\u0430\u043c\u0435\u0440\u0430<\/strong><\/p>\n<p><code>backInput<\/code> &#8212; <strong>\u0438\u043d\u043f\u0443\u0442<\/strong> \u0434\u043b\u044f \u0437\u0430\u0434\u043d\u0435\u0439 \u043a\u0430\u043c\u0435\u0440\u044b<\/p>\n<p><code>frontInput<\/code> &#8212; <strong>\u0438\u043d\u043f\u0443\u0442<\/strong> \u0434\u043b\u044f \u0444\u0440\u043e\u043d\u0442\u0430\u043b\u044c\u043d\u043e\u0439 \u043a\u0430\u043c\u0435\u0440\u044b<\/p>\n<p><code>captureSession<\/code> &#8212; <strong>\u0441\u0435\u0441\u0441\u0438\u044f<\/strong>, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043c\u044b \u0441\u0435\u0439\u0447\u0430\u0441 \u0431\u0443\u0434\u0435\u043c \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c<\/p>\n<p><code>photoOutput<\/code> &#8212; <strong>\u0430\u0443\u0442\u043f\u0443\u0442<\/strong>, \u0441 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435<\/p>\n<figure class=\"bordered\"><figcaption>\u041f\u043e\u0434\u0441\u0430\u0441\u044b \u043e\u0446\u0435\u043d\u044f\u0442<\/figcaption><\/figure>\n<p><em>\u0422\u0430\u043a\u0436\u0435 \u044f \u0441\u043e\u0437\u0434\u0430\u043b \u0431\u0443\u043b\u0435\u0432\u0443 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e, \u0433\u0440\u0430\u043d\u0438\u0446\u044b \u0437\u0443\u043c\u0430 \u0438 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u0443\u044e \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u0434\u043b\u044f \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 \u0441\u0435\u0441\u0441\u0438\u0438, \u043f\u043e\u0442\u0440\u0435\u0431\u043d\u043e\u0441\u0442\u044c \u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043e\u0431\u044a\u044f\u0441\u043d\u044e \u0447\u0443\u0442\u044c \u043f\u043e\u0437\u0436\u0435..<\/em>.<\/p>\n<p>\u0414\u0430\u043b\u0435\u0435 \u0437\u0430\u0439\u043c\u0435\u043c\u0441\u044f \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435\u043c \u0434\u0435\u0432\u0430\u0439\u0441\u0430. \u0422\u0443\u0442 \u0432 \u0438\u0433\u0440\u0443 \u0432\u0441\u0442\u0443\u043f\u0430\u0435\u0442 DiscoverySession! \u041d\u0430\u0448\u0430 \u0437\u0430\u0434\u0430\u0447\u0430 &#8212; \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u043a \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044e \u0438\u043c\u0435\u043d\u043d\u043e \u0442\u043e\u0442 \u0434\u0435\u0432\u0430\u0439\u0441, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u043d\u0430\u0448\u0438\u043c \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e\u043c. \u0415\u0441\u043b\u0438 \u0432\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043d\u0430 iPhone Pro, \u0442\u043e \u0432\u044b \u0445\u043e\u0442\u0438\u0442\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0442\u0440\u043e\u0439\u043d\u0443\u044e \u043a\u0430\u043c\u0435\u0440\u0443. \u041d\u0430 \u043d\u0435-pro \u0442\u0435\u043b\u0435\u0444\u043e\u043d\u0435 \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f \u043a\u0430\u043c\u0435\u0440\u0430 \u0441 \u0443\u043b\u044c\u0442\u0440\u0430\u0448\u0438\u0440\u0438\u043a\u043e\u043c, \u0430 \u043d\u0430 \u0431\u043e\u043b\u0435\u0435 \u0441\u0442\u0430\u0440\u044b\u0445 \u043c\u043e\u0434\u0435\u043b\u044f\u0445 \u0441 \u043e\u0434\u043d\u0438\u043c \u0448\u0438\u0440\u0438\u043a\u043e\u043c \u0438\u043b\u0438 \u0448\u0438\u0440\u0438\u043a\u043e\u043c\/\u0442\u0435\u043b\u0435\u0432\u0438\u043a\u043e\u043c, \u0432\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u0435 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0439 AVCaptureDevice. \u0411\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f DiscoverySession \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0431\u044b\u0441\u0442\u0440\u043e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c \u0442\u0438\u043f \u043a\u0430\u043c\u0435\u0440\u044b \u043d\u0430 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0435 \u0438 \u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0435\u0433\u043e \u043a \u0430\u0443\u0442\u043f\u0443\u0442\u0443. \u0412\u0438\u0434\u044b \u043a\u0430\u043c\u0435\u0440:<\/p>\n<figure class=\"full-width\"><figcaption>\u0418\u0441\u0442\u043e\u0447\u043d\u0438\u043a &#8212; https:\/\/developer.apple.com\/documentation\/avfoundation\/avcapturedevice\/devicetype<\/figcaption><\/figure>\n<p>\u0424\u0443\u043d\u043a\u0446\u0438\u044f \u043f\u043e\u0438\u0441\u043a\u0430 \u043d\u0443\u0436\u043d\u043e\u0439 \u043a\u0430\u043c\u0435\u0440\u044b \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0442\u0430\u043a:<\/p>\n<pre><code class=\"swift\">private func currentDevice() -> AVCaptureDevice? {  \u00a0 \u00a0 \u00a0 \u00a0 let discoverySession = AVCaptureDevice.DiscoverySession(deviceTypes: [.builtInTripleCamera, .builtInDualWideCamera, .builtInDualCamera, .builtInWideAngleCamera],                                                                  mediaType: .video,                                                                  position: .back) \u00a0 \u00a0 \u00a0 \u00a0 guard let device = discoverySession.devices.first  \u00a0 \u00a0 \u00a0 \u00a0 else { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return nil \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 if device.deviceType == .builtInDualCamera || device.deviceType == .builtInWideAngleCamera { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 startZoom = 1.0 \/\/ \u043e\u0431 \u044d\u0442\u043e\u043c \u0447\u0443\u0442\u044c \u043f\u043e\u0437\u0436\u0435 \u00a0 \u00a0 \u00a0 \u00a0 }  \u00a0 \u00a0 \u00a0 \u00a0 return device  }<\/code><\/pre>\n<p>\u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0430 \u0441\u0442\u0440\u043e\u043a\u0443 \u043d\u043e\u043c\u0435\u0440 3: \u043c\u044b \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0438\u043b\u0438 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0435 \u0434\u0435\u0432\u0430\u0439\u0441\u044b \u0432 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u043e\u043c \u043f\u043e\u0440\u044f\u0434\u043a\u0435. \u0415\u0441\u043b\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f iPhone Pro, \u043f\u0435\u0440\u0432\u043e\u0439 \u0432 \u043c\u0430\u0441\u0441\u0438\u0432\u0435 \u043e\u043a\u0430\u0436\u0435\u0442\u0441\u044f \u0442\u0440\u043e\u0439\u043d\u0430\u044f \u043a\u0430\u043c\u0435\u0440\u0430. iPhone 11-14 &#8212; \u043a\u0430\u043c\u0435\u0440\u0430 \u0441 \u0443\u043b\u044c\u0442\u0440\u0430\u0448\u0438\u0440\u0438\u043a\u043e\u043c. iPhone X\/XS &#8212; \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u043a\u0430\u043c\u0435\u0440\u0443 \u0441 \u0442\u0435\u043b\u0435\u0432\u0438\u043a\u043e\u043c. \u0410 \u043d\u0430 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u043c \u043c\u0435\u0441\u0442\u0435 \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0438\u043b\u0430\u0441\u044c \u043f\u0440\u043e\u0441\u0442\u0430\u044f \u0448\u0438\u0440\u043e\u043a\u043e\u0443\u0433\u043e\u043b\u044c\u043d\u0430\u044f \u043a\u0430\u043c\u0435\u0440\u0430, \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0430\u044f \u0432 <u>\u043a\u0430\u0436\u0434\u043e\u043c<\/u> \u0434\u0435\u0432\u0430\u0439\u0441\u0435. \u0422\u0430\u043a\u0436\u0435 \u0445\u043e\u0447\u0443 \u043e\u0442\u043c\u0435\u0442\u0438\u0442\u044c, \u0447\u0442\u043e 2 \u0438 3 \u043a\u0430\u043c\u0435\u0440\u044b \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b \u0434\u043b\u044f iPhone Pro.<\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c, \u043a\u043e\u0433\u0434\u0430 \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0438 CaptureDevice, \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0447\u0430\u0442\u044c \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0443 \u0438\u043d\u043f\u0443\u0442\u043e\u0432:<\/p>\n<pre><code class=\"swift\">private func setupInputs() {  \u00a0 \u00a0 \u00a0 \u00a0 backCamera = currentDevice() \/\/ \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u044b\u0439 \u0434\u0435\u0432\u0430\u0439\u0441 \u0437\u0430\u0434\u043d\u0435\u0439 \u043a\u0430\u043c\u0435\u0440\u044b \u00a0 \u00a0 \u00a0 \u00a0 frontCamera = AVCaptureDevice.default(.builtInWideAngleCamera, for: .video, position: .front) \/\/ \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u0444\u0440\u043e\u043d\u0442\u0430\u043b\u043a\u0443  \u00a0 \u00a0 \u00a0 \u00a0 guard let backCamera = backCamera, \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 let frontCamera = frontCamera \u00a0 \u00a0 \u00a0 \u00a0 else { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return \u00a0 \u00a0 \u00a0 \u00a0 }  \u00a0 \u00a0 \u00a0 \u00a0 do { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 backInput = try AVCaptureDeviceInput(device: backCamera)  \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 guard captureSession.canAddInput(backInput) else { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 }  \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 frontInput = try AVCaptureDeviceInput(device: frontCamera)  \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 guard captureSession.canAddInput(frontInput) else { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 } catch { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 fatalError(\"could not connect camera\") \u00a0 \u00a0 \u00a0 \u00a0 }  \u00a0 \u00a0 \u00a0 \u00a0 captureDevice = backCamera \/\/ \u0441\u0435\u0442\u0430\u043f\u0438\u043c \u0437\u0430\u0434\u043d\u044e\u044e \u043a\u0430\u043c\u0435\u0440\u0443  \u00a0 \u00a0 \u00a0 \u00a0 captureSession.addInput(backInput) \/\/ \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0438\u043d\u043f\u0443\u0442 \u043a \u0441\u0435\u0441\u0441\u0438\u0438 \u00a0 \u00a0 \u00a0 \u00a0 if backCamera.deviceType == .builtInDualWideCamera || backCamera.deviceType == .builtInTripleCamera { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 updateZoom(scale: startZoom) \/\/ \u043e\u0431 \u044d\u0442\u043e\u043c \u0447\u0443\u0442\u044c \u043f\u043e\u0437\u0436\u0435 \u00a0 \u00a0 \u00a0 \u00a0 }  \u00a0}<\/code><\/pre>\n<p>\u0421\u0435\u0442\u0430\u043f\u0438\u043c \u0430\u0443\u0442\u043f\u0443\u0442:<\/p>\n<pre><code class=\"swift\">private func setupOutput() {  \u00a0 \u00a0 \u00a0 \u00a0 guard captureSession.canAddOutput(photoOutput) else { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return \u00a0 \u00a0 \u00a0 \u00a0 }  \u00a0 \u00a0 \u00a0 \u00a0 photoOutput.isHighResolutionCaptureEnabled = true \u00a0 \u00a0 \u00a0 \u00a0 photoOutput.maxPhotoQualityPrioritization = .balanced \u00a0 \u00a0 \u00a0 \u00a0 captureSession.addOutput(photoOutput) }<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c, \u043a\u043e\u0433\u0434\u0430 \u043c\u044b \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u0438\u043b\u0438 \u0441\u0435\u0442\u0430\u043f \u0438\u043d\u043f\u0443\u0442\u043e\u0432 \u0438 \u0430\u0443\u0442\u043f\u0443\u0442\u043e\u0432, \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043d\u0430\u0447\u0430\u0442\u044c \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e \u043d\u0430\u0448\u0435\u0439 AVCaptureSession. \u0414\u0435\u043b\u0430\u0435\u043c \u043c\u044b \u044d\u0442\u043e \u043d\u0430 \u0444\u043e\u043d\u043e\u0432\u043e\u043c \u043f\u043e\u0442\u043e\u043a\u0435, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e <code>captureSession.startRunning()<\/code> \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0431\u043b\u043e\u043a\u0438\u0440\u0443\u044e\u0449\u0438\u043c \u0432\u044b\u0437\u043e\u0432\u043e\u043c \u0438 \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c \u0435\u0433\u043e \u043d\u0430 \u0433\u043b\u0430\u0432\u043d\u043e\u0439 \u043e\u0447\u0435\u0440\u0435\u0434\u0438 \u043d\u0435 \u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u043f\u043e \u043f\u0440\u0438\u0447\u0438\u043d\u0435 \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u0440\u0430\u0431\u043e\u0442\u044b \u0432\u0441\u0435\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0434\u043e \u0442\u043e\u0433\u043e \u043c\u043e\u043c\u0435\u043d\u0442\u0430 \u043a\u0430\u043a \u0441\u0435\u0441\u0441\u0438\u044f \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u0441\u044f.<\/p>\n<p>\u0424\u0443\u043d\u043a\u0446\u0438\u044f \u0441\u0435\u0442\u0430\u043f\u0430 \u0441\u0435\u0441\u0441\u0438\u0438:<\/p>\n<pre><code class=\"swift\">private func setupAndStartCaptureSession() {  \u00a0 \u00a0 \u00a0 \u00a0 cameraQueue.async { [weak self] in \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 self?.captureSession.beginConfiguration() \/\/ \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u043c \u0441\u0435\u0441\u0441\u0438\u044e \u0434\u043b\u044f \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 if let canSetSessionPreset =<\/code><\/pre>\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-343681","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/343681","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=343681"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/343681\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=343681"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=343681"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=343681"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}