{"componentChunkName":"component---src-pages-author-author-yaml-id-js","path":"/author/tanvi-jain/","result":{"data":{"allMarkdownRemark":{"edges":[{"node":{"id":"12010bda-49a0-53fa-bcec-845504e54db0","html":"<p>Apple's smartphone OS running on iPhone, iPad, iPod Touch hardware is iOS. For these computers, Apple offers tools and services for developing iOS apps and accessories.</p>\n<p>You can use React Native (JavaScript) or Xamarin (C# &#x26; F#) as an iOS developer to programme in native languages like Swift or Objective-C or build native cross-platform applications.</p>\n<p>In this article, we'll explore how to build iOS apps. We're going to look at how you can learn to develop an iOS application and play with existing apps.</p>\n<p>As with learning something new, learning to build iOS is difficult. Although, It is enjoyable, exciting, and satisfying!</p>\n<p>Here's what we'll get into:</p>\n<ol>\n<li>Setup your MAC for ios app development</li>\n<li>Setup, your editor for ios application</li>\n<li>Create your first ios app</li>\n<li>Run the ios application</li>\n</ol>\n<p>You will have a step-by-step plan to learn how to create an ios app when you have completed reading this guide. You know precisely what you should do, what steps you should take, and how you should take them. Yeah, and you don't need any coding experience to get started.</p>\n<p>So let's get started...</p>\n<h2 id=\"1-setup-your-mac-for-ios-app-development\" style=\"position:relative;\"><a href=\"#1-setup-your-mac-for-ios-app-development\" aria-label=\"1 setup your mac for ios app development permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>1. Setup your MAC for ios app development</h2>\n<p>Apple prefers a closed ecosystem over an open system. iOS can only be run on Apple's own devices, including the iPhone and iPad.</p>\n<p>We can run Mac on window machines using VMWare or Hackintosh, but these are not recommended for iOS coding purposes.\nSo basically, as an iOS developer, you will need a Mac for the development/debugging/testing of an iOS app.</p>\n<h2 id=\"2-setup-your-editor-for-ios-application\" style=\"position:relative;\"><a href=\"#2-setup-your-editor-for-ios-application\" aria-label=\"2 setup your editor for ios application permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>2. Setup, your editor for ios application</h2>\n<p>To start developing iOS apps, Xcode is the only tool you need to download. Xcode is an integrated development environment (IDE) provided by Apple. It includes the iOS SDK (Software Development Kit), a source code editor(UI), debugging tools, and much more.</p>\n<p>Many helping tools and needed simulators with a particular iOS version can be installed and added to Xcode.\nYou will need to have an Apple ID to download Xcode, deploy your app to a real iPhone/iPad for testing, and download any other software from AppStore.</p>\n<p>Apple ID is used to authenticate a user in Apple devices. You may create it by visiting the apple <a href=\"https://appleid.apple.com/account#!&#x26;page=create\">official site</a>.</p>\n<p>To install Xcode, go to the Mac App Store. App Store can be found in the dock. Login there with your Apple ID. In the Mac App Store, search \"Xcode\" and click the \"Get\" button to download it.</p>\n<p><img src=\"/eb4087ec36d030ba63d08fde5a4b9023/Imag1.webp\"></p>\n<h2 id=\"3-create-your-first-ios-app\" style=\"position:relative;\"><a href=\"#3-create-your-first-ios-app\" aria-label=\"3 create your first ios app permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>3. Create your first ios app</h2>\n<p>Now click and launch Xcode. Choose create a new Xcode project option to make a new project. Then choose the Single View App option as a type of the project and click Next. It will come with one view controller and a storyboard that you can customize further.</p>\n<p>Let's name your project as HelloWorld as per the convention 😉. Choose Team None for now. Select Swift as Language, click Next, and you are ready with your empty app doing nothing yet.</p>\n<blockquote>\n<p>Note: For creating a native <a href=\"https://www.loginradius.com/blog/engineering/secure-enclave-ios-app/\">iOS app</a>, you have to use one from Objective-c or Swift. Swift is a new and easy language provided by Apple, got so much popularity in less time.</p>\n</blockquote>\n<p><img src=\"/2d051b2c11984f8dc6eded5a15a4c6c0/Image2.webp\"></p>\n<p>Not to worry, you will soon modify your created app saying Hello to the World. 😍\nIn Xcode, you can navigate to a file or folder from the code editor's left panel. The right panel of the code editor, called Utility Area, will help you dealing with views or any component in the storyboard.</p>\n<p>On the top toolbar, you can see the Run and Stop buttons. At the bottom of the code area, you can see the debug/console area with breakpoint and other runtime tools.</p>\n<p><img src=\"/acc8133b158a35588991b53e9384515b/Image6.webp\"></p>\n<p>Now find and open Main.storyboard in the project directory by clicking on it. The storyboard is a file to design your view to show and layout all the components such as buttons, labels, lists, tab and navigation bars, and many more. Here you will see a blank view. Select the view by clicking on it. </p>\n<p>From Xcode 10 or above, for objects like a label to add, click on View menu in menu bar>click Show Library and drag the label to focused view. Or in older Xcode, you may find Object Library in the bottom right part of Xcode. Now double click on the label you have dropped on the view and change it's text to Hello World!</p>\n<p><img src=\"/633e42cc27973114869cb95c0f98ac2b/Image3.webp\"></p>\n<p>Feeling excited? 😃</p>\n<p><strong>Here you go with your first-ever app on screen</strong></p>\n<h2 id=\"4-run-the-ios-application\" style=\"position:relative;\"><a href=\"#4-run-the-ios-application\" aria-label=\"4 run the ios application permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>4. Run the ios application</h2>\n<p>Select the device destination or simulator from the Xcode screen's top left near the Run/Stop button. And press Command ⌘ + R to run the app or click the run button. It will initiate the iOS simulator and run your first app.</p>\n<p>For running the app on a real device, connect the device via cable to Mac. The device will automatically be shown in the list of device destinations. Now select the device and press Command ⌘ + R.</p>\n<p><img src=\"/ea2e25ecbb9a337ef4a3d2441836f8db/Image4.webp\"></p>\n<p>Share your first app with your parents and friends, and feel proud. 👏 </p>\n<p><img src=\"/58421c91afb17198bf5a507862b11fd7/hello_word.webp\" alt=\"HelloWorld\"></p>\n<blockquote>\n<p>Note: If you want to debug or run any existing app/demo instead of developing your own. For example, You might have some projects downloaded from Github on your local system. Now follow the instructions from project's Github to explore the project.\nOpen the project in Xcode and run in a simulator or real device by following step 4 described above.</p>\n</blockquote>\n<p>That's it. </p>\n<h2 id=\"conclusion\" style=\"position:relative;\"><a href=\"#conclusion\" aria-label=\"conclusion permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Conclusion</h2>\n<p>It's incredibly entertaining and satisfying to create your app idea. It's not just the result that counts-what makes it worth it is the gradual progress of improving, learning, and refining. And in the process, you will cultivate a special, employable skill of iOS development.</p>\n<p>I hope you liked this tutorial. Kindly share the blog and comment for any query or suggestion. </p>\n<p>To learn more about iOS applications, you can check out this article on “How to obtain iOS application logs without Mac” to learn about ios app logs in mac.</p>\n<style class=\"grvsc-styles\">\n  .grvsc-container {\n    overflow: auto;\n    -webkit-overflow-scrolling: touch;\n    padding-top: 1rem;\n    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));\n    padding-bottom: 1rem;\n    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));\n    border-radius: 8px;\n    border-radius: var(--grvsc-border-radius, 8px);\n    font-feature-settings: normal;\n  }\n  \n  .grvsc-code {\n    display: inline-block;\n    min-width: 100%;\n  }\n  \n  .grvsc-line {\n    display: inline-block;\n    box-sizing: border-box;\n    width: 100%;\n    padding-left: 1.5rem;\n    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));\n    padding-right: 1.5rem;\n    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));\n  }\n  \n  .grvsc-line-highlighted {\n    background-color: var(--grvsc-line-highlighted-background-color, transparent);\n    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);\n  }\n  \n</style>","frontmatter":{"title":"iOS App Development: How To Make Your First App","author":{"id":"Tanvi Jain","github":"tanvijn","avatar":null},"date":"October 19, 2020","updated_date":null,"tags":["ios","swift","xcode","mac"],"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1.5267175572519085,"src":"/static/dde63430f9de95dd6a3ca8d01bdc5f00/58556/CoverImage.webp","srcSet":"/static/dde63430f9de95dd6a3ca8d01bdc5f00/61e93/CoverImage.webp 200w,\n/static/dde63430f9de95dd6a3ca8d01bdc5f00/1f5c5/CoverImage.webp 400w,\n/static/dde63430f9de95dd6a3ca8d01bdc5f00/58556/CoverImage.webp 800w,\n/static/dde63430f9de95dd6a3ca8d01bdc5f00/cc834/CoverImage.webp 1024w","sizes":"(max-width: 800px) 100vw, 800px"}}}},"fields":{"authorId":"Tanvi Jain","slug":"/engineering/getting-started-with-ios-app-development/"}}},{"node":{"id":"e3153ce3-616f-5858-84e6-bedbc956d387","html":"<h2 id=\"introduction\" style=\"position:relative;\"><a href=\"#introduction\" aria-label=\"introduction permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Introduction</h2>\n<p>The Secure Enclave is a hardware-based key manager that’s isolated from the main processor to provide an extra layer of security. Using a secure enclave, we can create the key, securely store the key, and perform operations with the key. Thus makes it difficult for the key to be compromised. </p>\n<p>We usually save data persistently in the app using UserDefaults, Keychain, Core Data or SQLite.\nFor example, To save the session of logged in user, we save username and password. But this process puts our data at high-security risk. So it's always recommended to store sensitive data in an encrypted format. But again, it's a challenge to secure keys used in encryption/decryption.</p>\n<p><img src=\"/52c5d8e0a1d8ee7238f2080cc0689c39/image2.webp\" alt=\"Secure Enclave\"></p>\n<p>Now here <strong>Secure Enclave</strong> comes in the role. </p>\n<p>In this blog, we will use Secure Enclave to generate key pair and use those in encryption/decryption of sensitive data further.</p>\n<p>Here I will create a wrapper to generate key pair using Secure Enclave and use them to encrypt/decrypt sensitive data. And also a viewcontroller to show how to use a wrapper to get encrypted and decrypted data.\nYou may implement wrapper's methods as common methods and use wherever needed in the project. But its recommended to use a separate wrapper for handling communication with Secure Enclave.</p>\n<h2 id=\"wrapper\" style=\"position:relative;\"><a href=\"#wrapper\" aria-label=\"wrapper permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Wrapper</h2>\n<p> I have created .h and .m files named as SecEnclaveWrapper as a subclass of NSObject.\nIn .h file I am declaring function for being accessible from other classes like: </p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"objective-c\" data-index=\"0\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk3\">/**</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">Return encrypted value of data using kSecKeyAlgorithmECIESEncryptionStandardX963SHA256AESGCM algo</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">*/</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">- (</span><span class=\"mtk10\">NSData</span><span class=\"mtk1\"> *_Nonnull)encryptData:(</span><span class=\"mtk10\">NSData</span><span class=\"mtk1\"> *_Nonnull)data ;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">/**</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">Return decryrpted data of encrypted data  using kSecKeyAlgorithmECIESEncryptionStandardX963SHA256AESGCM algo</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">*/</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">- (</span><span class=\"mtk10\">NSData</span><span class=\"mtk1\"> *_Nonnull)decryptData:(</span><span class=\"mtk10\">NSData</span><span class=\"mtk1\"> *_Nonnull)data ;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">/**</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">Return an initialized instance of the wrapper</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">*/</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">- (</span><span class=\"mtk4\">instancetype</span><span class=\"mtk1\">)init;</span></span></code></pre>\n<p>Then in .m file, define the following methods as : </p>\n<p>The method <code>init</code> initializes and returns the object of this wrapper class. And 'encryptData' and 'decryptData' method return encrypted data and decrypted data of encrypted data, respectively.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"objective-c\" data-index=\"1\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">- (</span><span class=\"mtk4\">instancetype</span><span class=\"mtk1\">)init {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    self = [super init];</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">if</span><span class=\"mtk1\">(![self lookupPublicKeyRef] || ![self lookupPrivateKeyRef])</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        [self generatePasscodeKeyPair];</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> self;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">- (</span><span class=\"mtk10\">NSData</span><span class=\"mtk1\"> *)encryptData:(</span><span class=\"mtk10\">NSData</span><span class=\"mtk1\"> *)data {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> (data && </span><span class=\"mtk12\">data</span><span class=\"mtk1\">.</span><span class=\"mtk12\">length</span><span class=\"mtk1\">) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        CFDataRef cipher = </span><span class=\"mtk11\">SecKeyCreateEncryptedData</span><span class=\"mtk1\">(publicKeyRef, kSecKeyAlgorithmECIESEncryptionStandardX963SHA256AESGCM, (CFDataRef)data, </span><span class=\"mtk4\">nil</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> (__bridge </span><span class=\"mtk10\">NSData</span><span class=\"mtk1\"> *)cipher;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    } </span><span class=\"mtk15\">else</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> </span><span class=\"mtk4\">nil</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    }</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">- (</span><span class=\"mtk10\">NSData</span><span class=\"mtk1\">*)decryptData:(</span><span class=\"mtk10\">NSData</span><span class=\"mtk1\"> *)data {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">if</span><span class=\"mtk1\">(data && </span><span class=\"mtk12\">data</span><span class=\"mtk1\">.</span><span class=\"mtk12\">length</span><span class=\"mtk1\">){</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        CFDataRef plainData = </span><span class=\"mtk11\">SecKeyCreateDecryptedData</span><span class=\"mtk1\">(privateKeyRef, kSecKeyAlgorithmECIESEncryptionStandardX963SHA256AESGCM, (CFDataRef)data, </span><span class=\"mtk4\">nil</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\">  (__bridge </span><span class=\"mtk10\">NSData</span><span class=\"mtk1\"> *)plainData;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    }</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">else</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> </span><span class=\"mtk4\">nil</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    }</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<p>The 'lookupPublicKeyRef' method below will lookup keychain for public key &#x26; 'lookupPrivateKeyRef' method search for the private key and return key if found.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"objective-c\" data-index=\"2\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">- (SecKeyRef) lookupPublicKeyRef</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">{</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk10\">OSStatus</span><span class=\"mtk1\"> sanityCheck = noErr;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk10\">NSData</span><span class=\"mtk1\"> *tag;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">id</span><span class=\"mtk1\"> keyClass;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> (publicKeyRef != </span><span class=\"mtk4\">NULL</span><span class=\"mtk1\">) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk3\">// if already resides in memory, return</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> publicKeyRef;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    }</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    tag = [kPublicKeyName dataUsingEncoding:NSUTF8StringEncoding];</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    keyClass = (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kSecAttrKeyClassPublic;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk10\">NSDictionary</span><span class=\"mtk1\"> *queryDict = @{</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kSecClass : (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kSecClassKey,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kSecAttrKeyType : (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kSecAttrKeyTypeEC,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kSecAttrApplicationTag : tag,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kSecAttrKeyClass : keyClass,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kSecReturnRef : (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kCFBooleanTrue</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    };</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk3\">//else look key in keychain and return</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    sanityCheck = </span><span class=\"mtk11\">SecItemCopyMatching</span><span class=\"mtk1\">((__bridge CFDictionaryRef) queryDict, (CFTypeRef *) &publicKeyRef);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> (sanityCheck != errSecSuccess) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk11\">NSLog</span><span class=\"mtk1\">(</span><span class=\"mtk8\">@&quot;Error trying to retrieve key from server.  sanityCheck: %d&quot;</span><span class=\"mtk1\">, (</span><span class=\"mtk4\">int</span><span class=\"mtk1\">)sanityCheck);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    }</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> publicKeyRef;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">- (SecKeyRef) lookupPrivateKeyRef</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">{</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    CFMutableDictionaryRef getPrivateKeyRef = newCFDict;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk11\">CFDictionarySetValue</span><span class=\"mtk1\">(getPrivateKeyRef, kSecClass, kSecClassKey);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk11\">CFDictionarySetValue</span><span class=\"mtk1\">(getPrivateKeyRef, kSecAttrKeyClass, kSecAttrKeyClassPrivate);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk11\">CFDictionarySetValue</span><span class=\"mtk1\">(getPrivateKeyRef, kSecAttrLabel, kPrivateKeyName);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk11\">CFDictionarySetValue</span><span class=\"mtk1\">(getPrivateKeyRef, kSecReturnRef, kCFBooleanTrue);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk10\">OSStatus</span><span class=\"mtk1\"> status = </span><span class=\"mtk11\">SecItemCopyMatching</span><span class=\"mtk1\">(getPrivateKeyRef, (CFTypeRef *)&privateKeyRef);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> (status == errSecItemNotFound)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> </span><span class=\"mtk4\">nil</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> (SecKeyRef)privateKeyRef;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<p>The following methods will actually deal with Secure Enclave to generate a private key and public key.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"objective-c\" data-index=\"3\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">- (</span><span class=\"mtk4\">bool</span><span class=\"mtk1\">) generatePasscodeKeyPair</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">{</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    CFErrorRef error = </span><span class=\"mtk4\">NULL</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    SecAccessControlRef sacObject = </span><span class=\"mtk11\">SecAccessControlCreateWithFlags</span><span class=\"mtk1\">(</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                                                                    kCFAllocatorDefault,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                                                                    kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                                                                    kSecAccessControlPrivateKeyUsage,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                                                                    &error</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                                                                    );</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> (error != errSecSuccess) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk11\">NSLog</span><span class=\"mtk1\">(</span><span class=\"mtk8\">@&quot;Generating key pair, error: %@</span><span class=\"mtk6\">\\n</span><span class=\"mtk8\">&quot;</span><span class=\"mtk1\">, error);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    }</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> [self generateKeyPairWithAccessControlObject:sacObject];</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">- (</span><span class=\"mtk4\">bool</span><span class=\"mtk1\">) generateKeyPairWithAccessControlObject:(SecAccessControlRef)accessControlRef</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">{</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk3\">// create dictionary of private key </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    CFMutableDictionaryRef accessControlDict = newCFDict;;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">#if</span><span class=\"mtk4\"> </span><span class=\"mtk1\">!</span><span class=\"mtk11\">TARGET_IPHONE_SIMULATOR</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk11\">CFDictionaryAddValue</span><span class=\"mtk1\">(accessControlDict, kSecAttrAccessControl, accessControlRef);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">#endif</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk11\">CFDictionaryAddValue</span><span class=\"mtk1\">(accessControlDict, kSecAttrIsPermanent, kCFBooleanTrue);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk11\">CFDictionaryAddValue</span><span class=\"mtk1\">(accessControlDict, kSecAttrLabel, kPrivateKeyName);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk3\">// create dictionary for saving key into keychain</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    CFMutableDictionaryRef generatePairRef = newCFDict;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">#if</span><span class=\"mtk4\"> </span><span class=\"mtk1\">!</span><span class=\"mtk11\">TARGET_IPHONE_SIMULATOR</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk11\">CFDictionaryAddValue</span><span class=\"mtk1\">(generatePairRef, kSecAttrTokenID, kSecAttrTokenIDSecureEnclave);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">#endif</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk11\">CFDictionaryAddValue</span><span class=\"mtk1\">(generatePairRef, kSecAttrKeyType, kSecAttrKeyTypeEC);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk11\">CFDictionaryAddValue</span><span class=\"mtk1\">(generatePairRef, kSecAttrKeySizeInBits, (__bridge </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk4\">void</span><span class=\"mtk1\"> *)([</span><span class=\"mtk10\">NSNumber</span><span class=\"mtk1\"> numberWithInt:</span><span class=\"mtk7\">256</span><span class=\"mtk1\">]));</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk11\">CFDictionaryAddValue</span><span class=\"mtk1\">(generatePairRef, kSecPrivateKeyAttrs, accessControlDict);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk10\">OSStatus</span><span class=\"mtk1\"> status = </span><span class=\"mtk11\">SecKeyGeneratePair</span><span class=\"mtk1\">(generatePairRef, &publicKeyRef, &privateKeyRef);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> (status != errSecSuccess){</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk11\">NSLog</span><span class=\"mtk1\">(</span><span class=\"mtk8\">@&quot;Error trying to retrieve key from server.  sanityCheck: %d&quot;</span><span class=\"mtk1\">, (</span><span class=\"mtk4\">int</span><span class=\"mtk1\">)status);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> </span><span class=\"mtk4\">NO</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    }</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    [self savePublicKeyFromRef:publicKeyRef];</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> </span><span class=\"mtk4\">YES</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<p>The private key is generated and stored in Secure Enclave which cannot be directly used. Whereas public key have to be stored manually in keychain by following method.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"objective-c\" data-index=\"4\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">- (</span><span class=\"mtk4\">bool</span><span class=\"mtk1\">) savePublicKeyFromRef:(SecKeyRef)publicKeyRef</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">{   </span><span class=\"mtk10\">OSStatus</span><span class=\"mtk1\"> sanityCheck = noErr;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk10\">NSData</span><span class=\"mtk1\"> *tag;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">id</span><span class=\"mtk1\"> keyClass;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    tag = [kPublicKeyName dataUsingEncoding:NSUTF8StringEncoding];</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    keyClass = (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kSecAttrKeyClassPublic;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk10\">NSDictionary</span><span class=\"mtk1\"> *saveDict = @{</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kSecClass : (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kSecClassKey,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kSecAttrKeyType : (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kSecAttrKeyTypeEC,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kSecAttrApplicationTag : tag,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kSecAttrKeyClass : keyClass,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kSecValueData : (__bridge </span><span class=\"mtk10\">NSData</span><span class=\"mtk1\"> *)</span><span class=\"mtk11\">SecKeyCopyExternalRepresentation</span><span class=\"mtk1\">(publicKeyRef,</span><span class=\"mtk4\">nil</span><span class=\"mtk1\">),</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kSecAttrKeySizeInBits : [</span><span class=\"mtk10\">NSNumber</span><span class=\"mtk1\"> numberWithUnsignedInteger:</span><span class=\"mtk7\">256</span><span class=\"mtk1\">],</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kSecAttrEffectiveKeySize : [</span><span class=\"mtk10\">NSNumber</span><span class=\"mtk1\"> numberWithUnsignedInteger:</span><span class=\"mtk7\">256</span><span class=\"mtk1\">],</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kSecAttrCanDerive : (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kCFBooleanFalse,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kSecAttrCanEncrypt : (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kCFBooleanTrue,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kSecAttrCanDecrypt : (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kCFBooleanFalse,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kSecAttrCanVerify : (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kCFBooleanTrue,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kSecAttrCanSign : (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kCFBooleanFalse,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kSecAttrCanWrap : (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kCFBooleanTrue,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kSecAttrCanUnwrap : (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kCFBooleanFalse</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    };</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    sanityCheck = </span><span class=\"mtk11\">SecItemAdd</span><span class=\"mtk1\">((__bridge CFDictionaryRef) saveDict, (CFTypeRef *)&publicKeyRef);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> (sanityCheck != errSecSuccess) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk11\">NSLog</span><span class=\"mtk1\">(</span><span class=\"mtk8\">@&quot;Error trying to retrieve key from server.  sanityCheck: %d&quot;</span><span class=\"mtk1\">, (</span><span class=\"mtk4\">int</span><span class=\"mtk1\">)sanityCheck);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    }</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> publicKeyRef;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<h2 id=\"demo\" style=\"position:relative;\"><a href=\"#demo\" aria-label=\"demo permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Demo</h2>\n<p>Now I am creating ViewController.h and .m files. In viewDidLoad in .m file, having a string to be stored in UserDefaults. I will encrypt this string by a private key generated above and then store persistently encrypted data for later use.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"objective-c\" data-index=\"5\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">- (</span><span class=\"mtk4\">void</span><span class=\"mtk1\">)viewDidLoad {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    [super viewDidLoad];</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk10\">NSString</span><span class=\"mtk1\"> *strDatatosave = </span><span class=\"mtk8\">@&quot;example data to save&quot;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk10\">NSString</span><span class=\"mtk1\"> *bundleIdentifier = [[</span><span class=\"mtk10\">NSBundle</span><span class=\"mtk1\"> mainBundle] bundleIdentifier];</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk10\">NSString</span><span class=\"mtk1\"> *strGroupID = [</span><span class=\"mtk10\">NSString</span><span class=\"mtk1\"> stringWithFormat:</span><span class=\"mtk8\">@&quot;group.%@&quot;</span><span class=\"mtk1\">,bundleIdentifier];</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    SecEnclaveWrapper *keychainItem = [[SecEnclaveWrapper alloc] init];</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk10\">NSData</span><span class=\"mtk1\"> *encrypted = [keychainItem encryptData:[strDatatosave dataUsingEncoding:NSUTF8StringEncoding]];</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk10\">NSString</span><span class=\"mtk1\"> *strEncrypted = [[</span><span class=\"mtk10\">NSString</span><span class=\"mtk1\"> alloc] initWithData:encrypted encoding:NSUTF8StringEncoding];</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk11\">NSLog</span><span class=\"mtk1\">(</span><span class=\"mtk8\">@&quot;encrypted string %@&quot;</span><span class=\"mtk1\">,strEncrypted);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk10\">NSData</span><span class=\"mtk1\"> *decrypted =[keychainItem decryptData:encrypted];</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk10\">NSString</span><span class=\"mtk1\"> *strDecrypted = [[</span><span class=\"mtk10\">NSString</span><span class=\"mtk1\"> alloc] initWithData:decrypted encoding:NSUTF8StringEncoding];</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk11\">NSLog</span><span class=\"mtk1\">(</span><span class=\"mtk8\">@&quot;decrypted string as real string%@&quot;</span><span class=\"mtk1\">,strDecrypted);</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<h2 id=\"conclusion\" style=\"position:relative;\"><a href=\"#conclusion\" aria-label=\"conclusion permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Conclusion</h2>\n<p>In this blog, we learned about the basics of key generation via Secure Enclave and encryption and decryption using keys.\nBy default, key-pairs are generated in the Secure Enclave. The private key is available only at creation time and can not be obtained later as it is saved in Secure Enclave. Operations can be performed with it without exposing it to user code. Only Public Key will be stored and retrieved.</p>\n<p>You can find the complete repository link <a href=\"https://github.com/LoginRadius/engineering-blog-samples/tree/master/iOS/SecureEnclave/SecureEnclaveDemo\">here</a></p>\n<p>Thanks for reading the blog. For detailed information and execution example of this blog, please refer to the video below:</p>\n<iframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/c_1E_NV4NBk\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>\n<style class=\"grvsc-styles\">\n  .grvsc-container {\n    overflow: auto;\n    -webkit-overflow-scrolling: touch;\n    padding-top: 1rem;\n    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));\n    padding-bottom: 1rem;\n    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));\n    border-radius: 8px;\n    border-radius: var(--grvsc-border-radius, 8px);\n    font-feature-settings: normal;\n  }\n  \n  .grvsc-code {\n    display: inline-block;\n    min-width: 100%;\n  }\n  \n  .grvsc-line {\n    display: inline-block;\n    box-sizing: border-box;\n    width: 100%;\n    padding-left: 1.5rem;\n    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));\n    padding-right: 1.5rem;\n    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));\n  }\n  \n  .grvsc-line-highlighted {\n    background-color: var(--grvsc-line-highlighted-background-color, transparent);\n    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);\n  }\n  \n  .dark-default-dark {\n    background-color: #1E1E1E;\n    color: #D4D4D4;\n  }\n  .dark-default-dark .mtk3 { color: #6A9955; }\n  .dark-default-dark .mtk1 { color: #D4D4D4; }\n  .dark-default-dark .mtk10 { color: #4EC9B0; }\n  .dark-default-dark .mtk4 { color: #569CD6; }\n  .dark-default-dark .mtk15 { color: #C586C0; }\n  .dark-default-dark .mtk12 { color: #9CDCFE; }\n  .dark-default-dark .mtk11 { color: #DCDCAA; }\n  .dark-default-dark .mtk8 { color: #CE9178; }\n  .dark-default-dark .mtk6 { color: #D7BA7D; }\n  .dark-default-dark .mtk7 { color: #B5CEA8; }\n</style>","frontmatter":{"title":"Secure Enclave in iOS App","author":{"id":"Tanvi Jain","github":"tanvijn","avatar":null},"date":"October 13, 2020","updated_date":null,"tags":["ios","security","data","encryption","private key","xcode"],"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1.5037593984962405,"src":"/static/e677a934323b29af4619ee797f0286b8/58556/CoverImage.webp","srcSet":"/static/e677a934323b29af4619ee797f0286b8/61e93/CoverImage.webp 200w,\n/static/e677a934323b29af4619ee797f0286b8/1f5c5/CoverImage.webp 400w,\n/static/e677a934323b29af4619ee797f0286b8/58556/CoverImage.webp 800w,\n/static/e677a934323b29af4619ee797f0286b8/210c1/CoverImage.webp 900w","sizes":"(max-width: 800px) 100vw, 800px"}}}},"fields":{"authorId":"Tanvi Jain","slug":"/engineering/secure-enclave-ios-app/"}}},{"node":{"id":"281a18f8-df24-553d-9dcc-5dbea3086e65","html":"<p>Logs are very helpful in finding the root cause of the issues you may be experiencing in an app. It is an efficient way to resolve issues by knowing the exact reason after checking Logs.</p>\n<p>Let's say we have developed an iOS app. As in many situations, we want to test our app on another's phone for many reasons. And probably that phone cannot be connected to the Mac. So, the console logs of the app can be sent directly from the app to the developer(us).</p>\n<p>This blog will provide step-by-step instructions for mailing iOS app logs directly from the app. </p>\n<h3 id=\"getting-started\" style=\"position:relative;\"><a href=\"#getting-started\" aria-label=\"getting started permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Getting started</h3>\n<p>Here we are having a <a href=\"https://github.com/tanvijn/TestLogs/tree/master\">project</a> with a single ViewController. We may ask our users to install the app on their device, use it and at the end click on “Press for Logs” Button. By clicking IBAction pressForLogs function will get called which will open MailComposer and then the user can mail the Log file to us.</p>\n<h3 id=\"steps-to-do-in-your-own-project\" style=\"position:relative;\"><a href=\"#steps-to-do-in-your-own-project\" aria-label=\"steps to do in your own project permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Steps to do in your own project</h3>\n<ul>\n<li>Find AppDelegate.swift in your project. Define following var and function as global before any import statement.</li>\n</ul>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"java\" data-index=\"0\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk4\">public</span><span class=\"mtk1\"> </span><span class=\"mtk4\">var</span><span class=\"mtk1\"> </span><span class=\"mtk12\">logFilePath</span><span class=\"mtk15\">:</span><span class=\"mtk1\">String!</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\"> </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">//======================//</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">func </span><span class=\"mtk11\">print</span><span class=\"mtk1\">(</span><span class=\"mtk10\">_</span><span class=\"mtk1\"> </span><span class=\"mtk12\">items</span><span class=\"mtk15\">:</span><span class=\"mtk1\"> </span><span class=\"mtk10\">Any</span><span class=\"mtk1\">..., separator</span><span class=\"mtk15\">:</span><span class=\"mtk1\"> String = </span><span class=\"mtk8\">&quot; &quot;</span><span class=\"mtk1\">, terminator</span><span class=\"mtk15\">:</span><span class=\"mtk1\"> String = </span><span class=\"mtk8\">&quot;</span><span class=\"mtk6\">\\n</span><span class=\"mtk8\">&quot;</span><span class=\"mtk1\">) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    let output = </span><span class=\"mtk12\">items</span><span class=\"mtk1\">.</span><span class=\"mtk12\">map</span><span class=\"mtk1\"> { </span><span class=\"mtk8\">&quot;*</span><span class=\"mtk6\">\\(</span><span class=\"mtk8\">$0)&quot;</span><span class=\"mtk1\">}.</span><span class=\"mtk11\">joined</span><span class=\"mtk1\">(separator</span><span class=\"mtk15\">:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot; &quot;</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk3\">//Swift.print(output, terminator: terminator)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk11\">NSLog</span><span class=\"mtk1\">(output)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<p> Above function override any log calls in the app.</p>\n<ul>\n<li>Then define the following method in AppDelegate.Swift file. And call from <code>func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool function.</code></li>\n</ul>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"swift\" data-index=\"1\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk4\">func</span><span class=\"mtk1\"> </span><span class=\"mtk11\">printTheDataAtLogFile</span><span class=\"mtk1\">() {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    logFilePath = </span><span class=\"mtk11\">NSTemporaryDirectory</span><span class=\"mtk1\">().</span><span class=\"mtk11\">appending</span><span class=\"mtk1\">(</span><span class=\"mtk10\">String</span><span class=\"mtk1\">.</span><span class=\"mtk4\">init</span><span class=\"mtk1\">(</span><span class=\"mtk11\">format</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;%@.log&quot;</span><span class=\"mtk1\">,Bundle.</span><span class=\"mtk12\">main</span><span class=\"mtk1\">.</span><span class=\"mtk11\">object</span><span class=\"mtk1\">(</span><span class=\"mtk11\">forInfoDictionaryKey</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;CFBundleName&quot;</span><span class=\"mtk1\">) as! </span><span class=\"mtk10\">String</span><span class=\"mtk1\">)) as </span><span class=\"mtk10\">String</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">       </span><span class=\"mtk11\">freopen</span><span class=\"mtk1\">((logFilePath as NSString).</span><span class=\"mtk11\">cString</span><span class=\"mtk1\">(</span><span class=\"mtk11\">using</span><span class=\"mtk1\">: </span><span class=\"mtk10\">String</span><span class=\"mtk1\">.</span><span class=\"mtk11\">Encoding</span><span class=\"mtk1\">(</span><span class=\"mtk11\">rawValue</span><span class=\"mtk1\">: </span><span class=\"mtk10\">String</span><span class=\"mtk1\">.</span><span class=\"mtk12\">Encoding</span><span class=\"mtk1\">.</span><span class=\"mtk12\">ascii</span><span class=\"mtk1\">.</span><span class=\"mtk12\">rawValue</span><span class=\"mtk1\">).</span><span class=\"mtk12\">rawValue</span><span class=\"mtk1\">)!, </span><span class=\"mtk8\">&quot;a+&quot;</span><span class=\"mtk1\">, stderr)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">   }</span></span></code></pre>\n<p>Above function will write all logs into a file instead of console.</p>\n<ul>\n<li>\n<p>Open Viewcontroller.swift. Define below 2 functions in it. </p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"swift\" data-index=\"2\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk4\">func</span><span class=\"mtk1\"> </span><span class=\"mtk11\">allOptions</span><span class=\"mtk1\">() {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">let</span><span class=\"mtk1\"> alert = </span><span class=\"mtk11\">UIAlertController</span><span class=\"mtk1\">(</span><span class=\"mtk11\">title</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;Please Select an Option&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk11\">message</span><span class=\"mtk1\">: </span><span class=\"mtk4\">nil</span><span class=\"mtk1\">, </span><span class=\"mtk11\">preferredStyle</span><span class=\"mtk1\">: .</span><span class=\"mtk12\">actionSheet</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">alert.</span><span class=\"mtk11\">addAction</span><span class=\"mtk1\">(</span><span class=\"mtk11\">UIAlertAction</span><span class=\"mtk1\">(</span><span class=\"mtk11\">title</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;Log Mail&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk11\">style</span><span class=\"mtk1\">: .</span><span class=\"mtk12\">default</span><span class=\"mtk1\"> , </span><span class=\"mtk11\">handler</span><span class=\"mtk1\">:{ (UIAlertAction)</span><span class=\"mtk15\">in</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">self</span><span class=\"mtk1\">.</span><span class=\"mtk11\">shareDocument</span><span class=\"mtk1\">(</span><span class=\"mtk11\">documentPath</span><span class=\"mtk1\">: logFilePath)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}))</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">alert.</span><span class=\"mtk11\">addAction</span><span class=\"mtk1\">(</span><span class=\"mtk11\">UIAlertAction</span><span class=\"mtk1\">(</span><span class=\"mtk11\">title</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;dismis&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk11\">style</span><span class=\"mtk1\">: .</span><span class=\"mtk12\">cancel</span><span class=\"mtk1\">, </span><span class=\"mtk11\">handler</span><span class=\"mtk1\">:{ (UIAlertAction)</span><span class=\"mtk15\">in</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk11\">print</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;User click Dismiss button&quot;</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}))</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">self</span><span class=\"mtk1\">.</span><span class=\"mtk11\">present</span><span class=\"mtk1\">(alert, </span><span class=\"mtk11\">animated</span><span class=\"mtk1\">: </span><span class=\"mtk4\">true</span><span class=\"mtk1\">, </span><span class=\"mtk11\">completion</span><span class=\"mtk1\">: {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk11\">print</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;completion block&quot;</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">})</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">//  ============================= //</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">// this is to share file //</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">func</span><span class=\"mtk1\"> </span><span class=\"mtk11\">shareDocument</span><span class=\"mtk1\">(</span><span class=\"mtk11\">documentPath</span><span class=\"mtk1\">: </span><span class=\"mtk10\">String</span><span class=\"mtk1\">) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">if</span><span class=\"mtk1\"> FileManager.</span><span class=\"mtk12\">default</span><span class=\"mtk1\">.</span><span class=\"mtk11\">fileExists</span><span class=\"mtk1\">(</span><span class=\"mtk11\">atPath</span><span class=\"mtk1\">: documentPath){</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk4\">let</span><span class=\"mtk1\"> fileURL = </span><span class=\"mtk11\">URL</span><span class=\"mtk1\">(</span><span class=\"mtk11\">fileURLWithPath</span><span class=\"mtk1\">: documentPath)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk4\">let</span><span class=\"mtk1\"> activityViewController: UIActivityViewController = </span><span class=\"mtk11\">UIActivityViewController</span><span class=\"mtk1\">(</span><span class=\"mtk11\">activityItems</span><span class=\"mtk1\">: [fileURL], </span><span class=\"mtk11\">applicationActivities</span><span class=\"mtk1\">: </span><span class=\"mtk4\">nil</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  activityViewController.</span><span class=\"mtk12\">popoverPresentationController</span><span class=\"mtk1\">?.</span><span class=\"mtk12\">sourceView</span><span class=\"mtk1\">=</span><span class=\"mtk4\">self</span><span class=\"mtk1\">.</span><span class=\"mtk12\">view</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk11\">present</span><span class=\"mtk1\">(activityViewController, </span><span class=\"mtk11\">animated</span><span class=\"mtk1\">: </span><span class=\"mtk4\">true</span><span class=\"mtk1\">, </span><span class=\"mtk11\">completion</span><span class=\"mtk1\">: </span><span class=\"mtk4\">nil</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">else</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk11\">print</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;Document was not found&quot;</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<p>Call <code>allOptions()</code> from IBAction pressForLogs. Above functions will open ActivityViewContrrolle to let the user mail log file to you.</p>\n</li>\n</ul>\n<h4 id=\"voila-\" style=\"position:relative;\"><a href=\"#voila-\" aria-label=\"voila  permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Voila!! :)</h4>\n<p>Thanks for visiting us! We hope you find this knowledge base useful! Our mission is to make mobile app development happy. We hope we’re living up to the mission with your project.</p>\n<p>Please write to us for suggestions and for the contents we should come up with!</p>\n<p>Thanks for reading the blog. For detailed information and execution example of this blog, please refer to the video below:</p>\n<iframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/KTnFtIvoDiI\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>\n<style class=\"grvsc-styles\">\n  .grvsc-container {\n    overflow: auto;\n    -webkit-overflow-scrolling: touch;\n    padding-top: 1rem;\n    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));\n    padding-bottom: 1rem;\n    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));\n    border-radius: 8px;\n    border-radius: var(--grvsc-border-radius, 8px);\n    font-feature-settings: normal;\n  }\n  \n  .grvsc-code {\n    display: inline-block;\n    min-width: 100%;\n  }\n  \n  .grvsc-line {\n    display: inline-block;\n    box-sizing: border-box;\n    width: 100%;\n    padding-left: 1.5rem;\n    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));\n    padding-right: 1.5rem;\n    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));\n  }\n  \n  .grvsc-line-highlighted {\n    background-color: var(--grvsc-line-highlighted-background-color, transparent);\n    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);\n  }\n  \n  .dark-default-dark {\n    background-color: #1E1E1E;\n    color: #D4D4D4;\n  }\n  .dark-default-dark .mtk4 { color: #569CD6; }\n  .dark-default-dark .mtk1 { color: #D4D4D4; }\n  .dark-default-dark .mtk12 { color: #9CDCFE; }\n  .dark-default-dark .mtk15 { color: #C586C0; }\n  .dark-default-dark .mtk3 { color: #6A9955; }\n  .dark-default-dark .mtk11 { color: #DCDCAA; }\n  .dark-default-dark .mtk10 { color: #4EC9B0; }\n  .dark-default-dark .mtk8 { color: #CE9178; }\n  .dark-default-dark .mtk6 { color: #D7BA7D; }\n</style>","frontmatter":{"title":"How to obtain iOS application logs without Mac","author":{"id":"Tanvi Jain","github":"tanvijn","avatar":null},"date":"July 22, 2020","updated_date":null,"tags":["Logs","ios","xcode","iPhone","troubleshoot","Mac"],"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1.5037593984962405,"src":"/static/4fdc8a84c6075fd3dd77f0b0be3f1939/58556/Log.webp","srcSet":"/static/4fdc8a84c6075fd3dd77f0b0be3f1939/61e93/Log.webp 200w,\n/static/4fdc8a84c6075fd3dd77f0b0be3f1939/1f5c5/Log.webp 400w,\n/static/4fdc8a84c6075fd3dd77f0b0be3f1939/58556/Log.webp 800w,\n/static/4fdc8a84c6075fd3dd77f0b0be3f1939/99238/Log.webp 1200w,\n/static/4fdc8a84c6075fd3dd77f0b0be3f1939/90fb1/Log.webp 1500w","sizes":"(max-width: 800px) 100vw, 800px"}}}},"fields":{"authorId":"Tanvi Jain","slug":"/engineering/how-to-obtain-ios-application-logs-without-mac/"}}}]},"authorYaml":{"id":"Tanvi Jain","bio":"A Mobile application developer based on Jaipur, India. Having 6+ years of experience in iOS App development with Client based & Product based organizations.","github":"tanvijn","stackoverflow":null,"linkedin":"tanvi-jain-044b6585","medium":null,"twitter":null,"avatar":null}},"pageContext":{"id":"Tanvi Jain","__params":{"id":"tanvi-jain"}}},"staticQueryHashes":["1171199041","1384082988","2100481360","23180105","528864852"]}