Under The BridgeUnder The Bridge

Musings
App Store Aluminium Anniversary Affiliate Apocalypse

There’s an excellent series tagged App Store at 10 over at MacStories — all worth reading for reminiscing over the laughter, tears and rage of this last decade, but particularly these pieces:

But there is no laughter, just tears and rage, at today’s controversy, which is certainly starting off the decade with a BANG!

Apple Kills the App Store Affiliate Program, and I Have No Idea What We Are Going to Do.

Moments ago, Apple announced that they’re killing the affiliate program, citing the improved discovery offered by the new App Store. (Music, books, movies, and TV remain.) It’s hard to read this in any other way than “We went from seeing a microscopic amount of value in third party editorial to, we now see no value.” I genuinely have no idea what TouchArcade is going to do. Through thick and thin, and every curveball the industry threw at us, we always had App Store affiliate revenue- Which makes a lot of sense as we drive a ton of purchases for Apple. I don’t know how the takeaway from this move can be seen as anything other than Apple extending a massive middle finger to sites like TouchArcade, AppShopper, and many others who have spent the last decade evangelizing the App Store and iOS gaming- Particularly on the same day they announced record breaking earnings of $53.3 billion and a net quarterly profit of $11.5 billion.

I’m just beside myself.

I don’t know what we’re going to do.

I really didn’t think it would be Apple that eventually kills TouchArcade.

I guess now is a great time to link the TouchArcade Patreon again.

I’m just going to turn my phone off and go sit outside.

Yowza. Mind you, it’s not like this couldn’t have been seen coming…

Apple slashes affiliate commission rate on apps from 7 to 2.5%

… but the finality of destroying the affiliate reference business model is a bit crushing. Well, that’s one less avenue of monetization for your curation sites. Not that we were making anything particularly significant off our occasional app reviews, but not particularly significant still is a greater contribution than nothing. Ah well.

If you want to read more, although “tears and rage” pretty much covers it really, as always @mjtsai has a great roundup: Apple Removes Apps From Their Affiliate Program.

However. that’s not the only controversy afflicting the App Store lately; you might recall the WWDC-time excitement around the review guidelines now allowing trials:

Non-subscription apps may offer a free time-based trial period before presenting a full unlock option by setting up a Non-Consumable IAP item at Price Tier 0 that follows the naming convention: “XX-day Trial.” Prior to the start of the trial, your app must clearly identify its duration, the content or services that will no longer be accessible when the trial ends, and any downstream charges the user would need to pay for full functionality. Learn more about managing content access and the duration of the trial period using Receipts and Device Check

Mac App Store Sandboxing, IAP Trials, Multiplatform Services

Awesomeness, right? That’ll satisfy The Developers Union and sympathizers, riiiiight? Errrr, not so much…

Ersatz Free Trials

Every aspect of the solution is bolted on to a system which was not designed for, yet is somewhat admirably being used to simulate real support for free trials. Let me elaborate by listing several shortcomings and how they affect both users and developers in significant ways. Just off the top of my head …

  • Paid apps are listed as free, even though payment is required to unlock core functionality…
  • Bulk purchase programs are unavailable…
  • Family sharing is unavailable…
  • Not applicable to all app types…
  • Apps are ranked and featured in the wrong charts…
  • Transaction mechanics are pushed onto developers…
  • Free trials cannot be easily reset…
  • Apps cannot be made to “just work” out of the box…

There was also some grumbling at the time about the affiliate commission being lost on IAP purchases — well, that particular objection has been dealt with avec finalité, yes. Be careful what you complain about, indeed!

While the vast majority of commentators are satisfied to assume incompetence and/or malice for the lack of conventional free trials, there is a counterpoint worth considering:

Free Trials from Apple’s Perspective

I think Apple have probably thought long and hard about it, and concluded that the options they have introduced are actually better than the free trials developer’s are requesting…

… For me personally — and not a reflection of the opinions of others in my company — Apple are doing this right. There are perhaps a few rough edges — for example, they could word the free In-App Purchase option better — but their philosophy of making it completely clear to customers what they are getting, and when they pay, is on the money. It is not a case of Apple being vindictive. I guarantee they have thought about this problem deeply.

Well, we’re not sure that’s a compelling argument, but we can see that Apple would consider the current state good enough compared to resolving all these issues, definitely. So the chances that anything’s going to change more soon are probably slim indeed. So, to make the best of things as they are, here’s a library for you from BlackPixel:

Announcing IAPKit

Last week at WWDC 2018 Apple announced they are officially supporting free trials for apps via a Non-Consumable IAP item. Inspired by The Omni Group, this is exactly the approach Black Pixel took last year when releasing Kaleidoscope 2 and Pixelboard.

Last Summer when working on these two apps, we decided to create a shared framework to use internally that would wrap the iOS SDK APIs necessary to provide a smooth consistent experience with starting a free trial and upgrading to full app versions. Today we are open sourcing the fruit of this labor as IAPKit.

IAPKit provides an easy way for developers to connect to their own apps’ IAP products and display them in a simple UI that works with Auto Layout, Safe Area Insets, and iPad split-screen modes. We hope the Apple development community finds it as useful as we have…

Or, you could always just not bother with that, and go ahead and trial without it:

Trialware Makes Its Triumphant Return

To reliably answer the question of whether Apple is now allowing all-or-none trialware apps, I wanted to be very up-front about the changes with the App Store reviewer. To that end I wrote this directly into the reviewer’s notes:

