One of the unsung heroes of iOS is CarPlay. It makes your phone far easier, and safer to use while driving. Today, in iOS 12, it’s good, but definitely not great.
I don’t get the chance to talk to John on a podcast often, so this was a lot of fun. And less than an hour!
On ATP, we do often nerd out, but we don’t often go deep on code-related things. That’s fine; ATP is a more general-audience show.
This week, John Sundell was kind enough to ask me to join him on his delightfully nerdy podcast, Swift by Sundell. On this episode, we discussed my investigation into Combine (and reactive programming in general), as well as unit testing, and answered some listener questions.
I had a ton of fun recording this with John; if you’re an iOS developer (or interested in what makes us tick), you should enjoy this too…
You have to be wired wrong if you don’t see the delight and humor in a holiday called World Emoji Day. That day was yesterday, and my buddy Jeremy Burge was kind enough to invite me onto his monthly podcast, Emoji Wrap.
On the episode, we discuss Apple’s new announcements that will be released in an upcoming update to iOS 13. It was a ton of fun to speak with Jeremy, as well as get a sneak preview of what Apple is working on. I’m already anxiously awaiting his call for me to join the show again.
Additionally, internet linguist Gretchen McCulloch joined Jeremy to discuss how emoji are replacing real life gestures.
As an emoji aficionado, this appearance was quite an honor.
For reference, here’s a list of links to my two series of posts on RxSwift and Combine. There’s nothing new today, but it occurred to me that I didn’t have a good summary page that others can link to.
In late 2016, I walked through how to write an extremely basic app using RxSwift. We start by writing the app traditionally/procedurally, and then migrate it to being written using RxSwift.
- RxSwift Primer: Part 1
An overview of what RxSwift is and what problems it’s trying to solve.
- RxSwift Primer: Part 2
Introducing the app we’ll be migrating, and some basic concepts of RxSwift.
- RxSwift Pimer: Part 3
Eliminating the state in our app by using
- RxSwift Pimer: Part 4
Tying data to the user interface using
- RxSwift Pimer: Part 5
Architectural changes and unit testing.
Combine vs. RxSwift
In June of this year, I did a deeper dive on how functional reactive programming came to be, why one would want to use it, and how RxSwift and Combine take slightly different approaches to solving the same problems.
- Building Up to Combine
Let’s create the idea of an
- RxSwift Quick Overview
Exploring the projects that exist in and around RxSwift.
- Combine: Where’s the Beef?
Where are the
UIKitbindings in Combine?
- Quick Notes on Yesterday’s Post
Does KVO make Combine easier to use?
- Error Handling Approaches
RxSwift and Combine take very different approaches to handling errors.
- Under Pressure
Combine handles the concept of backpressure, whereas RxSwift mostly doesn’t.
We discussed how Aleen and I are both in the market for new laptops. My beloved MacBook “Adorable” is getting a bit long in the tooth, and I’m really considering replacing it soon. Aleen is in a similar situation. Stepehen attempts to be our guide as we navigate these new waters.
Yesterady I joined Lory Gil, Dan Moren, and Mikah Sargent on Clockwise. On this episode, we discussed Jony Ive’s recent departure from Apple, unplugging on vacation, the stickiness of gamification, and outdoor tech that we enjoy and/or are lusting after.
Clockwise stuffs an incredible amount of content into a very short time; you really can’t go wrong. As always, this was a fun one.
I have a confession to make:
I’m a monster.
I’m a monster who occasionally buys movies on optical disc.
In 2019, that’s probably a stupid thing to do. I’m a man of habit, and like good reflexes, they die hard.
A friend of mine was recently asking me how I ripped optical discs for use in Plex. The process is pretty easy, but has a couple of potential gotchas.
In broad strokes:
- Get the video off the disc and store it as a
- Compress it in such a way that any normal human won’t be able to tell the difference between the original and the compressed file.
MKVs are nice because they’re generic containers that can hold
pretty much any kind of audio or video content. Since there are
no restrictions about the kinds/codecs of content in a
is a great choice of container; whatever is on the disc can be
stored within a
However, as we’ll learn later, for long-term storage, I actually prefer something different.
- Get yourself a DVD or BluRay player.
There are many, many options for external drives that plug into your computer via USB. I bought a really cheap one that, unsurprisingly, was a piece of garbage. I replaced it with this Pioneer drive which is excellent.
- Download MakeMKV.
It’s available for both macOS and Windows.
- Pay for it.
It’s a great app, and at $50, it’s as much as a couple of BluRays.
- Install it. Note that on macOS, MakeMKV isn’t appropriately
signed, so the first time you run it, you’ll need to find it
/Applications, right-click on it, and select
- Plug in your drive, place the disc in it, and run MakeMKV.
Rip: Easy Mode
- When you run MakeMKV, the first step is to scan the disc and see what’s on it. You do so by clicking the huge icon on the left:
- Once you tap the icon, MakeMKV scans what’s on the disc and will present you with a list of titles, and within each title, chapters.
- If things go according to plan, and if you’re ripping a film,
it should be quite easy to figure out which title to rip. It
will be the one which is largest; usually 4GB+ for DVDs and
20GB+ for BluRays.
If you see more than one option, we’ll cover that later.
- Once you discover which title you want to rip:
- You’ll probably want to un-check all the other titles on the disc, as you probably don’t want to rip those.
- For the title you do want, you’ll probably want to un-check any of the subtitles or audio streams you don’t want. I typically find I’m un-checking Spanish and French on most discs.
- Set the path for the
MKVfile that MakeMKV generates, and then click the icon on the right. This will copy the disc to your computer.
Rip: Hard Mode
Depending on the disc, things can get pretty dodgy when it comes to picking which title to rip. Sometimes you can run into scenarios like this one:
Notice that two different titles are both effectively the same size: 34.4 GB.
Sometimes this is a language issue: even though one title can hold multiple languages of audio, or even subtitles, sometimes films will have different editions to change languages of text shown on screen. Things like signs, titles shown on-screen, etc. Animated films, like those made by Pixar, tend to do this quite a lot with on-screen signage.
However, many times, multiple [near-] identically sized titles are a rudimentary form of copy protection. Often times there is one clear winner, and a bunch of fakes that, when played back, aren’t quite right.
So, what’s the solution?
My first approach is to do a search; sometimes you can find a
forum post that answers the question. When you do find a post that
answers the question, it will be answered in the form of a
to rip. An example could be
If your search comes up empty, you could try to play the disc
and see if your playback software/device will tell you what
mpls it’s playing. In my experience, that’s not something most
players will tell you.
Alternatively, you can take the brute-force approach, which is what I usually do: rip everything and just try playing them. I take a look for on-screen text and forced subtitles. I also scrub through the file and make sure it looks, at a glance, like everything happens in the correct order.
Whichever one is in English, and seems to have all the right stuff in the right place, is the winner.
At this point, you could choose to stop. The
MakeMKV has created is perfectly playable by most software,
such as Plex or IINA. However, these files are
not compressed, and thus they are huge. Our example
above was ~35 GB.
Personally, even though I do have a massive NAS, I’d rather compress these files a bit for storage.
You may know Don as the father of the Safari web browser, but in his retirement, he’s kept his hands busy by writing a suite of incredibly good tools to help transcode and compress video.
In my experience, after running a video through Don’s tools, there is virtually no degradation in quality, despite the output file being 10-20% of the size of the original.
Don’s scripts do use the command line, and the installation can be a little bit fiddly. Installation is left as an exercise for the reader, but once you get everything installed, usage couldn’t be simpler:
That being said, I do prefer to provide a couple of options. So,
let’s say I had a file
avengers.mkv. I would run that file
through Don’s tools as such:
transcode-video --mp4 --burn-subtitle scan avengers.mkv
The two options:
--mp4 indicates that I want the resulting output to be a
MP4 file, rather than another
MKV. This tends to play
better with Apple devices, which is what I use to play these files.
--burn-subtitle scan is a little bit more nuanced. In some
films, foreign-language content spoken on-screen will be displayed
in English by forcing the subtitles to show during that time,
even if subtitles haven’t been turned on by the user. A great
example of this is The Hunt for Red October, when Russian is
--burn-subtitle scan indicates to Don’s tools that they should
attempt to scan for any forced subtitles, and then burn them
into the video, so they’re part of image shown on-screen. As
Don writes in his instructions:
By default, the transcode-video tool automatically burns any forced subtitle track it detects into the output video track. “Burning” means that the subtitle becomes part of the video itself and isn’t retained as a separate track. A "forced" subtitle track is detected by a special flag on that track in the input.
You can also use a special “scan” mode […] to find any embedded forced subtitle track that’s in the same language as the main audio track.
Be aware that using this special “scan” mode does not always work. Sometimes it won’t find any track or, worse, it will find the wrong track. And you won’t know whether it worked until the transcoding is complete.
Personally, I find it infuriating when I try to watch a movie
but the subtitles weren’t properly burnt in. To me, it’s worth
--burn-subtitle scan on anything that has some foreign
language content. You may feel differently.
I’ve only recently gotten in the habit of instructing Don’s tools to burn in subtitles, but they haven’t failed me… yet.
transcode-video process will take quite a while. When it’s
done, you’ll end up with a single file that has a compressed
version of the disc you started with. By
naming the file appropriately, you can easily add it to
Plex, where all the relevant metadata will be added automatically.
Now, you can watch your movie immediately, without having to sit through 2 minutes of FBI warnings and a ridiculous menu. Imagine that.
And if you ever stumble on this, thanks, Stuart. You really made my week. 😄
Phew, it’s been a busy month. 😅
Now that things are finally settling down, I have the time to give the episode the link post it deserves.
Recorded just a few days after Vignette’s release, I was still embroiled in the post-launch insanity. I was also preparing for my then-days-away departure for WWDC. Nevertheless, it was a really great discussion about what it’s like to start from no knowledge of programming, and build yourself up to your own app.
The Stalman Podcast is a wide-ranging show, and that’s what makes it so great. I always consider myself lucky when Tyler asks me to sit in and bring a bit of my kind of nerdiness to the show. :)
- How do we get to
- What is RxSwift anyway?
- Where are UIKit bindings in Combine?
- What’s new in Seed 2? Can KVO save us?
- When do we specify how things can go wrong?
- Who is in charge of saying “no”
We’ve been on a long journey, so let’s go ahead and wrap this up… for now.
Naturally, there’s a lot to love in Combine. So much of Combine is exactly what I’ve been hoping for: a first-party, blessed, approved, framework for reactive programming on Apple platforms. To my eyes, a tremendous amount of Combine was inspired by the ReactiveX project, of which RxSwift is a part.
A lot of what I’m used to is already there, even if the names have been changed.
In some cases, such as
think the change is a dramatic improvement. In most other cases, I don’t have
a strong opinion one way or the other. Which, ultimately, is a win.
Furthermore, there are some differences in the way RxSwift and Combine are designed. RxSwift doesn’t bother itself with typed errors nor backpressure. That leads for easier bookkeeping, but sometimes far more convoluted code. Combine, by comparison, bakes both typed errors and backpressure in from the start. More bookkeeping, but more robust code.
Overall, Combine today is definitely a “1.0” release. There’s a lot that is still missing from Combine. There is no clear way to bind to UIKit objects; the most obvious answer is KVO, but KVO isn’t available on most UIKit objects. Naturally, one can write these bindings by hand, but that’s fraught with peril, and a lot of work.
Plans for Vignette
All of this makes my planning for Vignette… complicated.
Currently, my plan is to keep on developing Vignette using RxSwift. There’s just too much missing from Combine that I’d have to give up and re-write to use it in lieu of RxSwift.
Vignette’s UI is trickier than you’d expect, but still not that complex, in the grand scheme of things. And the siren call of SwiftUI is very, very strong. To affect state changes in SwiftUI, Combine is preferred.
Having only played with SwiftUI a couple times, my current plan is:
- Any new views will be SwiftUI wherever possible.
- Existing views will be ported as time allows and as seems reasonable.
For existing views that I port, my current plan is to bridge from
RxSwift → Combine. Thankfully, the way I write my apps makes this
reasonably easy, as there is one
Observable<State> that will need to be
converted into a
Producer. Everything is contained in that one stream,
so it’s not like I have to assemble 350 output streams in order to bridge
into the Combine world.
(This could get real ugly on the input side, however, as what goes into my
state generator is a ton of UIKit-sourced
Observables. I’m still not sure
how this would play out in a SwiftUI world.)
For a greenfield app, I’m not sure what I’d do.
I think if I could make 100% of the app SwiftUI, I would do so, and use only Combine. To avoid pulling in the large RxSwift dependency would be awesome. However, the moment I need to do more than one or two things in UIKit, I’d probably have second thoughts.
Existing Apps Without RxSwift
If I was looking at what to do with an app that doesn’t use RxSwift, but does use UIKit, I’d probably avoid retrofitting Combine onto any of it. However, I’d absolutely do all new development in SwiftUI and Combine going forward. It is clearly the future; embrace it.
Where Do We Go From Here?
For now, this series on RxSwift vs. Combine is over. I’ve said all I can say without really diving into how this stuff works. The best way to do that, of course, is to use it.
Over the summer I plan to do some compulsory updates to Vignette, like dark mode support, and then start dabbling with SwiftUI and some of this new Combine hotness. As I do so, I’ll surely be putting up new posts describing my findings.
Should you find yourself in the position of needing some assistance with your own RxSwift (or straight UIKit) app, and want me to come in and take a look, please reach out. I have plenty of my own things to keep me busy this summer, but if the fit is right, I’d love to help out some other users. In no small part to help me learn too. 😊