Gentle Bytes BlogRamblings, news, programming recipes and more...http://gentlebytes.com/2019-09-01T02:00:00+02:00TomazStartupizer no longer available for sale/blog/2019/09/01/startupizer-deprecated/2019-09-01T02:00:00+02:002019-09-01T02:00:00+02:00Article Author<p>As of September 1st 2019, after 10 years of development, Startupizer is no longer available for sale.</p>
<p></p>
<p>Due to my gradual personal and developer transition away from Apple platforms, it has become increasingly difficult for me to maintain Startupizer. I did my best for the past one and a half years. This is my first true indie software so it was not an easy decision. But ultimately I felt my customers deserve better than I was able to provide, so as hard as it may be, I had to reach conclusion, and after 10 years of development, I am pulling the plug… I sincerely thank each and every customer from all over the world that trusted me with purchase! I hope you find Startupizer useful addition to your daily macOS experience! It should of course continue to work just fine, and I will continue to provide support, both technical and licensing for foreseeable future. However, there is possibility one of future macOS updates will prevent Startupizer from working correctly. In this case I may no longer be able to provide solution. But let’s hope this will not be the case!</p>
<p>I did my best to find alternative solution. Earlier this year, I reached out to fellow developer community trying to fine better home for it, but unfortunately didn’t get any response. I also contemplated the option to open source the code and perhaps prolong the life this way, but for the moment didn’t opt for it either. I am still open for both alternatives. While Startupizer is not profitable enough for me to warrant full attention on its own, it had constant monthly sales without any advertising from my part on the other hand. I feel it still has potential for nice income, especially when added to portfolio of multiple apps. If you are iOS or macOS developer and it feels like a good project for you, definitely contact me!</p>
<p>Again, thanks for all you support and feedback, and who knows, we may meet again in the future!</p>
Startupizer 2.3.11 released!/blog/2018/05/28/startupizer-2-3-11-released/2018-05-28T02:00:00+02:002018-05-28T02:00:00+02:00Article Author<p>Startupizer 2.3.11 is now available. Recommended for all customers.</p>
<p></p>
<p>This is just internal update to ensure GPRD compliance: in-app contact is now redirected to website instead of using third party handling.</p>
<p>Note: I value my privacy as well as privacy of all website readers and users of my applications. I used third party in-app contact form because it allowed users to attach screenshots or any other file to their questions or reports. This greatly simplified debugging and my ability to help when something didn’t work as intended. However this third party contact form used web server I didn’t control to send the data. It ultimately converted the request into support email and all further discussion was handled directly via email with no intermediate. To my knowledge, no personal information (apart from optional email) was stored on server, but I got no reply from the company when I asked. So I decided to use contact form on website for which I have full control.</p>
<p>On similar notice: this website doesn’t use any cookies apart from Google Analytics. However with this update, I’m also removing GA. I rarely used it, so it didn’t provide a lot of value anyway. I might add it back in the future - I will of course announce any change.</p>
URLRequest debugging/blog/2018/02/28/request-debugging/2018-02-28T01:00:00+01:002018-02-28T01:00:00+01:00Article Author<p>For most iOS applications, we need to handle server communication. UIKit provides <code>URLRequest</code> which manages requests to server. In this post we’ll take a look at how we can extend it to simplify request debugging.</p>
<p></p>
<p>When working with backend, we frequently encounter situations where we’d like to examine data returned from server as response to our requests, so we usually log requests (and replies) to be prepared for when communication doesn’t go according to expectations.</p>
<p>But frequently we want to examine the data independently of the application - for example, it may take couple steps to reach the screen that uses certain endpoint, or we just want to confirm the data is correctly interpretted by our code. We could do that with <code>curl</code> in Terminal, but that’s complicated due to various factors like OAuth tokens or dynamic headers we need to attach in order for request to succeed.</p>
<p>Or is it? <code>URLRequest</code> already includes all the data needed, so why can’t we use it to log <code>curl</code> command we can later paste and use in Terminal? No reason at all 😉</p>
<h3 id="solution">Solution</h3>
<p>Declare extension to <code>URLRequest</code>:</p>
<div class="highlight"><pre class="highlight swift"><code><span class="kd">extension</span> <span class="kt">URLRequest</span> <span class="p">{</span>
<span class="kd">public</span> <span class="k">var</span> <span class="nv">curlString</span><span class="p">:</span> <span class="kt">String</span> <span class="p">{</span>
<span class="c1">// Logging URL requests in whole may expose sensitive data,</span>
<span class="c1">// or open up possibility for getting access to your user data,</span>
<span class="c1">// so make sure to disable this feature for production builds!</span>
<span class="cp">#if !DEBUG</span>
<span class="k">return</span> <span class="s">""</span>
<span class="cp">#else</span>
<span class="k">var</span> <span class="nv">result</span> <span class="o">=</span> <span class="s">"curl -k "</span>
<span class="k">if</span> <span class="k">let</span> <span class="nv">method</span> <span class="o">=</span> <span class="n">httpMethod</span> <span class="p">{</span>
<span class="n">result</span> <span class="o">+=</span> <span class="s">"-X </span><span class="se">\(</span><span class="n">method</span><span class="se">)</span><span class="s"> </span><span class="se">\\\n</span><span class="s">"</span>
<span class="p">}</span>
<span class="k">if</span> <span class="k">let</span> <span class="nv">headers</span> <span class="o">=</span> <span class="n">allHTTPHeaderFields</span> <span class="p">{</span>
<span class="k">for</span> <span class="p">(</span><span class="n">header</span><span class="p">,</span> <span class="n">value</span><span class="p">)</span> <span class="k">in</span> <span class="n">headers</span> <span class="p">{</span>
<span class="n">result</span> <span class="o">+=</span> <span class="s">"-H </span><span class="se">\"\(</span><span class="n">header</span><span class="se">)</span><span class="s">: </span><span class="se">\(</span><span class="n">value</span><span class="se">)\"</span><span class="s"> </span><span class="se">\\\n</span><span class="s">"</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">if</span> <span class="k">let</span> <span class="nv">body</span> <span class="o">=</span> <span class="n">httpBody</span><span class="p">,</span> <span class="o">!</span><span class="n">body</span><span class="o">.</span><span class="n">isEmpty</span><span class="p">,</span> <span class="k">let</span> <span class="nv">string</span> <span class="o">=</span> <span class="kt">String</span><span class="p">(</span><span class="nv">data</span><span class="p">:</span> <span class="n">body</span><span class="p">,</span> <span class="nv">encoding</span><span class="p">:</span> <span class="o">.</span><span class="n">utf8</span><span class="p">),</span> <span class="o">!</span><span class="n">string</span><span class="o">.</span><span class="n">isEmpty</span> <span class="p">{</span>
<span class="n">result</span> <span class="o">+=</span> <span class="s">"-d '</span><span class="se">\(</span><span class="n">string</span><span class="se">)</span><span class="s">' </span><span class="se">\\\n</span><span class="s">"</span>
<span class="p">}</span>
<span class="k">if</span> <span class="k">let</span> <span class="nv">url</span> <span class="o">=</span> <span class="n">url</span> <span class="p">{</span>
<span class="n">result</span> <span class="o">+=</span> <span class="n">url</span><span class="o">.</span><span class="n">absoluteString</span>
<span class="p">}</span>
<span class="k">return</span> <span class="n">result</span>
<span class="cp">#endif</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div>
<h3 id="usage">Usage</h3>
<p>And log it:</p>
<div class="highlight"><pre class="highlight swift"><code><span class="k">let</span> <span class="nv">request</span> <span class="o">=</span> <span class="o">...</span>
<span class="nf">print</span><span class="p">(</span><span class="s">"</span><span class="se">\(</span><span class="n">request</span><span class="o">.</span><span class="n">curlString</span><span class="se">)</span><span class="s">"</span><span class="p">)</span>
</code></pre></div>
<p>And voila! We’re ready for next hard core debugging session - enable logging, navigate to screen with request you want to log and copy the text from Xcode console! 😀</p>
<h3 id="conclusion">Conclusion</h3>
<p>With minimal work we created useful debugging tool! <strong>BUT</strong> it’s not just our debugging tool, <code>curl</code>s are super useful to pass on to backend developers so they can easily investigate the issue on their side! Or to simplify the <a href="https://paw.cloud/docs/getting-started/import-curl">import</a> to <a href="https://paw.cloud/">Paw</a>. Or…. 😉</p>
Startupizer 2.3.10 released!/blog/2017/09/26/startupizer-2-3-10-released/2017-09-26T02:00:00+02:002017-09-26T02:00:00+02:00Article Author<p>Startupizer 2.3.10 is now available. Recommended for all customers.</p>
<p></p>
<p>Previous version, 2.3.9 fixed issues with betas and GM versions of macOS 10.13 High Sierra. But it turned out public release broke it again. 2.3.10 fixes these issues with released version of High Sierra.</p>
Startupizer 2.3.9 released!/blog/2017/09/06/startupizer-2-3-9-released/2017-09-06T02:00:00+02:002017-09-06T02:00:00+02:00Article Author
<p>Startupizer 2.3.9 is now available. Recommended for all customers.</p>
<p></p>
<p>This version fixes macOS 10.13 High Sierra spinning beach balls affecting some users.</p>
Startupizer 2.3.8 released!/blog/2017/07/03/startupizer-2-3-8-released/2017-07-03T02:00:00+02:002017-07-03T02:00:00+02:00Article Author
<p>Startupizer 2.3.8 is now available. Recommended for all customers.</p>
<p></p>
<p>Besied couple under the hood improvements and fixes, this update also addresses couple visual issues when running on macOS 10.12 Sierra.</p>
<p>Note for those running on contemplating on installing developer preview or public beta of macOS 10.13 High Sierra: tested 2.3.7 and 2.3.8 and both versions run without any noticable issue. But definitely let me know if you run into something (I recommend using in-app contact sheet as you can also attach screenshots and other files)!</p>