We are moving to a “trialware” biz model. The user has 14 days to evaluate the app. After that, they’ll be asked to pay the IAP price to continue using it.
Surprisingly after about a day, the app was approved! Wow!

… To sum up:

  • Apple is now apparently allowing “all-or-none” trialware apps
  • You don’t have to use wonky $0 IAPs and DeviceCheck to make it work

So there you go — we’ll probably try that our next attempt at monetization and see if it continues to work!

Trialling aside, it’s pretty clear that Apple wants everybody to move to a subscription model. That has its upsides and downsides; again, @mjtsai keeps a great roundup updated at Productivity Apps and Subscription Pricing.

And one more tidbit to finish off with on a more amusing note: You know how Apple’s gift cards get auto-scanned? Ever wanted to do that with your own App Store promo codes? Well, here’s how!

Cracking the code behind Apple’s App Store promo card design

Apple’s App Store gift cards have a special trick: you can simply hold one up to your iPhone or Mac’s camera and it’ll automatically scan in the code and redeem the card for you. As developers, we thought it’d be cool to print some of our own promo code cards to give away at events, so we tried to create our own scannable cards. Turns out, there’s more to it than meets the eye…

Homemade Marzipan Recipes: UIKit on macOS

Well, we are definitely going to accept credulously everything Mark Gurman tells us from now on, because he called it six months early: Yes, UIKit is coming to macOS, and it is, in fact, code named “Marzipan”— top marks! And there’s been a wide range of reactions to that, the best collected (as usual!) over at Michael Tsai’s blog:

Apple Announces Marzipan for 2019

One particularly notable contrarian voice can be found at Apple Didn’t Kill AppKit, Millenials Did:

But here’s the painful part: the techniques to do these things are already available, well-known, and very few people are using them. There are still lots of iPhone-only apps, or apps that make poor use of the iPad and just let their table views stretch out to infinity. And as for tvOS… it already runs UIKit. Your scenes are actual damn UIViewControllers. And yet look at the dearth of TV apps. We’ve had Marzipan on the TV for years and almost nobody uses it…

Well yes, that’s a good argument, and yes, it’s not all that hard to make a UIKit+AppKit app now if you want to, 

To be clear, the enemy is not other Apple-platform developers. The enemy is the use of bloated, cross-platform, phone-it-in frameworks. “Write once, run everywhere” has been promised and come up wanting for decades: Java applications and applets, Adobe AIR, Xamarin, PhoneGap, and so on. One semi-success story of recent years are the various approaches like Electron and Chromium, which effectively embed an entire instance of the Chrome web browser in an app wrapper. This approach is used by such Mac apps as Slack, Discord, and Spotify.

It is also a goddamned scourge, and straight up an abuse of the end-user’s equipment.

And yes, yes, that too.

However, none of these objections are particularly subtle, and yet Apple’s put a couple years so far into this and is doubling down. All in order to save, spitballing here, maybe 15-25% of any well-architected app would need to be different? Well, that makes people figure, also quite reasonably, that the real agenda here is to support the ARM Macs That Everyone Expects Sooner Or Later:

Marzipan as a Path to ARM Based Macs

What if MacOS on ARM only ran these new UIKit apps?

That’s a scary thought for this MacOS developer.

But then again, we already have this and it’s called iOS on the iPad. And maybe, just maybe, and remember these are half baked thoughts, but maybe Apple is wondering if some Pro users might be better served by MacOS Touch 1.0 running on ARM.

An interesting perspective. But, as announced, Apple is using it themselves, so we know that they evaluated the cross-platform strategy ably ranted on behalf of above, and they decided it made more sense to engineer this Grand UIKit Emulation Layer … well, for some reason. Be fascinating to find out what next year or two!

In the meantime, what’s shipping now is surprisingly functional, people are finding:

and although it’s generally agreed that you shouldn’t pay too much attention to the current implementation details, if you want to have some quick fun:

marzipanify

marzipanify is an unsupported commandline tool to take an existing iOS Simulator binary (with minimum deployment target of iOS 12.0) and statically convert it and its embedded libraries & frameworks to run on macOS 10.14’s UIKit runtime (Marzipan)…

MarzipanTool  — Port an iOS app to macOS 10.14 in 5 minutes

Here’s how to port your iOS apps to macOS 10.14 Beta using Apple’s iOSMac/Marzipan framework. A “Hello World” iOS app can become a macOS app in less than 5 minutes. (I timed it.).

Marzipan Platter

At WWDC 2018 Apple announced that they are working on a multi-year strategy to make it easier to port UIKit applications to the Mac. While some first-party applications such as the Home & News app are going to use this API in macOS 10.14, third-party developers won’t have official access for another year. As a result, I made this project to help tinkerers/other impatient people get a taste of what’s to come when Apple gives everyone access to Marzipan next year…

Marzipan – UIKit on macOS

For this post I prepared a very simple app — that allows you to fetch top stories from Hacker News and present them in a simple UITableView. This app is simple as far as functionality is concerned but includes some standard plumbing and networking to see whether common libraries can be used on macOS. The good news is that this is indeed possible and we can use libraries like Alamofire, Swinject and others without any special effort!

So, it doesn’t take too much to figure that Marzipan is going to be extremely important in the not so distant future … get started today!

But please, don’t do what this guy did, even tongue in cheek and all…

Marzipants

Here’s a proof-of-concept that React Native can work* (*lol) under Marzipan.

