Jekyll2020-06-18T06:29:59+00:00https://blog.theivan.io/feed.xmlIvan ParfenchukPersonal blog of Ivan ParfenchukRately: Do What’s Important, Daily2020-06-15T05:00:00+00:002020-06-15T05:00:00+00:00https://blog.theivan.io/my/apps/2020/06/15/rately-theme-system-journal-app<h2 id="background">Background</h2>
<p>In February 2019 I picked up a new habit: every evening I open my Google Sheet called “Everyday questions”, go through the list of questions and mark them as 0, 1, or 2.</p>
<p>“Zero” means I did <em>nothing</em> about it, “one” means I did <em>something</em> and “two” means that I did <em>enough</em>.</p>
<p>Since then I’ve logged 3348 data points.</p>
<p>This evening reflection gives me closure for the day, lets me see what I’ve accomplished, and even made me change my working schedule to a four-day working week. Before that, I rarely looked back at my day in detail, but now I’m doing it daily.</p>
<h2 id="rately">Rately</h2>
<p>You don’t need much to start tracking your days: a diary, a spreadsheet or a database.</p>
<p>But what is the best way to solve a problem like that?</p>
<p>Of course, it’s an app!</p>
<p>Please, welcome, <a href="https://rately.cc"><strong>Rately</strong></a>.</p>
<p><img src="/assets/2020-05-11-rately-splash-screen.png" alt="Rately app icon" class="half-page-image" /> <img src="/assets/2020-05-11-rately-screenshot.png" alt="Rately app icon" class="half-page-image" /></p>
<p>Rately lets you track your most important activities daily.</p>
<p>Just create a new activity and start tracking.</p>
<h2 id="neumorphic-design">Neumorphic design</h2>
<p>In case you miss skeuomorphic design from the pre-iOS 7 era, we have a treat for you.</p>
<p>In February, when I was struggling with design, <a href="https://www.producthunt.com/@mike_z3">Mikhail Zakharov</a> approached me with this beautiful new <strong>Neumorphic</strong> style.</p>
<p>The trick is to use off-white background and black/pure white semi-transparent shadows.</p>
<p><img src="/assets/2020-05-11-rately-neumorphism.png" alt="Rately Neumorphic design" /></p>
<h2 id="swiftui">SwiftUI</h2>
<p>The app is built with the new SwiftUI technology that Apple released last year.</p>
<p>SwiftUI lets you build and iterate over the interface quickly. However, in my experience, it has a lot of rough edges.</p>
<p>My first UI iteration failed due to the lack of fine-control over gestures in SwiftUI. When one pan gesture started conflicting with another, I was not able to resolve this conflict and had to ditch the design completely.</p>
<p>Another annoying point that I encountered was the way you build animations.
There are lots of tutorials around the internet on how you can build different animations easily with SwiftUI.</p>
<p>However, the way you get to a sleek piece of SwiftUI code, in my experience, is often non-obvious.</p>
<h2 id="subscriptions-via-revenuecat">Subscriptions via RevenueCat</h2>
<p>The app has a subscription in it, mostly to let users support the creators.</p>
<p>And this time we implemented subscriptions via <a href="https://www.revenuecat.com">RevenueCat</a>. Let me tell you what a treat it is to use RevenueCat!</p>
<p>If you ever implemented server-side receipt verification for In-App Purchase subscriptions, you should know that it’s quite a hassle to set everything up. Trials, renewals, verification, receipt storage, and on top of that, you still need to implement StoreKit integration locally. RevenueCat takes all that pain away.</p>
<p>There is some new RevenueCat terminology you need to learn, like entitlements and offerings, but it’s simple and they have great documentation available.</p>
<h2 id="get-it-now">Get it now</h2>
<p>Please, go to the App Store, try the app and let me know what you think!</p>
<p><a href="https://apps.apple.com/app/id1510322095"><img src="/assets/Download_on_the_App_Store_Badge.svg" alt="Download on the App Store" /></a></p>BackgroundКак скачать видео с ВК на айфон2020-03-08T15:00:00+00:002020-03-08T15:00:00+00:00https://blog.theivan.io/ru/%D0%B8%D0%BD%D1%81%D1%82%D1%80%D1%83%D0%BA%D1%86%D0%B8%D0%B8/2020/03/08/%D0%BA%D0%B0%D0%BA-%D1%81%D0%BA%D0%B0%D1%87%D0%B0%D1%82%D1%8C-%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE-%D1%81-%D0%B2%D0%BA-%D0%BD%D0%B0-%D0%B0%D0%B9%D1%84%D0%BE%D0%BD<h2 id="шаг-1-скопируйте-ссылку-на-видео">Шаг 1: скопируйте ссылку на видео</h2>
<p>В приложении VK это делается с помощью … меню:</p>
<p><img src="/assets/2020-03-08-copy-link-for-vk-video-app-1.jpg" alt="Как скопировать ссылку на видео вк" class="half-page-image" /> <img src="/assets/2020-03-08-copy-link-for-vk-video-app-2.jpg" alt="Как скопировать ссылку на видео вк" class="half-page-image" /></p>
<p>На сайте с помощью кнопки Поделиться <img src="/assets/share-icon.png" alt="Поделиться" class="share-icon" />:</p>
<p><img src="/assets/2020-03-08-copy-link-for-vk-video-website-1.jpg" alt="Как скопировать ссылку на видео на сайте вк шаг первый" class="half-page-image" /> <img src="/assets/2020-03-08-copy-link-for-vk-video-website-2.jpg" alt="Как скопировать ссылку на видео на сайте вк шаг второй" class="half-page-image" /></p>
<h2 id="шаг-2-getvideoorg">Шаг 2: getvideo.org</h2>
<p>Затем на сайте <a href="https://getvideo.org/ru">getvideo.org</a> вставьте ссылку на видео и нажмите <strong>-></strong>.
<img src="/assets/2020-03-08-getvideo-paste-link-1.jpg" alt="Вставьте ссылку на getvideo.org" /></p>
<h2 id="шаг-3-скачайте-видео">Шаг 3: Скачайте видео</h2>
<p>После обработки видео, ссылки для скачивания появятся внизу страницы. Выберите разрешение и нажмите “Скачать”:</p>
<p><img src="/assets/2020-03-08-getvideo-download-video.jpg" alt="Вставьте ссылку на getvideo.org" /></p>
<p>При этом видео сохранится в приложение Файлы и будет доступно на вашем устройстве в офлайне.</p>
<p>Для того чтобы открыть загруженное видео, нажмите на иконку “Загрузки” в правом-верхнем углу и кликните на видео.</p>
<p><img src="/assets/2020-03-08-safari-downloads-button.jpg" alt="Список "Загрузки" в Safari" /></p>
<p><img src="/assets/2020-03-08-safari-downloads-open-video.jpg" alt="Список загрузок в Safari" /></p>
<p>Чтобы открыть приложение Файлы, нажмите на иконку лупы справа от названия видео.</p>
<p><img src="/assets/2020-03-08-safari-downloads-open-files-app.jpg" alt="Открыть приложение Файлы" /></p>Шаг 1: скопируйте ссылку на видеоHow to make watchOS-only application (no iOS counterpart)2020-02-14T06:00:00+00:002020-02-14T06:00:00+00:00https://blog.theivan.io/watchkit/2020/02/14/watchos-only-app<p>In this guide, we follow the process of creating a <strong>watchOS-only</strong> application, which doesn’t have an iOS counterpart and available only on the App Store for Apple Watch.</p>
<h2 id="create-a-new-project-in-xcode">Create a new project in Xcode</h2>
<p>Click File -> New -> Project (Shift+cmd+N), select <strong>watchOS</strong> tab and choose <strong>Watch App</strong>.</p>
<p><img src="/assets/2020-02-14-watchos-app-xcode-project.jpg" alt="Creating new watchOS project" /></p>
<p>Enter a name, hit Next and select a folder where you want to save your project.</p>
<h2 id="create-a-new-app-id-in-developer-portal">Create a new App ID in Developer Portal</h2>
<p>Create a new App ID in Apple Developer Portal here: <a href="https://developer.apple.com/account/resources/identifiers/bundleId/add/">Apple Developer Portal New App ID page</a></p>
<p><img src="/assets/2020-02-14-watchos-app-developer-portal-app-id.png" alt="Creating new App ID" /></p>
<h2 id="app-store-connect">App Store Connect</h2>
<p>In App Store Connect, go to My Apps, click <strong>+</strong>, then <strong>New App</strong> and select, counterintuitively, <strong>iOS</strong> platform.</p>
<p><img src="/assets/2020-02-14-watchos-app-app-store-connect-new-app.png" alt="Creating new App in App Store Connect" /></p>
<p>The last unusual thing you need to skip the usual <strong>App Previews and Screenshots</strong> section.</p>
<p><img src="/assets/2020-02-14-watchos-app-app-store-connect-skip-ios-screenshots.png" alt="Skip iOS Screenshots section" /></p>
<p>Scroll further and expand the <strong>Apple Watch</strong> section. That’s where you are going to upload your screenshots.</p>
<p><img src="/assets/2020-02-14-watchos-app-app-store-connect-watchos-screenshots.png" alt="Upload watchOS screenshots in Apple Watch section" /></p>
<p>If you need a quick way to generate icon sizes for different Apple Watch, you can use service like App Icon Generator, but pay attention to compression artifacts which can appear on some icons: <a href="https://appicon.co">App Icon Generator</a></p>
<h2 id="metronome-for-watch">Metronome for Watch</h2>
<p>As a quick exercise I made this small haptic Metronome watchOS app which is distributed on the App Store for Apple Watch: <a href="https://apps.apple.com/us/app/metronome-for-watch/id1498649562?ls=1">Metronome for Watch app</a></p>
<p><img src="/assets/2020-02-14-watchos-app-metronome-for-watch.jpg" alt="Skip iOS Screenshots section" /></p>In this guide, we follow the process of creating a watchOS-only application, which doesn’t have an iOS counterpart and available only on the App Store for Apple Watch.How to make Apple Watch Haptic Engine continue playing in background2020-02-02T18:35:23+00:002020-02-02T18:35:23+00:00https://blog.theivan.io/watchkit/2020/02/02/apple-watch-haptics-in-background<p>If you are building an app where you want the haptics to continue playing when your Apple Watch app is sent to the background, you need to use the so-called “Extended session” (WKExtendedRuntimeSession).</p>
<p>For that:</p>
<ol>
<li>Head to your <em>WatchKit Extension</em> target settings</li>
<li>Click Signing & Capabilities</li>
<li>Click + Capability to add new Capability</li>
<li>Find and select “Background Mode” capability, double click it</li>
</ol>
<p>In “Background Modes” capability select the “Session Type” that suits your app functionality. In this example, I’ll use “Self Care”</p>
<p><img src="/assets/2020-02-02-haptic-in-background.jpg" alt="Configuring Background mode for WatchKit Extension" /></p>
<p>Then, when you start playing the haptics, you need to start the “Extended session”:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>func startSession() {
session = WKExtendedRuntimeSession()
session.start()
}
</code></pre></div></div>
<p>When it’s time to end playing the haptics, you need to invalidate your extended session:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>func stopSession() {
session.invalidate()
}
</code></pre></div></div>
<p>There is one caveat though. You can’t continue playing haptics if the user exits your app (by clicking on the Digital Crown).
In that case, watchOS stops your extended session and you need to reactivate it when the user comes back.</p>
<p>For that, we will use one of the <code class="language-plaintext highlighter-rouge">WKExtensionDelegate</code> methods <code class="language-plaintext highlighter-rouge">applicationDidBecomeActive</code>.
Let’s imagine we are using a shared <code class="language-plaintext highlighter-rouge">HapticEngine</code> component to control our haptics.</p>
<p>Then, in WKExtensionDelegate we could add something like that:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>class ExtensionDelegate: NSObject, WKExtensionDelegate {
func applicationDidBecomeActive() {
// Restart our WKExtendedRuntimeSession
HapticEngine.shared.startSessionIfNeeded()
}
// ... other methods
}
</code></pre></div></div>
<p>Here is a final HapticsEngine drop-in class that allows you to play haptics every second, even if the Apple Watch screen dims:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>class HapticsEngine: NSObject, ObservableObject {
static let shared = HapticEngine()
private var timer: Timer?
private var session = WKExtendedRuntimeSession()
private var isPlaying: Bool { timer != nil }
private func startSessionIfNeeded() {
guard !isPlaying, session.state != .running else { return }
session = WKExtendedRuntimeSession()
session.start()
}
private func stopSession() {
session.invalidate()
}
private func tick() {
WKInterfaceDevice.current().play(.start)
timer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: false, block: { [weak self] (_) in
self?.tick()
})
}
func startPlayinTicks() {
timer?.invalidate()
timer = nil
startSessionIfNeeded()
tick()
}
func stopPlayingTicks() {
timer?.invalidate()
timer = nil
stopSession()
}
}
</code></pre></div></div>If you are building an app where you want the haptics to continue playing when your Apple Watch app is sent to the background, you need to use the so-called “Extended session” (WKExtendedRuntimeSession).10 years of remote work: tips and tricks2020-01-22T17:35:23+00:002020-01-22T17:35:23+00:00https://blog.theivan.io/remote/work/2020/01/22/remote-work<p>It is my tenth year of working remotely in various companies and teams. To celebrate the upcoming anniversary I want to share some difficulties I’ve met and ways to overcome them.</p>
<p>So, what I find to be difficult when working remotely?</p>
<h2 id="staying-on-top-of-the-company-life">Staying on top of the company life</h2>
<p>If the company you are working in is not remote-first, it might be difficult to stay on top of everything. If there are headquarters where all the decision-makers are sitting, you will tend to be on the receiving end most of the time. That might be fine for some people, but if you want to engage in the company’s life, sometimes that might feel frustrating.</p>
<p>What I found to be helpful:</p>
<ul>
<li>Daily stand-up video calls. The more often you talk to folks at the HQ, the more up-to-date you are going to be</li>
<li>Engaging all members of your team. The more often members of your team participate in the discussions, the more informed they are going to be, the more grounded the decision making is going to feel</li>
<li>Sharing the information openly. When information is shared openly, people can see the reasoning behind the decisions and that makes your team more cohesive</li>
<li>Using real-time discussion tools like miro.com was helpful as well</li>
</ul>
<h2 id="lack-of-human-contact">Lack of human contact</h2>
<p>When I only see my coworkers on video, it starts feeling lonely sometimes. Talking on video is not the same as talking in real life, and I find that some kind of human contact is necessary. Some companies do get together a few times a year and I find that helpful to connect with your colleagues, but not enough.</p>
<p><img src="/assets/2020-01-19-cocoaheads-small-img.jpg" alt="Cocoaheads meetup" /></p>
<p>If you feel lonely, here are some of the activities that might help:</p>
<ul>
<li>Local meetups and conferences. If your coworkers are far away, but you want to talk about your work, meetups and conferences are great places to do that</li>
<li>Going to work outside of your home office. Places like coworking spaces, libraries and cafes are full of people like you. Go outside, find a place to sit and just be there</li>
<li>Small-talk with your colleagues, even via the internet is humanizing and might be the activity that helps you understand each other</li>
</ul>
<h2 id="lack-of-physical-activity">Lack of physical activity</h2>
<p>Without having to commute, sometimes I spend 48 hours without leaving my home. There is no way this is a healthy pattern so I try to compensate for it as I can.</p>
<p>This is what might help you:</p>
<ul>
<li>Signing up for a gym. Find a gym near your home and do the exercise that you enjoy. Group training, weightlifting, running on a treadmill. Start small, but regularly and at some point, it might become a habit</li>
<li>Going out for a walk. If you spend the whole day working at home, it’s nice to take a 30 min walk in the evening. Clear up your mind and get some fresh air</li>
<li>Walking to cafes/coworking spaces regularly. You can create an artificial commute for yourself and at least take a walk regularly to a place where you do the work</li>
</ul>
<h2 id="growing-professionally">Growing professionally</h2>
<p>If your company doesn’t have any programs to grow employees, you are on your own. Some companies might be better than others, but if you don’t feel pressure to grow from your coworkers, that might be a problem.</p>
<p>This is what I find helpful:</p>
<ul>
<li>Attending conferences/meetups and talking to people there. You can learn the latest trends and learn how things work in other companies</li>
<li>Setting aside time to learn. Chose a time that you spend just for learning each week. Don’t do anything else at that time and you will do some progress each week</li>
<li>Sign up for an online course. There are so many of them these days. Online education platforms like Udacity, Coursera, courses from universities like edX, MIT OpenCourseWare</li>
<li>Finding online communities around the topics you are interested to learn. Communities like OpenDataScience, Cocoaheads might be a great source of inspiration and material</li>
</ul>
<h2 id="discipline">Discipline</h2>
<p>When you are at home, it might be too easy to relax. Just move 10 meters to your couch, close your eyes and you are sleeping. Or go do some chores, after all, it is also important to keep the house clean!</p>
<p>What are the tricks that can keep yourself disciplined?</p>
<ul>
<li>Wake up at the same time. Even better if you can go to bed at the same time. Having enough sleep each night is great for your brain and helps you focus in the daytime.</li>
<li>Dress appropriately. Take off your comfy clothes and put on something more official. For me, it just changes the mood and makes me feel more oriented to work rather than to rest.</li>
<li>Have a dedicated space for your work. A good table, a chair, located at the same place in your house. When you sit there means that you are going to work and your brain gets used to it.</li>
<li>Turn off social networks, alerts and put away your phone. If they are too distracting for you, using additional tools to restrict yourself might be helpful. Try Limits in Screen Time on iOS</li>
</ul>
<h2 id="tldr">TL;DR</h2>
<p>It might be difficult to be on top of things happening in the company. Some people might feel lonely. It might be more difficult to grow professionally.
And I find that the most important decisions are still better to do in a face-to-face meeting.</p>
<p>However, remote work can be great in terms of productivity and flexibility! Stay tuned for the second post in the series.</p>It is my tenth year of working remotely in various companies and teams. To celebrate the upcoming anniversary I want to share some difficulties I’ve met and ways to overcome them.Bitbucket + Bitrise: Configuring Continuous Integration for an iOS app2019-04-29T18:00:00+00:002019-04-29T18:00:00+00:00https://blog.theivan.io/continuous/integration/2019/04/29/bitbucket-bitrise<p>When iOS applications start growing, at some point it becomes essential to have a quick develop-release-test feedback loop. You can create this loop by doing everything manually, but it can be much quicker and more advanced if you use Continuous Integration (CI) tools.</p>
<p>With a CI tool, you can build up a history of releases and quickly see which build contained what. You can run tests for every build automatically and catch some inevitable bugs. You can have consistency in your release notes. And you can streamline your release cycles, which automates your checklists.
Sound interesting? Let’s try to build this feedback loop using Bitbucket Webhooks, Bitrise and fastlane.</p>
<p>For a couple of months, I’ve been tracking my time during the weekdays. I tried to track as much as I could, from the moment I wake up to the moment I go to bed.</p>
<h1 id="deployment-flow">Deployment flow</h1>
<p>The flow we are going to use for our Continuous Integration is going to look like this:</p>
<ol>
<li>Create & merge a Pull Request in Bitbucket</li>
<li><a href="https://bitbucket.org/product">Bitbucket</a> performs a “Webhook” HTTP request to Bitrise</li>
<li><a href="https://www.bitrise.io/">Bitrise</a> starts building the process and launches fastlane</li>
<li><a href="https://fastlane.tools/">fastlane</a> builds the app and sends it to App Store Connect</li>
<li>App Store Connect processes the build, and it becomes available in TestFlight</li>
</ol>
<h1 id="bitbucket-webhooks-and-git-branching-model">Bitbucket Webhooks and git branching model</h1>
<p>Each deployment starts from us creating a Pull Request.</p>
<p>Let’s say your team is using master git branch for code in the releasable state. It also makes new releases by merging this master branch to the release branch.</p>
<p>The following section describes how to create a Webhook manually. However, if you use Bitrise, it can create a Webhook for you automatically, so, feel free to skip to the Bitrise section.</p>
<h1 id="manual-webhook-configuration">Manual Webhook configuration</h1>
<p>Next, let’s configure Bitbucket Webhooks so that whenever someone pushes to release branch or merges Pull Request to release branch, the Webhook is triggered.</p>
<p>To do that go to your Bitbucket repository and click “Settings” in the side menu. Then click “Webhooks” in the “Workflows” section and then click “Add webhook.”</p>
<p>Fill out Title, URL (see below), set Status to Active, and select “Choose from a full list of triggers” for Triggers. The triggers we are going to use are:</p>
<ol>
<li>Repository: Push</li>
<li>Pull Request: Created, Updated</li>
</ol>
<p>To get the URL for our Webhook:</p>
<ol>
<li>Head over to Bitrise, create a new app</li>
<li>Open the Dashboard -> Your app -> Code tab</li>
<li>Scroll to Incoming Webhooks section and click Setup Manually.</li>
<li>Select “Bitbucket Webhooks” and copy the Webhook URL</li>
</ol>
<p><img src="/assets/2019-04-29-bitbucket-webhooks.png" alt="Configuring webhook in Bitbucket" /></p>
<h1 id="bitrise-and-automatic-webhook-configuration">Bitrise and automatic Webhook configuration</h1>
<p>Bitrise is a platform for Continuous Integration. You can configure different deployment “workflows” in it and have the Bitrise servers build and publish your application. Here are the steps to create a new deployment workflow for our CI setup.</p>
<iframe width="560" height="315" src="https://www.youtube.com/embed/UeIekFewrKM" frameborder="0" allowfullscreen=""></iframe>
<p>Bitrise is a platform for Continuous Integration. You can configure different deployment “workflows” in it and have the Bitrise servers build and publish your application. Here are the steps to create a new deployment workflow for our CI setup.</p>
<ol>
<li>First sign up in Bitrise, go to Dashboard, click “Add New App”</li>
<li>Select “Private” if you want your config and logs to stay private</li>
<li>Select Bitbucket and connect it to your account</li>
<li>Click “Auto-add SSH key” or configure SSH access manually</li>
<li>Enter <code class="language-plaintext highlighter-rouge">release</code> as branch name in the “Choose branch” step</li>
<li>In Project build configuration select “fastlane” , check that Fastlane lane is set to <code class="language-plaintext highlighter-rouge">ios release</code>.</li>
<li>Select the stack that you normally use to build your app or just the latest available Xcode/macOS and click Confirm.</li>
<li>In the last step “Webhook setup” click “Register Webhook for me”</li>
</ol>
<p>The last step creates a Webhook in Bitbucket, so you don’t have to do anything manually. You can head over to Bitbucket repository and check the Webhook configuration in Settings -> Webhooks.
In our setup, we are going to use fastlane to build and publish the app to App Store Connect.</p>
<h1 id="fastlane-configuration">Fastlane configuration</h1>
<p>Fastlane is a set of tools for automating development and release process.</p>
<p>Follow this guide to install fastlane: <a href="https://docs.fastlane.tools/getting-started/ios/setup">Setup — fastlane docs</a></p>
<p>In short, you need to install Xcode development tools:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>xcode-select --install
</code></pre></div></div>
<p>and then install fastlane via RubyGems</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo gem install fastlane -NV
</code></pre></div></div>
<p>or via brew:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>brew cask install fastlane
</code></pre></div></div>
<p>Then open the working directory of your app in the Terminal and initialize fastlane.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cd /path/to/your/app fastlane init
</code></pre></div></div>
<p>Select “3. 🚀 Automate App Store distribution”</p>
<p>Then follow the configuration requests. Fastlane can create and configure the new App Id for you and create a sample deployment “lane.” Lane is just a collection of steps, required to complete some scenario.</p>
<p>Once the configuration is finished, let’s open the Fastfile which has been created and configure our first deployment script. Fastlane has large set of tools for automating various processes like code signing, uploading of screenshots, running tests and so on. However, we are going to start with a simple setup:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>default_platform(:ios)
platform :ios do
desc "Push a new release build to the App Store"
lane :release do
build_app(scheme: "CITest")
upload_to_app_store(force: true, skip_metadata: true, skip_screenshots: true)
end
end
</code></pre></div></div>
<p>The “release” lane will</p>
<ol>
<li>Perform a build of your project build_app(scheme: “CITest”)</li>
<li>Upload the resulting ipa file to App Store Connect upload_to_app_store. In this guide, we are skipping Fastlane metadata upload.</li>
</ol>
<p>You can test your setup by opening your project directory in Terminal and running fastlane release:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cd /path/to/your/app/directory fastlane release
</code></pre></div></div>
<h1 id="code-signing">Code-signing</h1>
<p>If you see problems with code-signing start here: Troubleshooting — fastlane docs. You can use fastlane match to manage code signing, but be careful: if you already have generated Certificates and Provisioning Profiles, match can break things. However, if it’s a completely new setup or you don’t care much about the existing profiles, match is going to speed things up considerably.</p>
<p>We’ll use fastlane match in our example:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cd /path/to/your/app/directory
fastlane match development
fastlane match adhoc
fastlane match appstore
</code></pre></div></div>
<p>Then open the Xcode, turn off Automatic code signing and select provisioning profiles that match has generated.</p>
<p>After that, we can add match to our Fastfile:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>default_platform(:ios) platform :ios do
desc "Push a new release build to the App Store"
lane :release do
match(type: "appstore", readonly: true)
build_app(scheme: "CITest")
upload_to_app_store(force: true, skip_metadata: true, skip_screenshots: true)
end
end
</code></pre></div></div>
<table>
<tbody>
<tr>
</tr>
</tbody>
</table>
<h1 id="finishing-up-the-bitrise-setup">Finishing up the Bitrise setup</h1>
<p><img src="/assets/2019-04-29-bitrise-config.png" alt="Setting secrets in Bitrise" /></p>
<p>Bitrise is building the project on its servers which don’t have any of your passwords and credentials required to code-sign and upload your app to App Store Connect. Therefore we’ll have to share some of those, precisely these two:</p>
<ol>
<li>Login/password for App Store Connect user</li>
<li>Password to decrypt your match repository (if you use match)</li>
</ol>
<p>The App Store Connect user doesn’t have to be the one you use to control your apps. You can create a new user in App Store Connect, which only has access to the app you automate and has at least a Developer role.</p>
<p>Once you set your new App Store Connect user, head over to Bitrise and open Workflow Editor tab and then Secrets. Add two new secrets:
ITUNES_CONNECT_USER and ITUNES_CONNECT_PASSWORD with App Store credentials for this new user. Plus put the same password into FASTLANE_PASSWORD secret.</p>
<p>If you use match, then add one more secret called MATCH_PASSWORD with the password you used to encrypt match repository.</p>
<h1 id="conclusion">Conclusion</h1>
<p>That should be it. Try to create a new Pull Request and merge it and see if Bitrise triggers the new build. If everything goes well, you will see the new build in TestFlight and will be able to select it for your new iOS app version.</p>
<p><img src="/assets/2019-04-29-bitrise-green-build.png" alt="Successful build in Bitrise" /></p>
<p>There is much more that you can do with automated deployments, such as:</p>
<ol>
<li>Testing using a fastlane scan</li>
<li>Automated build number incrementation</li>
<li>dSYM uploads to Crashlytics_Raygun_etc</li>
</ol>
<p>However, start with simple things first. I hope this guide helps you!</p>When iOS applications start growing, at some point it becomes essential to have a quick develop-release-test feedback loop. You can create this loop by doing everything manually, but it can be much quicker and more advanced if you use Continuous Integration (CI) tools.Time tracking2018-10-22T18:00:00+00:002018-10-22T18:00:00+00:00https://blog.theivan.io/time/tracking/2018/10/22/time-tracking<p>For a couple of months, I’ve been tracking my time during the weekdays. I tried to track as much as I could, from the moment I wake up to the moment I go to bed.</p>
<p>Let’s go over an 11 week period and see what’s interesting in there, shall we?</p>
<p><img src="/assets/2018-10-22-time-tracking-img.jpg" alt="Toggl time tracking report" /></p>
<h1 id="eating">Eating</h1>
<p>One of the most surprising findings for me was that I spend so much time on food. On average, every weekday I spend</p>
<ul>
<li>45 minutes cooking</li>
<li>1 hour 10 minutes consuming food</li>
<li>10 minutes shopping at a supermarket</li>
<li>8 minutes unloading and loading dishwasher</li>
<li>5 minutes on breaks to eat or drink something
So it’s 2 hours and 18 minutes every day to food-related things.</li>
</ul>
<p>But this time includes our evening dinners with my wife, which are deliberately slow. Without it, it would hover around 1.5 hours every day.</p>
<h1 id="transportation">Transportation</h1>
<p>Thankfully, I work mostly from home, so I don’t have those commute hours that many people have. That allowed me to spend only 12 minutes every weekday when I had to transport myself somewhere.</p>
<h1 id="work">Work</h1>
<p>Pure working hours on my day job took around 6.5 hours every day.</p>
<h1 id="other">Other</h1>
<p>32 minutes every weekday in a shower or doing other stuff I have to do to keep my body clean
9 minutes doing sports
18 minutes playing video games
10 minutes mindlessly surfing web and social networks (could be more, but that’s what I tracked like wasted time for sure)</p>
<h1 id="conclusion">Conclusion</h1>
<p>Overall, that is a fun and insightful exercise I do once in a while. I feel like for me, the most interesting effects of it are:
You realize how scarce your time is. Outside of a day job, there are only a few hours each day you can allocate to whatever you want.
It makes you more aware of the time at every moment of your life. You wait in a queue of the post office somewhere and boom, 15 minutes of your life are gone.
For time tracking I used the app called Toggl — Free Time Tracking Software. It had quite a lot of UI issues during the iOS 12 Beta period, but seem to work better now.</p>For a couple of months, I’ve been tracking my time during the weekdays. I tried to track as much as I could, from the moment I wake up to the moment I go to bed.