Cocoa SwitchBy Boris Yurkevich.http://cocoaswitch.com/
Wed, 14 Feb 2018 11:13:19 +0000Wed, 14 Feb 2018 11:13:19 +0000Jekyll v3.6.2What's like to use cheap Android phone.<p>In past 2 days my friend asked me to help with her smartphone.<sup id="fnref:1"><a href="#fn:1" class="footnote">1</a></sup> That’s the only computer device she uses and she said she “can’t contact my husband any more because of ads”.</p>
<p>Device has to be charged from the top, which was very uncomfortable to use and cable was constantly disconnecting. The battery was old, we could use it only when charging.</p>
<p>First thing I noticed, is how big screen was, compared to my iPhone 6s. It was easy to read, with larger touch targets. That’s a plus, considering affordable cost of the device. Of course with such a low cost,<sup id="fnref:2"><a href="#fn:2" class="footnote">2</a></sup> there’s many compromises.</p>
<p>She started to show me dozen of apps she didn’t installed, games and gambling apps. While I navigated the phone ads popped up, I saw 4 kind of ads which could appear even on the Home Screen.</p>
<ol>
<li>Banner in the bottom.</li>
<li>Ads which look like Facebook bubble.</li>
<li>Google Play redirects. When I was using Google Play app, it would show me page with random game.</li>
<li>Full screen ads, some of them even faked lock screen UI.</li>
</ol>
<p>I was bombarded with notifications and alerts from “antivirus” and “cleaner” which I was canceling, I was sure it will go away after I reset the phone. How naive.</p>
<p>First thing I did is backed up her notes from third-party app. I could log in into Google and sync it. Then I installed Google Photos. Device didn’t have enough space and it offered to delete some apps right from the modal alert, which was nice. However then I run out of space again, and the modal alert offered to delete apps which I didn’t want to get rid of. There was no button to jump into Settings, I had to find storage manager on my own.</p>
<p>We uploaded all her photos and videos to Google. I even liked the experience, because Google offers free unlimited storage. I installed Google Contacts and Chrome. She had almost 2,000 contacts on her SIM card, Contacts app offered to back it up and it’s even cleaned SIM card automatically.</p>
<p>Ignorantly, I didn’t backed up WhatsApp conversations, which is possible to do with Google Drive. I though I could restore them logging in into her account but because her account was linked to her another oversea phone number, we couldn’t receive the text. So I had to create new account for her and we lost all conversations.</p>
<p>I reset her phone from the settings, surprised how many <strong>bloatware it had as part of the system.</strong> It wasn’t possible to remove system “antivirus” and “app cleaner”, Opera Mini and many other not wanted apps. All I could do is to disable notifications and disable constant monitoring. I didn’t trust it.</p>
<p>My biggest disappointment was <strong>the lack of OS update option.</strong> The device was sold with 5.1 and it is the only Android version it supports. I couldn’t even find this model on Lenovo website.</p>
<p>Another surprise was lack of Chinese keyboard from the OS. And this is device which specially made for China and sold by Chinese manufacturer. I installed Gboard but it also didn’t have Chinese. In despair, I searched Play Store for “Chinese keyboard” and found another keyboard from Google which did the job, it had only 1 Chinese language option which was poor because iOS has 2: traditional and simplified.</p>
<p>I installed Google Photos, Contacts and Chrome again but at some actions I was presented with option which include system app, there was no way to make OS remember my choice even when I ticked specific “do not ask again” option. This duplication felt through entire OS, there’s 2 settings app and many system apps can be find with alternatives from Google — Clock app, messages app. I tried to install messages app but it didn’t work properly, it didn’t show SMS messages.</p>
<p>Because Lollipop doesn’t have privacy permissions controls, when denying permission and then changing my mind, I had to reinstall an app. App would say “I can’t access camera, restart your phone” — which is ill-advised.</p>
<div class="footnotes">
<ol>
<li id="fn:1">
<p>She has Lenovo K50-t3s with 5.1 Lollipop. <a href="#fnref:1" class="reversefootnote">&#8617;</a></p>
</li>
<li id="fn:2">
<p>About <a href="https://www.pdevice.com/product/lenovo-k3-note-k50-t3s-price-specs">$106.99 on this day.</a> <a href="#fnref:2" class="reversefootnote">&#8617;</a></p>
</li>
</ol>
</div>
Wed, 14 Feb 2018 10:00:00 +0000http://cocoaswitch.com/2018/02/14/android/
http://cocoaswitch.com/2018/02/14/android/Jerry Bottle.<p><img src="http://cocoaswitch.com/images/jerry.jpg" alt="Silver bottle with Jerry Seinfeld photo" /></p>
Wed, 07 Feb 2018 22:10:00 +0000http://cocoaswitch.com/2018/02/07/jerry/
http://cocoaswitch.com/2018/02/07/jerry/Horrible Custom Smart App Banner Collection.<p>Apple has <a href="https://developer.apple.com/library/content/documentation/AppleApplications/Reference/SafariWebContent/PromotingAppswithAppBanners/PromotingAppswithAppBanners.html">simple manual for web developers how to make Smart App Banner.</a> It looks like this:
<img src="https://developer.apple.com/library/content/documentation/AppleApplications/Reference/SafariWebContent/Art/smartbanner_2x.png" alt="Picture from Apple website." title="Smart App Banner" /></p>
<p>Over past years I was collecting different custom implementations from all over the web. You will be surprised how creative some developers are.</p>
<p><img src="http://cocoaswitch.com/images/sap-ebay.jpg" alt="eBay" />
<img src="http://cocoaswitch.com/images/sap-glassdoor.jpg" alt="Glassdoor" />
<img src="http://cocoaswitch.com/images/sap-tastemade.png" alt="Tastemade" />
<img src="http://cocoaswitch.com/images/sap-cnet.jpg" alt="Cnet" />
<img src="http://cocoaswitch.com/images/sap-dmail.jpg" alt="Daily Mail" />
<img src="http://cocoaswitch.com/images/sap-adobe.jpg" alt="Adobe" />
<img src="http://cocoaswitch.com/images/sap-peak.jpg" alt="Peak" />
<img src="http://cocoaswitch.com/images/sap-telegraph.jpg" alt="Telegraph" /></p>
<p>And still it remains secret to me why would anyone wants custom solution for this problem? Is this blunt ignorance or might be it is designers who think their design is better than standard solution? Or perhaps it’s greed and website owner wants have more tracking? Anyway, this custom banners look worth and don’t work well. They have worth privacy as well, so don’t tap on them.</p>
<p><a href="https://itunes.apple.com/gb/app/altershot/id911930618?mt=8&amp;at=1010l4GJ&amp;ct=1010l4GJ">Screenshots edited in Altershot.</a></p>
Tue, 23 Jan 2018 17:18:00 +0000http://cocoaswitch.com/2018/01/23/smart-app-banner/
http://cocoaswitch.com/2018/01/23/smart-app-banner/How Electron Made GitHub Desktop Worse.<p>Not long ago GitHub released new version of their Mac app. Big update which is actually rewrite. New version uses Electron. We know Electron from Slack. I decided to compare 2 versions to demonstrate difference between native and not native.<br />
<img src="http://cocoaswitch.com/images/github-electron-web.png" alt="Website presents new version of GitHub Desktop" /></p>
<p>The fact that new version is presented as “The new native” offenses me. GitHub Desktop at farthest point from native it ever was.</p>
<p>Let’s look at App size.<br />
<img src="http://cocoaswitch.com/images/app-size.png" alt="2 app sizes" /></p>
<p>Old app is 63.7 MB and new is 168 MB. Not surprised as web app need to include all dependencies and custom frameworks. Native apps can use powerful system frameworks which is already included into OS once.</p>
<p>Let’s open application. First thing I noticed, minimum window size for Electron app is much larger. Look how many white space is wasted. Old native app could be resizes to much smaller size which makes it’s superior for those who keep many windows on screen and value space.</p>
<p><img src="http://cocoaswitch.com/images/new-electron.png" alt="Native version of GitHub Desktop" />
<img src="http://cocoaswitch.com/images/new-github.png" alt="Electron version of GitHub Desktop" /></p>
<p>Now let’s focus on the title bar. Electron app missing title. Not only title shows what item selected but is also possible to click on it and navigate file hierarchy. Right Click on the drop down menu and select item, this opens Finder.
<img src="http://cocoaswitch.com/images/title-bar.png" alt="Title Bar options" /></p>
<p>New app has black top and white content area. That’s not a good look, usually Mac apps have main color scheme, dark apps dark everywhere, iMovie is perfect example, and apps like Finder and Safari have light background.</p>
<p>On the screenshots you can see how basic “Add Local Repository” interface differs. Pay attention on the buttons styles, old GitHub apps has familiar buttons looks which is the same as any other Mac app, while new Electron app has its own style. Not only it looks out of place, this also adds additional cognitive load. The same is true for apps font, old app uses excellent system font. At least Cancel button is on the left.</p>
<p>Last let’s click on the File menu. Menu bar is important on Mac. Everything that’s app does can be accesses from menu bar, it allows user to study what app can do, it also displays shortcut commands.<br />
<img src="http://cocoaswitch.com/images/menu-comparison.png" alt="Menu comparison" /></p>
<p>Now here, I have to say, new GitHub Desktop does not a bad job, some web apps don’t have menu commands at all. However particularly in the File menu I noticed that old app had more options. One of most important changes is ability to open multiple windows. This core function is lacking from Electron version.</p>
<p>Another subtle benefit using native app is lack of need to click twice when window not active. Any web site or web app can recognize click only in active mode. Normal Mac apps can receive click events even when window not active. For example, you can click on the + button in top right corner of GitHub Desktop even when window is not active. Any web application will require 2 clicks in this situation.</p>
<h3 id="conclusion">Conclusion.</h3>
<p>Web apps never going to feel native. You can call it “React native” but it will not make code more native. You can call it “Electron” but it will not make app size smaller and efficient.</p>
<p><a href="http://cocoaswitch.com/downloads/GitHub-Desktop.zip">Native GitHub Desktop app is no longer available but you can download my copy.</a> I still use it to this day and I will continue until it stopps working.</p>
Mon, 22 Jan 2018 22:20:00 +0000http://cocoaswitch.com/2018/01/22/github-electron/
http://cocoaswitch.com/2018/01/22/github-electron/Auto Layout Scroll View with footer.<p><img src="http://cocoaswitch.com/images/scroll-view.png" alt="iOS simulator screenshot with blue content area and yellow footer" /></p>
<p>The goal of this Auto Layout exercise is to build scroll view with dynamic content height and footer. There’s 2 challenges here.</p>
<ol>
<li>Sticking footer to the bottom even when there’s very little content.</li>
<li>Allowing scroll view to scroll even though content height is unknown.</li>
</ol>
<p>First, read <a href="https://www.natashatherobot.com/ios-autolayout-scrollview/">“iOS: How To Make AutoLayout Work On A ScrollView” from Natasha</a> as it’s very practical and saved me many hours.</p>
<p>The fastest and easiest way to get started is Storyboard and Interface Builder. <a href="https://github.com/borisyurkevich/Scroll-View-with-Footer">Download sample project from GitHub.</a></p>
<ol>
<li>Add Scroll View to your root view and add pin it with 4 constraints. Your root view should have only 1 child which is the scroll view.</li>
<li>Create new “container” view and add it to the scroll view. Scroll view can have only one child view. This was mentioned by Natasha and I always follow this rule since, I lost many hours when I didn’t know about this.</li>
<li>Add constraint for container view width to be equal with root view width.</li>
<li>Add footer view and pin it to the bottom.</li>
<li>Scroll view can’t function when content height is unknown. Add height constraint outlet. In this example for my content I have single label, I don’t set container view height because it will change depending on label height. I pinned label to its superview. Make sure your Storyboard file doesn’t have error messages and layout conflicts resolved.</li>
</ol>
<p><img src="http://cocoaswitch.com/images/height-constraint.png" alt="Interface Builder with footer sticking to the top" /></p>
<p>At this point you should get something like this in your Interface Builder. We still have some work to do. Open view controller and add following code.</p>
<figure class="highlight"><pre><code class="language-swift" data-lang="swift"><span class="n">labelHeightConstraint</span><span class="o">.</span><span class="n">constant</span> <span class="o">=</span> <span class="n">view</span><span class="o">.</span><span class="n">bounds</span><span class="o">.</span><span class="n">height</span> <span class="o">-</span> <span class="n">footerView</span><span class="o">.</span><span class="n">bounds</span><span class="o">.</span><span class="n">height</span></code></pre></figure>
<p>So far I have no content and we had to increase label heigh so footer sticks to the bottom as design required. If I set text for the label it will truncate which I don’t want. I had to disable this constraint and allow scrolling.</p>
<figure class="highlight"><pre><code class="language-swift" data-lang="swift"><span class="n">labelHeightConstraint</span><span class="o">.</span><span class="n">isActive</span> <span class="o">=</span> <span class="kc">false</span></code></pre></figure>
<p><img src="http://cocoaswitch.com/images/scrollable-content.png" alt="2 screens with text taking all the space." /></p>
<h3 id="iphone-x">iPhone X</h3>
<p>I thought I was done but when I run the code I realised it was broken on new iPhone X. Here’s code snippet that helped me.</p>
<figure class="highlight"><pre><code class="language-swift" data-lang="swift"><span class="k">override</span> <span class="kd">func</span> <span class="nf">viewDidAppear</span><span class="p">(</span><span class="n">_</span> <span class="nv">animated</span><span class="p">:</span> <span class="kt">Bool</span><span class="p">)</span> <span class="p">{</span>
<span class="k">super</span><span class="o">.</span><span class="nf">viewDidAppear</span><span class="p">(</span><span class="n">animated</span><span class="p">)</span>
<span class="n">labelHeightConstraint</span><span class="o">.</span><span class="n">constant</span> <span class="o">=</span> <span class="p">(</span><span class="n">view</span><span class="o">.</span><span class="n">frame</span><span class="o">.</span><span class="n">height</span> <span class="o">-</span> <span class="n">view</span><span class="o">.</span><span class="n">safeAreaInsets</span><span class="o">.</span><span class="n">top</span><span class="p">)</span> <span class="o">-</span> <span class="n">footerView</span><span class="o">.</span><span class="n">bounds</span><span class="o">.</span><span class="n">height</span>
<span class="p">}</span></code></pre></figure>
<p>The key is <code class="highlighter-rouge">viewDidAppear</code> because safe area insets equal to zero in <code class="highlighter-rouge">viewDidLoad.</code> I also had to disable landscape layout.</p>
<p>I noticed that iPhone X screen is very tall so all my text was visible and footer was in the middle of the screen, I had to activate constraint again. Only disable height constraint when you have many pages of content, iPhone X can fit surprising amount of information.</p>
<p><img src="http://cocoaswitch.com/images/iPhone-X-layout.png" alt="iPhone X screenshot" /></p>
Wed, 01 Nov 2017 12:01:00 +0000http://cocoaswitch.com/2017/11/01/auto-layout-footer/
http://cocoaswitch.com/2017/11/01/auto-layout-footer/State of Mobile Gaming.<p><img src="http://cocoaswitch.com/images/iPhone-vs-3DS.jpg" alt="Black iPhone and Nintendo 3DS on the white desk." title="iPhone and Nintendo 3DS" /></p>
<p>I carry my <a href="https://www.amazon.co.uk/gp/product/B00S84TXLM/ref=as_li_tl?ie=UTF8&amp;camp=1634&amp;creative=6738&amp;creativeASIN=B00S84TXLM&amp;linkCode=as2&amp;tag=courageousi0c-21&amp;linkId=a4639dc567f3eb97c7dd9a1965f39737">Nintendo 3DS</a> almost every day. Completing one game after another, surprised how good and memorable Nintendo games are. I try to play on iPhone sometimes but it always disappointment, ether game requires internet connection or it is too plain, too simple, without a story and characters, repetitive. Generic sense I’m getting from mobile studios is maximising revenue from each player with tracking, dirty psychological tricks, micro transactions and cool-off timers. Sadly neither developers or consumers care about gameplay and story aspects. Yes, there’s a <a href="https://itunes.apple.com/gb/app/monument-valley/id728293409?mt=8&amp;uo=4&amp;at=1010l4GJ">Monument Valley</a> but the game is short and very simple, it’s not comparable to <a href="https://www.amazon.co.uk/gp/product/B0753JH6VV/ref=as_li_tl?ie=UTF8&amp;camp=1634&amp;creative=6738&amp;creativeASIN=B0753JH6VV&amp;linkCode=as2&amp;tag=courageousi0c-21&amp;linkId=df9564e109a5972d4310934e96838ee3">Super Mario 3D Land (recently discounted)</a> or <a href="https://www.amazon.co.uk/gp/product/B01G8H8AWI/ref=as_li_tl?ie=UTF8&amp;camp=1634&amp;creative=6738&amp;creativeASIN=B01G8H8AWI&amp;linkCode=as2&amp;tag=courageousi0c-21&amp;linkId=1601d0e3f90870fc84a0bb752e7286c1">Legend of Zelda.</a></p>
<p>Is it because price raise to the bottom or short playing sessions or lack of physical controls included with every device, or, more likely, combination of all? I wonder can this market be sustainable in a long run? Classic video game industry always relied on creating something special, experience which is art form more immersive than TV and movies. To play best games you have to own dedicated console. For a long time you had to own MP3 player and photo and video camera separately but now all this markets cannibalised by iPhone. Gaming industry is still separate. Hardware is not longer an issue, even last year iPhone 7 are more powerful than Nintendo Switch, has much better screen as well. So why no one makes exclusive iOS games with big budget and controller support? I am not talking about ports or multi platform games. Nowadays tools like Unity and Unreal makes it easy to deploy game on each platform but this approach doesn’t take advantage of unique hardware aspects like 3D Touch and Haptic Feedback. Or why there’s no iPad exclusive games which take advantage of a larger screen? There’s ports but that’s all.</p>
<p>Nintendo is very smart by releasing <a href="https://www.amazon.co.uk/gp/product/B06XYSLG5F/ref=as_li_tl?ie=UTF8&amp;camp=1634&amp;creative=6738&amp;creativeASIN=B06XYSLG5F&amp;linkCode=as2&amp;tag=courageousi0c-21&amp;linkId=77c5a965623a2dc86684cf7d5e19151a">Switch</a> which can be used in commute and games which can be played together with all necessary controllers included, games which use consoles unique features (HD Rumble). It’s a natural evolution for 3DS. I am very happy about progress they made and have a lot of hope that people who experienced game on Nintendo console will never look towards Rovio, King again.</p>
Mon, 30 Oct 2017 11:53:00 +0000http://cocoaswitch.com/2017/10/30/state-of-mobile-gaming/
http://cocoaswitch.com/2017/10/30/state-of-mobile-gaming/Apps Should Work Offline, with Visible Status Bar.<p>We have not expensive data plan, and I disable mobile data for most of my apps. I have a problem with “Internet Wall” appearing in even one of the best apps like Carrot Weather (<a href="https://itunes.apple.com/gb/app/carrot-weather/id961390574?mt=8&amp;uo=4&amp;at=1010l4GJ">iOS</a> or <a href="https://itunes.apple.com/gb/app/carrot-weather-talking-forecast-robot/id993487541?mt=12&amp;uo=4&amp;at=1010l4GJ">Mac</a>) or Super Mario Run <a href="https://itunes.apple.com/gb/app/super-mario-run/id1145275343?mt=8&amp;uo=4&amp;at=1010l4GJ">(iOS). </a>Just today I opened Carrot Weather while on vacation to have white screen of nothing telling me there’s connection problem.</p>
<p><img src="http://cocoaswitch.com/images/weather-vs-carrot.jpg" alt="Apple Wather on left and Carrot on the right. Apple app has visible status bar and shows all data even though both apps don't have immidiate internet acces." title="Apple Weather and Carrot Weather while offline" /></p>
<p>And not only I can’t check the weather but I can’t see time, battery level and most important, connection status. I guess developer decided their custom made artistic interface is more important than Status Bar.</p>
<p>I use Carrot Weather for their great Apple Watch app. On iPhone I prefer Weather but I launch Carrot from time to time. Recently Carrot Weather had big 2.0 update with new UI. I am sure developer very proud of all extra features and personality added into Carrot Weather but I don’t care. I even turned off all “fun” features. And this is why I continue to use Weather, it shows me the weather in any conditions, especially when I am trying to manage my data plan usage. It also shows me Status Bar at any screen.</p>
<p>Recently we shipped goEvo <a href="https://itunes.apple.com/gb/app/goevo/id1204199991?mt=8&amp;uo=4&amp;at=1010l4GJ">(iOS),</a> app with daily planner for meals and exercises, and function to log emotional state and even have 2 way conversations with virtual coach. I am proud that all of its features work without internet connection.</p>
<p>Every non-web software developer should understand that application they develop should not require immediate internet connection. It’s not hard to do, and it’s good for performance and energy efficiency. Otherwise what’s point of making native app? If Carrot Weather can’t do data persistence, they should’ve focus their development building web application instead.</p>
Sat, 16 Sep 2017 18:28:54 +0000http://cocoaswitch.com/2017/09/16/offline-first/
http://cocoaswitch.com/2017/09/16/offline-first/Raise of Smart Consumer.<p>In a light of approaching Safari release with <a href="https://webkit.org/blog/7675/intelligent-tracking-prevention/">Intelligent Tracking Prevention</a> and <a href="http://www.adweek.com/digital/qa-newyorker-com-editor-michael-luo-talks-readership-revenue-and-the-mooch/">ad industry reacting with public letter to Apple,</a> I am seeking view in which industry can change while technology is used in favour of people privacy.</p>
<h3 id="classic-ads">Classic Ads.</h3>
<p>As example, after Soviet Union fall there was new market opportunities for western companies. Russians were ready to buy new products and their choices were determined by ads. Richest and biggest companies captured the market. TV ads worked — some products has been called by brand name, like some people call each MP3 player as “iPod” — to this day most Russian people call nappies as “pampers”. Advertising is a big market driver and necessary part of any successful product. It worked well without any data collection or tracking.</p>
<h3 id="track-convert-repeat">Track, Convert, Repeat.</h3>
<p>World we live today is not as simple. “Big Data” became
annoying buzz word, most of tech used to collect and analyse people’s behaviour. Company getting bigger. There’s new loyalty schemas with cards like Nectar Card and Tesco Club Card is pure not hidden tracking in which customers acquired by small portion of a sale, about 0.1% to my rough estimates earned in points which on top of all can expire.</p>
<p>There’s web tracking too, with cross domain cookies identifiers and whole industry of companies which entire focus on maximising conversions by any means. Facebook ads generate thousands of dollars every second. Advertisers exploiting VR and AR as well, you can get Google cardboard VR just as part of movie promotion walking on streets of London. Although advertising industry arguing no wrong doing to as the only “serve consumer interests”, we know they only serve only their own interest.</p>
<blockquote>
<p><a href="https://twitter.com/marcoarment/status/908764314231853056">@marcoarment:</a> If the ad industry is complaining, you know Apple made the right decisions for us. Thanks, Safari team!</p>
</blockquote>
<p>Those tactics has only single goal — maximising profits by using technology while influencing peoples choices. Those companies want to use same advertisement models with invading new areas of our personal lives. Their lack of ability to change means we will find a way around their primitive “track, convert, repeat” model. Ad industry complaining about decreasing profits but instead of changing they only make thing worse by using even more ads often through mediation networks, inserting video ads, fighting content blockers.</p>
<h3 id="trust-and-research-as-primary-buying-factor">Trust and Research as Primary Buying Factor.</h3>
<p>My wife wanted to get me new slippers. I saw massive ad campaign all around London Tube and on the web. I knew the brand she’s going for. 5 minutes of research gave me everything I need to argue against the purchase. I found one youtuber who purchased this slippers 1 year ago and reflected on his purchase recently. Slippers broke soon because cheap materials and customer support was not up to the high price. Company invested all the profits into advertisement and almost none in the product quality and support.</p>
<p>Nothing stops websites to continue serve ads, but they will have to do it with respect to readers privacy, without profiling and identifying. Facebook, Amazon and Google continue to track us on their own. Not much can be done, as they deploy code from their own domains, except maybe abandoning services altogether, hence switching from Google to <a href="https://duckduckgo.com/">DuckDuckGo.</a> However, we should make harder identify us across. Videos we watch on YouTube shouldn’t influence recommend products from Amazon, click on a search result shouldn’t make us an ad target. Safari already doing great job while blocking third party cookies by default and for 2 years supports innovative efficient and private ad blockers like <a href="https://itunes.apple.com/gb/app/1blocker-better-than-just-an-adblock/id1107421413?mt=12&amp;uo=4&amp;at=1010l4GJ">1Blocker for Mac</a> <a href="https://itunes.apple.com/gb/app/1blocker/id1025729002?mt=8&amp;uo=4&amp;at=1010l4GJ">and iOS.</a></p>
<p>There’s individuals like Jhon Grubber who started first using sponsored posts in RSS, websites and podcasts with exclusive subscription model, podcasters which experience product while sponsoring it ensuring basic curation. There’s Marco Arment created his <a href="https://overcast.fm/account/buy_ad">own advertising network in Overcast.</a> This innovation is a new way for products to rich their customers and they fund independent content creators. This examples show there’s new ways for advertisement to exist without breaking trust.</p>
<p>I believe our economy and society are better off when individuals make conscious choices about products they purchase. Choice influenced not with massive surveillance and propaganda but trust and research. I want to leave in a world where companies compete not by sole marketing but with design, quality, customer service and environment impact. Looking into future, I want to end this by quoting a <a href="https://forums.macrumors.com/posts/25034304">reaction comment from MacRumors.</a></p>
<blockquote>
<p>I want to be respected as a consumer, able to make my own choices about my needs, seek them out on my own and be helped by knowledgeable people when I want information on what to purchase.</p>
</blockquote>
Fri, 15 Sep 2017 22:48:00 +0000http://cocoaswitch.com/2017/09/15/raise-of-smart-consumer/
http://cocoaswitch.com/2017/09/15/raise-of-smart-consumer/SOLID Photo Gallery in Swift 4<p>Goal of this exercise is to improve my code design. I am hearing a lot about SOLID design principles and “uncle Bob”, so I decided to understand its ideas. This exercise is my attempt to implement this ideas on practice in simple and modern Swift application. Although SOLID principles explained with C++ examples, its good Object Oriented Design principles can be applied to Swift.</p>
<p>As mentioned by Robert C. Martin before, this principles is only recommendations and is not a law. Sometimes it is better to violate this good design principles but only when necessary. I also have to mentions that this is only mine interpretation, I can be wrong. Please <a href="mailto:boris.yurkevich@gmail.com">write to me</a> if you have any feedback.</p>
<h3 id="goal">Goal.</h3>
<p>Applications accesses Flickr API and displays image gallery, displays meta data for each image.</p>
<p>To satisfy acceptance criteria we need to display collection of photos, be able to show all metadata for each photo and perform actions on each photo. I designed 3 screens and to implement them we will need following:</p>
<ol>
<li>PhotosCollectionViewController</li>
<li>PhotoViewController</li>
<li>MetadataViewController</li>
</ol>
<p>Let’s assume, later we will need to add sorting feature for the next version of application.</p>
<h3 id="naive-design">Naive Design.</h3>
<p>For getting photos from Flickr singe service class is created. This class sends data to <code class="highlighter-rouge">PhotosCollectionViewController.</code></p>
<p>For the UI we use single Storyboard file.</p>
<h3 id="good-model-design">Good Model Design.</h3>
<p>What makes design good or bad? How we can judge it? There’s 3 warnings signs in which we can evaluate design quality. This was described in <a href="http://docs.google.com/a/cleancoder.com/viewer?a=v&amp;pid=explorer&amp;chrome=true&amp;srcid=0BwhCYaYDn8EgMjdlMWIzNGUtZTQ0NC00ZjQ5LTkwYzQtZjRhMDRlNTQ3ZGMz&amp;hl=en">The Dependency Inversion Principle.</a></p>
<ol>
<li>Code that hard to change.</li>
<li>Every change breaks code in unexpected place.</li>
<li>Code can’t be reused.</li>
</ol>
<p>In order to create reusable design we need to think what parts of application can be changed in the future and what kind of change we should be ready for. We can improve naive design in many ways. Let’s focus on model design and UI design separately and start with model.</p>
<p>Lets say everything user can’t see is part of the model. First decision that I made is to write separate <code class="highlighter-rouge">NetworkService</code> protocol. Swift protocol itself can have only method definition, not implementation. I extended <code class="highlighter-rouge">NetworkService</code> and chose to use Apple <code class="highlighter-rouge">URLSession</code> to request data with status and optional error object.</p>
<p>Let’s imagine this source code need to be used in another project which relies on third party Alamofire library. In this case, developer need to replace <code class="highlighter-rouge">NetworkService </code> extension. If developer keeps same method definition, good news, <code class="highlighter-rouge">PhotosCollectionViewController</code> will not need to change. Job well done.</p>
<p>Another struct is required to specify request path, I called it <code class="highlighter-rouge">FlickrService.</code> It has endpoint path and data type parameter. I also created <code class="highlighter-rouge">FlickrDataModel</code> struct. In this struct I added method to parse data into Flickr model taking advantage of Swift 4 Standard Library with <code class="highlighter-rouge">JSONDecoder.</code> I chose to use nested Decodable Structs to mirror data model from an Flickr endpoint.</p>
<p>Unlike naive model, in this design I separated Flickr related logic and networking logic into separate abstractions. This enables easy code reuse, and also allows easier refactoring of one part of application without breaking other part.</p>
<p><code class="highlighter-rouge">PhotosCollectionViewController</code> communicates with lower level networking module through higher level <code class="highlighter-rouge">FlickrService</code> class which conforms to abstract <code class="highlighter-rouge">NetworkService</code> protocol and can perform request. I believe this is good example of The Dependency Inversion Principle. Higher level abstractions doesn’t depend on lower level implementation.</p>
<h3 id="the-rest-of-application">The rest of application.</h3>
<p>So far I spend most of my attention into <code class="highlighter-rouge">PhotosCollectionViewController.</code> There’s 2 other goals:</p>
<ol>
<li>View controller for displaying photo in full screen and performing some actions: sharing photo, opening original Flickr web page.</li>
<li>Displaying metadata in full screen.</li>
</ol>
<p>This can be done with 2 or 1 view controller. Whenever <code class="highlighter-rouge">Photo</code> metadata changes, this view controllers and UI would need to change as well. I chose to split metadata viewer and full screen photo view into 2 different view controllers. I created 2 Storyboard files and took advantage of Storyboard References. That’s better than using single Storyboard file, now engineers can work simultaneously. Storyboard itself allows us to separate view logic from business logic. This allows changes in UI design and layout without need to change view controller code.</p>
<p>I assume one can say that this design violates The Dependency Inversion Principle — changes in <code class="highlighter-rouge">Photo</code> object model, replacement it with another object, or adding new data source types, require changes in UI and controllers. For this simple exercise I chose to keep UI static. We can’t be ready to every possible change and need to think carefully what areas of application can change. Because this is photo browsing app I keep core UI functionality together. I believe it is important to understand purpose of the application, in our case it is displaying photos with meta data. We should design our code to be ready for additional features and changes in implementation. In case when core purpose changes, it is better to start from scratch.</p>
<h3 id="separating-user-interface">Separating User Interface.</h3>
<p>Well done, version one finished. I am satisfied with design and core requirements. What if we would like to implement sort function? It can be done inside the same collection view controller. But this would be bad design and eventually lead to well known Massive View Controller problem. What if we want to reuse sorting module or change its implementation? The Dependency Inversion Principle states that UI should not be connected with business logic directly, UI should communicate through higher level abstractions. Ideally, sorting feature should have its own MVC.</p>
<p>To fix this, we can create <code class="highlighter-rouge">SortOptions</code> struct which defines <code class="highlighter-rouge">SortType</code> enum and its order. It also contains text to be displayed in UI. We use <code class="highlighter-rouge">UISegmentedControl</code>, I consider it as low lever class which should know nothing about business logic. We extend this control with <code class="highlighter-rouge">SortControl</code>extension which would take <code class="highlighter-rouge">SortOptions</code> and would configure <code class="highlighter-rouge">UISegmentedControl.</code> to display appropriate number of segments with appropriate labels.</p>
<p>I included <code class="highlighter-rouge">SortOptions</code> struct into <code class="highlighter-rouge">PhotosCollectionViewController</code> which is fine but I didn’t connect <code class="highlighter-rouge">UISegmentedControl</code> directly to <code class="highlighter-rouge">PhotosCollectionViewController</code> like it’s done in naive model. Instead, I created <code class="highlighter-rouge">SortViewController</code> and took advantage of Cocoa Touch Container View. This allows me to move <code class="highlighter-rouge">UISegmentedControl</code> into separate Storyboard file, meaning if UI changes, <code class="highlighter-rouge">PhotosCollectionViewController</code> will work the same, only <code class="highlighter-rouge">SortViewController</code> would require change. As long as our collection view conforms to <code class="highlighter-rouge">SortableCollection</code> protocol and communicates through <code class="highlighter-rouge">SortViewController</code>, design does not violates The Dependency Inversion Principle.</p>
<h3 id="bibliography">Bibliography.</h3>
<ul>
<li><a href="https://en.wikipedia.org/wiki/SOLID_(object-oriented_design)">SOLID (object-oriented design)</a></li>
<li><a href="http://butunclebob.com/ArticleS.UncleBob.PrinciplesOfOod">Principles Of OOD, Robert C. Martin (Uncle BOB)</a></li>
<li><a href="https://github.com/ochococo/OOD-Principles-In-Swift">Swift implementation for The Principles of OOD based on Uncle Bob articles.</a></li>
</ul>
<h3 id="xcode-project">Xcode project.</h3>
<p><a href="https://github.com/borisyurkevich/photos">Project is available on GitHub.</a></p>
Wed, 30 Aug 2017 03:59:00 +0000http://cocoaswitch.com/2017/08/30/solid-photo-gallery-in-swift-4/
http://cocoaswitch.com/2017/08/30/solid-photo-gallery-in-swift-4/Let Safari Be Different. Case Against Favicons.<p>Idea of why Safari team should change its original design and add favicons getting big traction among Daring Fireball users. <a href="https://daringfireball.net/2017/08/safari_should_display_favicons_in_its_tabs">Jhon Gruber wrote</a> that most of his readers think that Safari team should include favicons in its browser. I have different opinion.</p>
<p>Safari should stay as it is, tabs should not have colourful favicons. Option in Preferences is not a good solution neither. Safari design should not follow common pattern where each browser has favicons in its tabs. It doesn’t have tabs on the top and it shouldn’t have favicons either. Here’s why.</p>
<p>I believe Safari designed to be minimal for multiple good reasons. It’s not hard to include them from technical perspective, this is clear design choice.</p>
<h3 id="why-safari-worse-with-favicons">Why Safari worse with favicons.</h3>
<p>Let’s think why Apple designers decided not to include favicons into Safari. I can speculate on many reasons. First that’s coming into my mind is content. Apple wants us to focus on the material. Colourful icons row is another distraction which gets in our way when we reading article or navigating the page. Aesthetics important here. Safari looks nicer, favicons small and noisy. Favicons look cheap. Safari looks professional, it makes website stand out, it doesn’t compete with its content.</p>
<p>Two main arguments from favicon supporters are:</p>
<ol>
<li>Favicons help to identify tab quickly, find the right tab without need to click or read.</li>
<li>Favicons allow to fit more recognisable tabs in a single window.</li>
</ol>
<p>I could agree with first argument, it is harder to find the right tab in Safari. But only when people use Safari like they would use Chrome. I believe Safari was created with different workflow in mind.</p>
<p>Web browser is main research tool for me. My goal finding information and returning into apps. My work starts with new Safari window and search query. Then reading and opening new tabs. When need to go back, not trying to use mouse — using hot key <code class="highlighter-rouge">command + shift + {</code> to go back, and <code class="highlighter-rouge">command + shift + }</code> to go forward. It feels faster than trying to find the right tab, I can see entire pages. I also use <code class="highlighter-rouge">command + 1, 2, 3…</code> to open first, second and third tabs and so on.</p>
<p>At some point I need to find particular tab and that’s when I use View &gt; Show All Tabs, another muscle memory combination: <code class="highlighter-rouge">command + shift + \</code>. It also works well with iPad and iPhone. Each tab presented as small preview.</p>
<p><img src="http://cocoaswitch.com/images/show-all-tabs.png" alt="Safari window with 6 tabs visible as small page previews." title="Safari Show All Tabs" /></p>
<p>Safari tab preview is better representation of web pages and its content, from here we can find the right page and close pages we don’t need.</p>
<p>Okay, let’s imagine I had Chrome, then favicons would not help me, some of tabs are from the same domain, which means I have to use keyboard anyway. When you need to click, you need to read title and Safari even has more space to fit it.</p>
<p>The second argument with many tabs in single window is also not a problem. I open new Safari window whenever I have new task at a hand and “Show All Tabs” can help too. Normally I have more than 5 Safari windows open, and this number increases over time. Opening multiple windows allows me to separate my tasks. I close entire windows with one click after task is done.</p>
<p>From what I saw, some Chrome users maximise browser window, this is not how I use Safari, I have many narrow windows so I can see more than one page at a time and hide sidebar distractions behind the scroll area. This also means that I only have tabs I need for a given task.</p>
<h3 id="option-in-preferences-is-bad-solution">Option in Preferences is bad solution.</h3>
<p>Now answering your possible question, why don’t add option to the Preferences. If Apple designers would ever decide to add the option, it will be enabled by default. Most of people don’t have time and energy to go through settings and fiddle with checkboxes — nerds love it, most of the people don’t. App should be configured in a right way from the start. Hence if Apple designers think that favicons is the right way, they would ship new version with favicons and the will be no option to disable them. Because when you do need to open Preferences, less checkboxes means faster navigation, so there’s no need to search for a toggle.</p>
<h3 id="what-if-they-do-it">What if they do it.</h3>
<p>I realise that how I use web browser might be not the right way for some people. I see more people use web applications instead of native apps and keep only one maximised window. I spend more time in apps and I use Dock more than I use tab picker. Safari is just another app for me and I don’t do everything there. For math or weather queries Spotlight feels better, I don’t listen to music on YouTube, I use Dictionary app for looking up a definition, I use Xcode documentation window and so on… Safari is just another app for me.</p>
<p>People can change, designers change their opinion. It can happen. It will make me feel sad. Not as much sad as <a href="https://arstechnica.com/gadgets/2003/04/finder/">spacial Finder</a> though.</p>
Tue, 15 Aug 2017 23:23:00 +0000http://cocoaswitch.com/2017/08/15/let-safari-be-different/
http://cocoaswitch.com/2017/08/15/let-safari-be-different/