But, like, it’s proof that we don’t need Electron, right? 💪

… It’s surprising how well it’s working. Besides the obvious mobile-specific things, it’s running abouuuut as well as tvOS builds of React Native.

I wouldn’t recommend using it. Ever. C’mon now.

Twas The Night Before Dubmas 2018

So with 12 hours to go as we type this before the WWDC 2018 keynote, let’s run down the various predictions floating out there, shall we?

The first interesting thing is that once you download the latest version of the WWDC app — go do that right now, if you haven’t yet — you’ll notice that the option to filter sessions by OS has gone away. Now, that could be just a random designer’s whim, we suppose… 

… but it could be a hat tip that the Marzipan rumours are completely on point, yes? Although we would be rather surprised to wake up tomorrow and find that AppKit has gone away, we wouldn’t be overly shocked. 

(Pro Tip: In the WWDC app, all those emoji-prefixed mystery sessions? Favorite them. Then, right after the keynote, you’ll have a curated list of all the revealed secrets ready to go!)

Speaking of apps, if you are in San Jose tonight, check out this stellar list of party, meet up, and alt-conference apps:

Apps That Help You Make the Most of WWDC

But back to the predictions for this year: If there is anything earth-shattering in the offing other than Marzipan, they’ve managed to keep them pretty much completely out of the rumor mill; the general consensus is that this will be an evolutionary year, at best, and thank heavens for that:

Spoiler alert: Apple’s WWDC 2018 is probably going to be boring, and that’s the way it should be

 

But beyond that, we don’t know much of anything regarding Tim Cook’s and Craig Federighi’s plans for the keynote. That probably means there aren’t any new products hiding up their sleeves. My guess is that the show will be relatively dull from a new-product standpoint, with the usual enhancements to iOS and macOS, some new watchOS features, and maybe a sneak peek at Apple’s upcoming video service. There won’t be a dramatic unveiling of the new Mac Pro or a new $99 HomePod mini. And forget about the ARM-powered MacBook Air we keep hearing whispers about…

Apple WWDC 2018: Why New Iphone Software Announcement Is so Mysterious

But there is another important reason that nothing might have leaked: there is very little to leak. Another story from inside Apple this year said that the company was changing its strategy to focus on improving the performance, efficiency and quality of existing features, rather than looking to institute new ones…

Chances are they’re right yes, but if they do turn out to be wrong, we’ll be the first to point and laugh.

One thing it seems we can count on being introduced is ramping up NFC support, there’s been widespread hints of that:

Apple to Expand Secure Wireless Chip Beyond Payments

And improvements to ARKit are pretty much a given:

WWDC 2018: What to expect from iOS 12, MacOS 10.14 and more

But the more recent Bloomberg report says that multiplayer AR will be featured in this year’s software — something that would lay further groundwork for the Apple AR/VR headset that the company is apparently tinkering with behind closed doors (that’s expected closer to 2020, if at all). A further report, from Reuters, cites anonymous sources and says Apple is working on a way for two iPhones to share AR data directly, so potentially private info about a user’s surroundings wouldn’t have to be stored in the cloud…

Hardware-wise, the expectations seem to range between “nothing” and “speed bumped iPad Pros”

Exclusive: Apple Plans New iPads and iOS 12 for WWDC 2018, New Marzipan Details Emerge

However, we do know for sure that macOS 10.14 will have a system Dark Mode and will very likely be called “Mojave” and that the Mac App Store is getting a makeover, and how do we know that for sure, you ask? Why, because Apple leaked it themselves:

macOS 10.14 Leak Confirms Dark Mode, Apple News App, App Store Video Previews

Just ahead of Apple’s upcoming Worldwide Developer Conference (WWDC), developer Steve Troughton-Smith came across a 30-second preview video on Apple’s servers that should have been hidden, but was accidentally made viewable. The video shows Xcode 10 running on macOS 10.14.

Also visible is an Apple News icon in the dock, as currently found in iOS. The presence in the video seemingly indicates that Apple is porting its Apple News app over the Mac in desktop form. In addition, it looks like Apple is enabling video previews in macOS 10.14, with a redesign of the Mac App Store so that it looks similar to the App Store as currently featured on the mobile side (iOS 11)…

Personally, we’re holding out hope that Apple’s acquisition of buddybuild and the interesting presence of the “Getting to Know Swift Package Manager” session in the schedule indicates that there’s exciting new developments to ease the pain of iOS dependency management. But that would be a forlorn hope indeed, we suspect.

Flutter Flutter Little App

So things were not all that terribly interesting at Google I/O this year, at least as far as iOS developers are concerned — 

100 things we announced at I/O ‘18

— until you get down to

90. We shipped Flutter Beta 3, the latest version of our mobile app SDK for creating high-quality, native user experiences on iOS and Android…

That’s always an interesting claim, isn’t it? Well, allegedly it’s

Ready for Production Apps: Flutter Beta 3

This week at Google I/O, we’re announcing the third beta release of Flutter, our mobile app SDK for creating high-quality, native user experiences on iOS and Android, along with showcasing new tooling partners, usage of Flutter by several high-profile customers, and announcing official support from the Material team.

We believe mobile development needs an upgrade. All too often, developers are forced to compromise between quality and productivity: either building the same application twice on both iOS and Android, or settling for a cross-platform solution that makes it hard to deliver the native experience that customers demand. This is why we built Flutter: to offer a new path for mobile development, focused foremost on native performance, advanced visuals, and dramatically improving developer velocity and productivity…

Well, to our ears, this has a distinct ring of the claims made for cross-platform development by for instance Xamarin, which tend to not be widely shared by those who actually attempt to ship products with them:

Xamarin SUCKS! Lessons learned from weeks wasted

I’m really sorry for the language, but this software is simply and literally the worst mega f***ing shit I’ve ever used in my life. This halfass piece of garbage only serves to waste people time. And IKR, how could people pay for this, ffs?!

… SO TO ANYONE OUT THERE WHO, LIKE ME, THOUGHT “HEY, IT CAN’T BE THAT BAD, CAN IT? I’LL JUST SPEND A FEW HOURS, MAYBE A DAY SETTING THINGS UP BUT IT WILL PAY FOR ITSELF”. NO. GO BACK. IT WON’T PAY. IT’LL NEVER PAY. IN FACT, IF YOUR DREAM IS TO WORK AT MICROSOFT THEN MAYBE YOU SHOULD STICK TO XAMARIN. BECAUSE YOU’LL FEEL LIKE YOU’RE FIXING XAMARIN’S BUGS, NOT YOURS. IN FACT, SOMETIMES YOU’LL EVEN FORGET ABOUT YOUR PROJECT. YOU’LL BE JUST LIKE “WTF IS THIS PROJECT DOING HERE? OH, IT’S MINE”, BECAUSE YOU’LL BE SO INTO XAMARIN BUGS. YOU’LL START THINKING ABOUT GOING TO GITHUB AND FIX XAMARIN INSTEAD OF YOUR OWN CODE (SERIOUSLY). THIS IS A DISEASE. DO NOT GO ANY FURTHER. YOU’VE BEEN WARNED.

Don’t hold back there, tell us how you really feel why don’t you?

Or, there’s always the trendy flavor of the last couple years before people actually started trying to maintain real apps with it, React Native:

Native > Flutter > React Native

As we all know there are a lot of cross-platform development frameworks but none beats the user experience of a natively developed application. A few months back here I was trying to appeal for React Native. But when I took it for a full spin for a fun project. I fell flat on my face.

There were many shortcomings when it came to React Native. Since mobile applications heavily depend on swipe-based user interaction and React Native heavily depends on a bridge that makes the JS code run on the native engine. This caused a lot of janking due to bottleneck. List Views using React Native was a nightmare…

Well, that fellow is optimistic about Flutter’s potential, apparently once bitten still not shy. Give it a couple more decades, you’ll be cynical as a troll, just watch … either that or burnt out completely, there does not appear to be any middle ground.

For some additional supporting evidence, here’s hands on experience:

How fast is Flutter? I built a stopwatch app to find out.

According to the docs, high performance is to be expected:

Flutter is designed to help developers easily achieve a constant 60fps.
But what about CPU utilization?

TL;DR: Not as good as native. And you have to do it right…

Now, not as good as native, that’s not stopping people shipping apps with it, check out the Showcase here. As we write this, the Hamilton musical app is the flagship example of a shipping cross-platform Flutter app, and the builders veritably ecstaticize themselves over the experience here: 

Rise Up! — The story of how the Hamilton App uses Flutter to do more for its fans

So there is definitely the potential here to suck less than other cross-platform solutions — not to imply that’s a high bar! — and it’s always good to have options available, yes?

So if you are interested in Flutter —

— and it definitely looks worth at least keeping an eye on to see if it gains further traction or slides into the shambling undeadness of past Google abandoned failures —

— here’s some resources to check out:

Flutter @ Google I/O 2018 YouTube playlist from @flutterio

Udacity’s free Build Native Mobile Apps with Flutter course

… and of course the Wenderlich tutorial empire is staking territory out here already:

Getting Started with Flutter

Getting Started with Flutter in Android Studio screencast

Flutter Navigation Tutorial

And if you, Dear Reader, happen to have some experience building a non-trivial application with Flutter, be sure to let us know how it went!

 

How To Be Evil: Guide To Violating iOS User Privacy

Remember last year there was this fuss about apps harvesting your location data and selling it? 

The curious case of Accuweather and other apps selling our location data

Well, if you were doing that, the news today is Apple’s not going to put up with it, apparently:

Apple finally decided to start enforcing guidelines on selling location data

So the question that’s no doubt on your mind today then, Dear Evil™ Readers, is: What ways are left to be Evil™ to my users?

As it happens, and this is just the strangest thing, since fastlane was purchased by Google, it seems that the main thing @KrauseFx has been working on is compiling a Manual Of How To Be Evil™:

Privacy research

I work on privacy research projects for the iOS platform in my free time. Those projects are in no way affiliated with my work or my employer…

Definitely not, we’d never suspect that! It’s not as if that employer has repeatedly needed to pay out tens of millions of dollars for privacy breaches…

oh, wait.

All kidding aside, you probably want to read through the collection of articles on that page to be aware of things that could happen to you and how to protect against them, even if you’re not planning to Use Them For Evil™ — 

— or, as may happen, inadvertently. No, seriously. In iOS Privacy: watch.user, that bit about

take pictures and videos without telling you
upload the pictures/videos it takes immediately

Yeah, that was one of the more memorable bug reports we’ve had, back in this kinda-Vine kinda-Instagram thing we worked on back in the day:

QA: Troll, why is your code uploading pictures of my girlfriend?

TROLL: Dude, my code is not uploading pictures of your girlfriend.

QA: *holds up device*

TROLL: Huh. OK … how is my code uploading pictures of your girlfriend?

(Lesson Learned there: even if you use timers only for photo countdowns, your app should listen for applicationSignificantTimeChange, or strange things may happen.)

But the one that we actually want to draw your attention today that you definitely need to read is how to protect your app from other people using it for Evil™:

Trusting third party SDKs

Third-party SDKs can often easily be modified while you download them! Using a simple person-in-the-middle attack, anyone in the same network can insert malicious code into the library, and with that into your application, as a result running in your user’s pockets.

31% of the most popular closed-source iOS SDKs are vulnerable to this attack, as well as a total of 623 libraries on CocoaPods…

… What’s the worst that a malicious SDK could do?

  • Steal sensitive user data, basically add a keylogger for your app, and record every tap
  • Steal keys and user’s credentials
  • Access the user’s historic location data and sell it to third parties
  • Show phishing pop-ups for iCloud, or other login credentials
  • Take pictures in the background without telling the user

The attack described here shows how an attacker can use your mobile app to steal sensitive user data…

And as an aid to that, there’s a repo set up now:

Trusting SDKs – HTTPs

A crowd-sourced list of SDKs and how they protect their downloads with HTTPs.

Based on the Trusting SDKs post by @KrauseFx this repo contains a crowd-sourced list of SDKs and their status when it comes to security when downloading the binary or source code…

Since you are responsible for your app’s behaviour whether the source of Evil™ is your code or your SDKs’ code, it behooves you considerably to acquaint yourself with the risks here — so read up thoroughly, and good luck with not being the next privacy-violating headline!

Swift Four -point- One And All

Looks like a particularly Good Friday today: It’s iOS 11.3 Day, which means Xcode 9.3 Day, which means we have a new Swift to learn:

Swift 4.1 Released!

Swift 4.1 is now officially released! It contains updates to the core language, including more support for generics, new build options, as well as minor enhancements to Swift Package Manager and Foundation. There was also significant progress made in stabilizing the ABI.

Doug Gregor and Ben Cohen recently discussed many of these features on a two-part episode of the Swift Unwrapped podcast. Check out the podcasts here: Part 1 and Part 2

The most code-affecting (by elimination, in the case of Equatable & Hashable!) bits are the progress on the generics front:

Swift 4.1 adds more generics features to the language, furthering the goals set out in the Swift Generics Manifesto. The following generics-related proposals have been implemented in this release:

SE-0143 Conditional Conformance
SE-0157 Support recursive constraints on associated types
SE-0185 Synthesizing Equatable and Hashable conformance
SE-0187 Introduce Sequence.compactMap(_:)
SE-0188 Make Standard Library Index Types Hashable
SE-0191 Eliminate IndexDistance from Collection

For more information about progress made with conditional conformance in Swift 4.1, check out this blog post

Do indeed check out that blog post,

Conditional Conformance in the Standard Library

The Swift 4.1 compiler brings the next phase of improvements from the roadmap for generics: conditional conformances.

This post will look at how this much-anticipated feature has been adopted in Swift’s standard library, and how it affects you and your code…

TL;DR: Things like Optionals and Arrays and Dictionaries will now be Equatable if their contents are, the way things should work!

More than TL;DR: Swift 4.1 conditional conformance is 💖AMAZING💖  and Conditional Conformance

Also, if you’d like more mapping smarts in JSONDecoder, there’s help with that:

JSONEncoder: Key strategies

The strategy enum allows developers to pick from common actions of converting to and from `snake_case` to the Swift-standard `camelCase`. The implementation is intentionally simple, because we want to make the rules predictable…

More discussion in Swift 4.1 improves Codable with keyDecodingStrategy

And the common nil-stripping application of flatMap is deprecated: Replacing flatMap With compactMap

If you‘re trying to hit a binary size target, this’ll help: Code Size Optimization Mode in Swift 4.1

That’s about it for things we’ve noticed of interest, but there’s another comprehensive roundup over at Chez Wenderlich in What’s New in Swift 4.1? — anything we missed here is no doubt in there!

UPDATES:

compactMap for Swift < 4.1

Behind-the scenes improvements in Swift 4.1

Forcing Compiler Errors in Swift

How to use conditional conformance in Swift

What’s new in Swift 4.1? and playground

What’s new in Swift 4.2? and playground

Ole Begemann’s Swift 4.1

What’s new in Swift? diffs any versions

Understanding protocol associated types and their constraints: “Swift 4.1 introduced the ability to make associated type constraints recursive: an associated type can be constrained so that it must also be of the same protocol…”

Review: Continuous Delivery for Mobile with fastlane

 We’ve been idly following fastlane since it was just deliver, and it has had a lively lifespan indeed from obscurity to Twitter to Google and all; so it’s reasonably sure it’s approaching industry standard status at this point, which would make a canonical introduction to it handy indeed. And, why, look what we have to review today, a shiny new copy of

Continuous Delivery for Mobile with fastlane

Fastlane Book Cover

 

Competitive mobile apps depend strongly on the development team’s ability to deliver successful releases, consistently and often. Although continuous integration took a more mainstream priority among the development industry, companies are starting to realize the importance of continuity beyond integration and testing…

What You Will Learn

  • Harness the fastlane tools for the Continuous Deployment strategy
  • Integrate Continuous Deployment with existing Continuous Integration.
  • Automate upload of screenshots across all device screen-sizes
  • Manage push notifications, provisioning profiles, and code-signing certificates
  • Orchestrate automated build and deployments of new versions of your app
  • Regulate your TestFlight users and on-board new testers

It’s actually not 100% accurate, that title; a more accurate one would be “The Complete Beginner’s Guide To How To Ship An iOS App With fastlane Making It Suck Less.” That wasn’t quite as buzzword-compliant, we suppose.

If you do happen to be an iOS-focused complete beginner at dealing with iTunes Connect and all, and you intend to follow the common path of Crashlytics and/or TestFlight for beta distribution … then yes, we believe we can recommend this unqualifiedly as the most coherent introduction out there, go buy it and you can stop reading now!

If you’ve already got this distribution thing sussed, and you’re just curious about whether this fastlane thing that all the cool kids are into these days is worth adopting … hmmm, we’ll give it a three out of five. It’s worthy at explaining what it does explain, but to make it five-star for the more accomplished developer, we’d need two star-worthy things:

1. Documentation on the Android setup and shipping process as thorough as there is for iOS. There’s about six pages worth here, which is pretty thin compared to the iOS coverage. 

If you couldn’t care less about shipping for Android, of course, then this is not a valid criticism.

2. More thorough examples of how to integrate with CI and testing services other than the selected ones, to actually deserve the Continuous Delivery label. As a specific omission we were looking for, the book promises

The next step in this beta lane is to distribute our app via two popular testing platforms: TestFlight and HockeyApp.

… and then goes on to not deliver on this promise for HockeyApp. Since that was, in fact, the main thing we were looking for in this book, how to set it up with a HockeyApp-centric workflow, we were disappointed. So we figure that we’ll take another point off for not being an encyclopedic reference. Yes, we’re brutal. Again, if you are a complete beginner and/or you do use the standard tools that the book does cover, this is not a valid criticism either.

Should you be teetering, here is the publisher’s page and you can check out the TOC and all; plus the code repo for the examples — adding fastlane to Firefox — is here on Github.

But definitely, if you know anyone who’s just getting into iOS development, we’d rate this the best introduction there is out there without question!

On the other hand, as long as we’re talking about fastlane and all, there is the odd pocket of resistance to it you might read for balance:

Five Options for iOS Continuous Delivery Without Fastlane

If you’re looking to escape Fastlane’s frequent build-breaking changes, these five options for iOS continuous delivery are worth examining…

… but that’s definitely a minority opinion, most people find it adds at least some value.

As an example, up there where I docked it a point for not including less popular CI/deployment options? Here is an example of one such:

How to set up GitLab Continuous Integration for iOS projects without a hassle

Why GitLab-CI?

We had GitLab and we couldn’t find any reason for using something else. So, we decided to use it, why not 😎? As for me, the GitLab-CI/CD is more developer-oriented than Jenkins. At least because it is aimed at the pipelines, tags, and branches, unlike Jenkins with jobs. And we have to use those things to get the necessary job instead of configuration without code. GitLab-CI/CD seems like a tool for running scripts on a remote machine; no more, but enough.

Some time later, we realized what it doesn’t matter what to use if we use Fastlane. Because it was able to do all what we needed. As the result, we got freedom from other tools. So I can strongly recommend using Fastlane instead of manual scripts or other approaches…

And, of course, we do find several mentions of “Hockey” over at 

fastlane/examples: “A collection of example fastlane setups”

so it’s not as if their omission is a crippling lack in any way. We just figure a book like this should aim for canonical completeness!

UPDATES:

Build it, Test it, Deliver it! Complete iOS Guide on Continuous Delivery with fastlane and Jenkins

Effortless iOS Code Signing With Match

Delegate Strength Tip: No More Weakness

Now here’s a simple tip worthy of some signal boosting: If you had to pick the most annoying thing about modern Cocoa programming, that continues to regularly trip up even the best of the experts, what would you pick?

Yep, the weak-strong dance, that was our pick too. From the original @weakify and @strongify horrors through the currently conventional [weak-self]-guard-return boilerplate in Swift, it’s just distracting noise and all to easy to overlook with no help from the compiler in catching your retain cycles isn’t it?

Well, here is by far the most elegant solution to that problem we’ve ever seen!

Do you often forget [weak self]? Here’s a solution

You see, from an API design point of view, this new approach actually made things worse. Previously, the designer of an ImageDownloader API was responsible for not introducing any memory leaks to our app. Now, it’s an exclusive obligation of the API user.

And [weak self] is something that is incredibly easy to overlook. I’m more than sure that there is a lot of code out there (even in production) that suffers from this simple, but so ubiquitous problem … We can’t rely even on ourselves to write [weak self] in every part of our app (where needed), and we certainly cannot expect all our potential API users to do the same. As API designers, we need to care about safety at the point of use.

Exactly so!

Let’s look at the core of the problem: 99% of the time, when assigning a delegation callback, there should be a [weak self] capture list, but nothing is actually preventing ourselves from omitting it. No errors, no warnings, nothing. What if instead we could force the correct behavior?

Yes, that is, in fact, something we do want to force. And Messr. Dreyman has a remarkably concise and elegant solution to adopt:

public struct Delegated<Input, Output> {

private(set) var callback: ((Input) -> Output?)?

public mutating func delegate<Target: AnyObject>(to target: Target,
with callback: @escaping (Target, Input) -> Output) {
self.callback = { [weak target] input in
guard let target = target else { return nil }
return callback(target, input)
}
  }
}

and then you use like

self.downloader = ImageDownloader()
downloader.didDownload.delegate(to: self) { (self, image) in
self.currentImage = image
}

That’s a massive leap in safety for very little work, we’re going to adopt it immediately.

With handy accessors and conveniences to go along the library’s still under 50 lines of code — copy the code (or load it with your package manager of choice) from Delegated on github!

Universal Links: The Web-App Connection

Hmmm, looks like we’ve never got around to noticing Universal Links for Developers in this space before; the advantages of those, from Support Universal Links, are

  • Unique. Unlike custom URL schemes, universal links can’t be claimed by other apps, because they use standard HTTP or HTTPS links to your website.
  • Secure. When users install your app, iOS checks a file that you’ve uploaded to your web server to make sure that your website allows your app to open URLs on its behalf. Only you can create and upload this file, so the association of your website with your app is secure.
  • Flexible. Universal links work even when your app is not installed. When your app isn’t installed, tapping a link to your website opens the content in Safari, as users expect.
  • Simple. One URL works for both your website and your app.
  • Private. Other apps can communicate with your app without needing to know whether your app is installed.

Big step up from the custom URL stuff we last mentioned way back in URL Scheme Tidbits, isn’t that? Here’s a well worth reading article to bring us up to speed on some practical applications:

Techniques to Connect Websites to iOS Apps

First, what’s the end game here? To simply leverage some hosted .json files on your server and put meta tags in your markup to allow users to jump straight into your app or display information about it more effectively. That’s it.

This stuff is typically key for SaaS business’ or solopreneurs because in the world we live in, where there is a SaaS website a (hopefully) native app will follow. We want to help them dance together.

It helps that iOS 11 built features specifically for this. Open up your camera, point it at a QR code. Boom — iOS shows us the actionable details. Share a link in messages. Get a rich text preview. The list goes on…

QR code support? Yep, that comes for free with your apple-app-site-association file:

If you host such a file, the end result is that your app will immediately show to open via a notification when the user points at the QR code. The only metadata your QR code needs is the URL for your website.

No external QR code download, no more taps — nothing. It just happens.

If the user doesn’t have your app, Safari will kick in instead, taking them to your website…

… Safari handles all of this as well. If you hosted the QR code as an image, and an iOS user 3D touches on it — this exact same flows happens.

Yeah? Cool!

And if you haven’t looked into Shared Web Credentials for iOS 11 yet, that’s easy too, just associate your domains and tell the app where the credentials go:

This nifty trick is absolutely essential for you if your app has a log in mechanism or any user portal system online. By employing password autofill, users can tap on the lock icon in the quicktype bar that appears over the keyboard, authenticate and then have their information automatically filled out.

It’s beautiful, and I use it daily.

To allow for this to happen, there is minor housekeeping that you need to do for the text fields or text views representing your log in. Simply assign the correct values added in iOS 11 to their textContentType property…

… Once you throw that up on your site — the entire web credentials and password autofill pipeline is all set. I can’t tell you how much times this saves from a user perspective. It goes up by an order of magnitude if one uses Safari’s password suggestions as well.

Lastly, there’s tips on how to enrich your Messages sharing:

Sharing links within Messages is a ubiquitous practice among iOS users. Nothing is more rewarding than tapping on the link cards, with their inviting .png hero images sitting there beckoning us to load up a website within Safari.

Except when that doesn’t happen, and it’s just plain text 😬.

This is so easy to avoid, though, as you easily can control the title, icon, image and even video that displays. Using the open graph protocol, you can supply all of this stuff inside your site’s <head> tag…

The article finishes off by recapping Smart Banners in case you haven’t gotten around to those since iOS 6 either. That makes it a pretty much definitive resource for your app and website coordination — thoroughly recommend you go read and bookmark!

Promises, Promises, Knowing I’d Believe

And in Spot the 80s Lyric today, that post title is Naked Eyes providing the soundtrack for today’s post; we’re going to take a look at an interesting new library from Google named simply

promises

 

In general, a promise represents the eventual result of an asynchronous task, respectively the error reason when the task fails. Similar concepts are also called futures (see also wiki article: Futures and promises)…

Promises is a modern framework that implements the aforementioned synchronization construct in Swift and Objective-C.

Features

  • Simple: The framework has intuitive APIs that are well documented making it painless to integrate into new or existing code.
  • Interoperable: Supports both Objective-C and Swift. Promises that are created in Objective-C can be used in Swift and vice versa.
  • Lightweight: Has minimum overhead that achieves similar performance to GCD and completion handlers.
  • Flexible: Observer blocks can be dispatched on any thread or custom queue.
  • Safe: All promises and observer blocks are captured by GCD which helps avoid potential retain cycles.
  • Tested: The framework has 100% test coverage.

Benchmark
One of the biggest concerns for all frameworks is the overhead they add on top of the standard library (GCD in this case).

The data below was collected by running performance tests for Objective-C and Swift on an iPhone 6s iOS 11.2.1 for the popular frameworks: PromiseKit, BrightFutures, Hydra, RxSwift and plain GCD for comparison…

There’s a whole bunch of metrics collected there, this is the one we found most interesting:

Google Promises Benchmarks

So if you do have a need to mix Objective-C and Swift async code, promises looks like a pretty good option to consider!

However, these benchmarking comparisons aren’t going to mean very much in typical usage patterns, so you should probably go with whatever syntax feels most collegial, really.

Also, those benchmarks are probably not up to date with PromiseKit, which just updated:

PromiseKit 6 Released

With PromiseKit our then did multiple things, and we relied on Swift to infer the correct then from context. However with multiple line thens it would fail to do this, and instead of telling you that the situation was ambiguous it would invent some other error. Often the dreaded cannot convert T to AnyPromise. We have a troubleshooting guide to combat this but I believe in tools that just work, and when you spend 4 years waiting for Swift to fix the issue and Swift doesn’t fix the issue, what do you do? We chose to find a solution at the higher level.

So we split then into then, done and map.

  • then is fed the previous promise value and requires you return a promise.
  • done is fed the previous promise value and returns a Void promise (which is 80% of chain usage)
  • map is fed the previous promise value and requires you return a non-promise, ie. a value.

At first I was nervous about this. But with some use on real projects I quickly realized that done alone was making PromiseKit use much more pleasant. Because Swift has no inference to do about the return for done you can write many line closures without any pain. then and map still require you to specify the return types for closures if they are multiple line, but often they are single line because you are chaining promises encapsulated in other functions.

The result is a happier compiler, a happier you and also, pleasantly (and somewhat surprisingly), clearer intent for your chains.

There’s another recent release in this space that’s mostly under the radar so far but looks like it merits a close look as well:

Tomorrowland

It is loosely based on both PromiseKit and Hydra, with a few key distinctions:

  • It uses atomics internally instead of creating a separate DispatchQueue for each promise. This means it’s faster and uses fewer resources.
  • It provides full support for cancellable promises. PromiseKit supports detection of “cancelled” errors but has no way to request cancellation of a promise. Hydra supports cancelling a promise, but it can’t actually stop any work being done by the promise unless the promise body itself polls for the cancellation status (so e.g. a promise wrapping a network task can’t reasonably cancel the network task). Tomorrowland improves on this by allowing the promise body to observe the cancelled state, and allows linking cancellation of a child promise to its parent.
  • Its Obj-C support makes use of generics for improved type safety and better documentation.
  • Like Hydra but unlike PromiseKit, it provides a way to suppress a registered callback (e.g. because you don’t care about the result anymore and don’t want stale data affecting your UI). This is distinct from promise cancellation.
  • Tomorrowland promises are fully generic over the error type, whereas both PromiseKit and Hydra only support using Error as the error type. This may result in more typing to construct a promise but it allows for much more powerful error handling. Tomorrowland also has some affordances for working with promises that use Error as the error type.
  • Tomorrowland is fully thread-safe. I have no reason to believe PromiseKit isn’t, but (at the time of this writing) there are parts of Hydra that are incorrectly implemented in a non-thread-safe manner.

 

and here’s another:

Getting Started with Deferred

At Big Nerd Ranch, we have created a library called Deferred, which makes it easier for developers to work with data that is not yet available but will be at some point in the future. For example, when you’re downloading data from the network or parsing data, the data is not yet available because some work needs to be completed first. You might know this concept as Futures or Promises, but if not, don’t worry—this post will help you gain a better understanding…

…It was originally inspired by OCaml’s Deferred library.

And there’s a couple more mentioned in this excellent article on the subject,

Under the hood of Futures & Promises in Swift

So there’s a veritable plethora of abstractions to choose from.

Long as we’re on the topic of asynchronicity and all, here’s a good read on parallelization:

Parallel programming with Swift: Basics and Parallel programming with Swift: Operations

and a couple task libraries to take a look at:

Queuer

Queuer is a queue manager, built on top of OperationQueue and Dispatch (aka GCD).
It allows you to create any synchronous and asynchronous task easily, with just a few lines.

Here is the list of all the features:

  • Works on all Swift compatible platforms (even Linux *)
  • Easy to use
  • Well documented (100% documented)
  • Well tested (currently 99% code coverage)
  • Create an operation block
  • Create a single operation
  • Create chained operations
  • Manage a centralized queue
  • Create unlimited queue
  • Declare how many concurrent operation a queue can handle
  • Create a network request operation *
  • Create a network download operation *
  • Create a network upload operation *
  • Ability to restore uncompleted network operations *

ProcedureKit

A Swift framework inspired by WWDC 2015 Advanced NSOperations session. Previously known as Operations, developed by @danthorpe with a lot of help from our fantastic community…

And finally, here’s some lower level tidbits that are worth noting if you have challenges where you need to go right to the metal:

Friday Q&A 2017-10-27: Locks, Thread Safety, and Swift: 2017 Edition

Back in the dark ages of Swift 1, I wrote an article about locks and thread safety in Swift. The march of time has made it fairly obsolete, and reader Seth Willits suggested I update it for the modern age, so here it is!

Initializing on the main thread using dispatch_once without race conditions

We recently refactored the Khan Academy iOS app to use Core Data instead of the haphazard system of JSON files which we were previously using. In this post I’ll explain how to run initialization code that has to happen on the main thread without worrying about race conditions…

Leaky abstractions in Swift with DispatchQueue

At Q42 we have some apps with very occasional weird multi-threading issues. After a bunch of debugging Mathijs Kadijk and I figured out it had something to do with DispatchSpecificKey…

A Simple Approach to Thread-Safe Networking in iOS Apps

With our newfound understanding of URLSession‘s threading model, let’s sketch out how we might extend it to easily support running two requests in parallel. (The source code for this section is available on GitHub, ready for you to drop into a Playground.)…

UPDATES:

Understanding DispatchQueues

GCD Tips

Parallel programming with Swift: Promises