[This episode is sponsored by Hired.com. Every week on Hired, they run an auction where over a thousand tech companies in San Francisco, New York and L.A. bid on iOS developers, providing them with salary and equity upfront. The average iOS developer gets an average of 5-15 introductory offers and an average salary offer of $130,000/year. Users can either accept an offer and go right into interviewing with a company or deny them without any continuing obligations. It’s totally free for users, and when you're hired they also give you a $2,000 signing bonus as a thank you for using them. But if you use the iPhreaks link, you’ll get a $4,000 bonus instead. Finally, if you're not looking for a job but know someone who is, you can refer them on Hired and get a $1,337 bonus as thanks after the job. Go sign up at Hired.com/iphreaks]
JAIM:
Hey everybody, and welcome to episode 134 of the iPhreaks Show. Today on our panel, we have Andrew Madsen.
ANDREW:
Hello, from Salt Lake City.
JAIM:
Alondo Brewington.
ALONDO:
Hello, from North Carolina.
JAIM:
And I’m Jaim Zuber. Today as our guest, we have David Mauro and Kevin Lord. Do you guys want to introduce yourself?
DAVID:
Sure! I’m David Mauro. I am a lead iOS developer at Buzzfeed. I’m currently focused on the Buzzfeed News app.
KEVIN:
My name is Kevin Lord. I am in St. Kitts in the Caribbean right now and my wife attends vet school out here. I also am at Buzzfeed. I do iOS development architecture type stuff and focusing a lot on our frameworks and various libraries.
JAIM:
I think I speak for every person in the Northern Hemisphere; right now it’s December and we all hate you. [Laughter]
KEVIN:
Oh yeah, it’s like 85 and sunny and humid everyday here.
JAIM:
Do you have a parrot?
KEVIN:
I do not have a parrot.
JAIM:
Alright.
KEVIN:
But I do have monkeys in my backyard.
JAIM:
That’s good enough. We’ll take that. So we’ve brought you on to talk about Mattress. Can you tell us what Mattress is?
DAVID:
Yeah. Mattress is a framework for iOS designed to cache entire webpages for offline consumption as well as speeding up the downloading of pages through normal online use. Its main design is it has two caches so that the offline cache is distinct from your standard NSURLCache so that it won’t be overwritten through normal usage of the WebView. That’s about it.
JAIM:
So you're caching the webpage.
KEVIN:
Yeah. [Crosstalk]
DAVID:
Yes. The idea for this came about when I was asked, “Hey, we have these bookmarks in the Buzzfeed app and we want to have the favorites available offline.” We don’t have native content in the Buzzfeed app or didn’t at the time, so that meant keeping entire articles that are designed in a WebView making those available for offline use which, as you can imagine, is actually a little more complicated than it can seem at first glance because you're medium to store between dozens and hundreds of requests all cached to disk.
KEVIN:
It’s also a little more complicated than just loading a page because a lot of sites including Buzzfeed, assets are loaded on the fly. So as the user scrolls down the webpage, images will be loaded and other embeds and things like that will be loaded but they're not loaded until the user actually scrolls down so it takes a lot more work to handle things like that also.
DAVID:
Yeah, just knowing when a webpage is done downloading is a very big question. It’s very loaded in – there’s sort of a, “Oh, I know when a webpage is done – as soon as I can see about a fold.” But from my developer perspective, in terms of what do we need to do to make this webpage available for a reasonable use for offline consumption? A lot goes into that.
For instance, if there’s a video embed on the page, that’s probably not going to be – that’s out of the purview of Mattress and something like that is not going to be available, but something like lazy loading images for instance; Mattress offers a flexible delegate pattern that allows the user of the framework to determine when a page is done downloading content. So if you wanted those lazy loading images to be downloaded within the page, you couldn’t make that happen on your own.
JAIM:
So what are the elements – are configurable like that? Like HTML, JavaScript – things like that.
DAVID:
What we do is every time it did finish load on the WebView delegate, it’s called, we hand that off to the delegate of the Mattress cache. We say, “Hey, this WebView that you wanted is sane – it’s finished loading. Just let us know if you actually think it’s done or not.” So the user can run JavaScript; they can check the dom state, the interactive state or if it’s complete and they just return a Boolean of whether the user think it’s done or not.
JAIM:
Cool. So if we’re talking about caching webpage in our app, that seems a little bit like voodoo. How is this built? How can we use this?
DAVID:
The way it’s built is it uses UIWebView to actually download the page because we’re starting from a URL; we supply URL and we say ‘this is the URL of the webpage we want downloaded’ and the WebView is used to essentially find all of the requests that are needed because that’s what a UIWebView does really well. It’s just – you give it a request and it parses that HTML at that endpoint, finds all the JavaScript there, the CSS. It runs the JavaScript and that might have more requests embedded within it. All of those requests that are made are going to get picked up as they pass through the NSURLProtocol.
So what we can do is hook into that and see all those requests coming and we can essentially identify them which the – this is what the framework is doing behind-the-scenes is identify each of those requests and associate them with that initial request so that we know where they need to be stored and how they should be saved. So how to use it would be – you need to use a UIWebView which – because unfortunately WKWebView doesn’t use the NSURLCache or NSURLProtocol; it kind of have its own caching and protocol system that just does not hook into the standard system stuff.
Using UIWebView, you would just simply – first, you would tell the framework to cache a page, so you just say ‘hey Mattress, ready to cache for me?’ and then that’s going to be my shared cache. Then, I’m going to tell you load this page and you’ll let me know when it’s done. Later, whenever you're ready, you can just simply load that URL in a WebView, and if you're offline it’ll be loaded for you.
JAIM:
That’s cool. That’s a pretty cool functionality that’s difficult to build in your own app. It’s nice to have a framework that does this.
DAVID:
Yeah, it’s kind of dark magic. A little bit.
ANDREW:
I’m curious to learn a little more about how you actually implemented this. I’ve read through the code; I noticed that you subclass NSURLCache. The first question that came to mind – I’ve never really seen this done before; it’s not something I’ve explored very much either though and I wonder if this is really something Apple designed the API for or did it just end up working out nicely so you could do this. In other words, are you guys the first to actually do this?
DAVID:
I don’t know if we’re the first. Kevin, has anyone else done anything like this that you’ve seen before? Because I don’t think I have.
KEVIN:
None that I can think of. I think most relies on using the built-in NSURLCache. Yeah, I can’t think of any other framework or libraries that have sub-classed it.
DAVID:
It’s funny that you say this works out nicely because it didn’t at all, really. I don’t believe it is designed to be sub-classed. Sub-classing doesn’t run to so many issues but the big problem that you run into with NSURLCache is the way it’s designed is they [inaudible] – there’s this global singleton URL cache that you're supposed to create an NSURLCache and assign to. In reality, any time you create a URL cache, it confuses the whole system and it seems to use that to say you create two caches, because the idea for Mattress is you have your standard URL cache and then you have your distinct Mattress cache.
The Mattress offline cache is not an NSURLCache because if you create two of them, they actually start running into each other. It’s very clearly not designed to do what we set out to do; the way that was solved was just create our own disk caching system which the offline cache uses. That’s not – it doesn’t do what NSURL cache does where it offers both memory and disk cache; it’s only a disk cache but that actually make the most sense for our use case, both for loading content faster and loading it for offline use. You're probably going to be running this in some other time later on and you don’t want to – memory cache will not get you much.
The subclass URL cache is really just used to override some stuff to point requests and such in the right direction and mostly just passes off its functionality into the superclass or in two Mattresses disk cache depending on where it should go or come from.
ANDREW:
I thought that was cool because being able to subclass NSURL gave you a way to hook into UIWebView without doing anything special with UIWebView itself; you just use it like you normally do.
DAVID:
Exactly. That’s what’s really cool about it. Like you said, you use UIWebView like you normally would because UIWebView is designed in this cool way that it uses NSURLCache and NSURLProtocol; we can get behind-the-scenes and say ‘oh actually, you want this request from disk’ which is, again, what WKWebView does not view which is – we hate WKWebView now.
ANDREW:
I’d like to talk a little bit about that. We actually shipped an app today at work that uses WKWebView on the Mac. We started out using WebView which is the old WebView on the Mac. I basically have the same opinion of WKWebView that you seem to have, probably for different reasons. But can you talk a little bit about the details of why you – why WKWebView doesn’t work and you have to use UIWebView here?
DAVID:
Yeah. Kevin, if you want to talk about this? I know you probably know even more about this than I
do.
KEVIN:
Yeah sure. So I feel like WKWebView has a whole lot of promise. When it came out, everyone was super excited about it. [Inaudible] so the first performance increases and stuff with the JavaScript engine, but then when you start using it, it’s definitely not as flexible and configurable as UIWebView is. There’s a number of different things where it just doesn’t use the built-in subsystems that UIWebView does.
There’s a few other things like cookies – I believe it has its own cookie cache which is separate from the shared cookie cache. For a long time, you weren’t able to load local files; I think they solved that in iOS 9. We don’t really do that, like try to load local [inaudible] files directly. I’m not positive but I think that part’s been solved. The main thing that cause us problems is that it also doesn’t hook into the NSURLProtocol subsystem. So UIWebView, you can just register your own NSURLProtocol handler class and it will check with that class to see if it can load any request that comes through the WebView. However, WKWebView pretty much just ignores that and does its own thing.
I think there’s probably some good reasons why it’s like that behind-the-scenes architecture-wise so it’s pretty different and runs in its own process and things like that, but it does make it a lot more limited.
DAVID:
I think it being limited for that because of the subsystem. Also, now with the Safari view controller, I think the WKWebView use case is significantly smaller now because if you just need to present a WebView and you want to be hands-off about it as far as view controller is going to be the way to go, and as soon as you need to get at all more complicated and hook into these subsystems to do anything special with the request coming through, you're going to need to use UIWebView.
WKWebView is now on this sort of no man’s land of ‘when are you going to use this’.
ANDREW:
Yeah, that’s basically our problem. It seems like the reason to use WKWebView or UIWebView is because you're doing something more sophisticated than just showing a webpage. In our case, it’s a hybrid web app/native app like Slack or something where the UI’s implemented on the web, but we need to hook in to that. We had that same problem with WKWebView having its own cookie storage. The other big issue for us is that the JavaScript Bridge for WKWebView is pretty lousy compared to WebView. It’s asynchronous and just not nearly as nice as the JavaScript Core Bridge for WebView.
Oh well, I also am disappointed that they announced WKWebView like it was the future. Everybody got excited about it and it seems like they’ve done very little with it in the year and a half or whatever since it came out.
DAVID:
This is probably a good time to give a shout-out to the Twitter.com/wkwebviewparody account which is somebody tweeting on behalf of WKWebView, commenting on basically how bold its functionality is. It’s pretty great. It’s a good – if you're getting upset with WKWebView not doing what you want it to, it’s a good relief to go to just read that Twitter account.
KEVIN:
WKWebView also caused a pretty huge crash in the Buzzfeed app also. We switched over to using WKWebView for loading the articles and apparently, there was this bug where when you were – [inaudible] it was if you're trying to run JavaScript. So we run JavaScript in various, different places to take off a tracking call within the WebView or something like that, and if you kick off a JavaScript – something that run in JavaScript and then the WebView is released, it just crashes. [Chuckles] That was causing a ten percent crash rate in the app at one point because of that bug. That was definitely not for a [inaudible].
JAIM:
I’m curious about the NSURLProtocol, the whole subsystem. Essentially, you can just create your own class that influence the NSURLProtocol, and when you add it to the cache, you could intercept any request that come through. Is that how it works?
KEVIN:
Yeah, you create an NSURLProtocol. Essentially, any that you announce to the subsystem will – anytime a request comes through that for someone who uses the subsystem like UIWebView, it’ll say ‘hey, can you use this request’ and you just let it know whether or not you can.
For instance in Mattress, our Mattress URL protocol looks for keys that it has assigned to requests based on whether we’re offline or whether we recognize this as a request that we’ve associated with a request that the user kicked off to sort offline. If you don’t handle it, you just say no. essentially, it goes through all of the protocols registered with the system and keep looking for one that says ‘hey, I’ll handle this for you’.
JAIM:
It seems to me that with this – this is very powerful but you're also getting request from the entire app – third party components, that type of things. It seems very easy to mess things up in a very insane way.
DAVID:
That’s a good point. It is like – you need to be pretty strict about what – the default is assume you can’t handle a request, and if you say you can’t handle it, just make absolutely sure that you can.
So for a request that we do handle, there’s a lot of logic before them. It’s like, is this – obviously it’s like ‘is this HTTP or HTTPS’ because that’s all we’re concerned with and that’s the first level to check and it’s ‘do we actually have a cache’ – we’re expecting – essentially has the user actually turn on Mattress. Then we check that there’s a cache response for that request or that there is a WebView cacher as we call it that is in charge of that request. Those checks then have a lot of logic in them.
It’s pretty aggressively checking against a lot of different things to make sure we’re sure we want to handle that request before we say we will.
JAIM:
Okay. So when you're creating your web request, how do you indicate to Mattress that this is something that you want the protocol to handle?
DAVID:
The way that this is used is the user will kick things off first by telling the Mattress URL cache, "Hey, I have this URL I want you to download.” In turn, Mattress will create a WebView cacher; that’s essentially just a WebView delegate. It owns a WebView and it is the delegate for the WebView.
When it makes these requests, it will use kind of a combination of its main document URL. So essentially, when you kick off that request, that becomes the main document URL and that’s how it identifies other request is coming through.
Additionally, the initial request has a key added to the request in the header. So what we do, for instance, is the WebView cacher has this mutable request for request method. All the request that are relevant are going to get passed through here and it’s just adding – it’s just calling NSURLProtocol set property true for key Mattress cache request property key. So that’s just adding this identifier to the request that says, “Hey, I’m part of this offline caching system and I need my request to go into the offline cache instead of the standard cache.” Also, any request that come through now, I am going to – they’ll check in with every WebView cacher and then this WebView cacher knows how to identify requests that’s relevant to it based on the main document URL.
It’s a little convoluted. It works out actually a bit more cleanly than it sounds when describing, but yeah, it’s actually worked out really well. It seems to be pretty safe in terms of – I haven’t ever noticed any crosstalk between WebView cachers or anything.
In the news app for instance, I think we’re running four different WebView cachers at once when we background cache webpages.
JAIM:
Okay, so you create a request through the web cacher which handles any setting of the header, and when you use it, you just use the UIWebView.
DAVID:
Right.
JAIM:
Okay. So your view code really doesn’t have any difference that they're using [inaudible] is not a double handled upstream.
DAVID:
Yeah, exactly. So when they load that URL that they previously cached – when they load that in Mattress – if they're offline, the URL protocol will say – there’s actually a delegate method that asks the app ‘are you offline?’ just to make it simpler to identify whether or not we’re offline because that can be a complicated question in itself. So you tell it you're offline, and then when Mattress gets a request, it’ll see that it’s offline and it will just immediately know to only bother checking this disk cache – to start by checking the disk cache that’s offline. If it didn’t have that in there, it’s just going to go through the standard methods.
So if you're online or if you're offline, it’s going to eventually fall back to the standard NSURLCache that it would’ve been using anyways. So it’s just sort of a – we sneak in the middle there and if we need to, we hop in and pull stuff out of the disk cache and supply it. Otherwise, we don’t necessarily need to be there. If it’s a request that we haven’t cached before, Mattress will essentially be doing nothing even though the user in their app is simply just using an NSURL and a WebView.
CHUCK:
One thing that I’m curious about – sorry, I’m coming in a little bit late but anyway, my question is can you use the system – you're talking about using it with WKWebView and things like that. Can you use it with things like NativeScript or React Native or some of these other systems that operate partially or completely in a WKWebView and use JavaScript to do a lot of the calls and things like that? Or do those URL calls go through a completely different system?
DAVID:
That’s a good question. Kevin, do you know anything about those systems?
KEVIN:
No. I have no idea. I’ve never really used any of those frameworks. I will say that if they're using WKWebView then it definitely won’t work if they can work with any UIWebView potentially but I’m not totally clear on what the Mattress benefit would be in that kind of [inaudible].
DAVID:
Yeah. I think it’s essentially – it’s up to the framework really, whether or not they would be hooking into this because essentially, if they hook into the standard NSURLProtocol and NSURLCache system then it will work with Mattress. If they don’t, then Mattress would just never see their request.
CHUCK:
Alright. That makes sense.
ALONDO:
Are there any performance applications here? Things that we’d want to worry about if we’re trying to cache in an unusual number of resources there.
DAVID:
Yes, definitely. [Chuckles] That’s a great question because obviously we’re using UIWebView. So being UI kit, we need to run this on the main thread. We haven’t really dug into this. I’ve tested it and developed builds and stuff and run multiple of these at a time while scrolling through a collection view and it seems to perform okay but there – we’re using a WebView to load these in. Even though the WebView is hidden, it’s probably doing a lot of rendering type stuff on the main thread that would cause performance issues.
So for now, in our use – in the Buzzfeed News App, we only ever run this in the background fetch process. So if you have background fetch turned off, we actually won’t – you won’t get to leverage Mattress. That’s something we want to explore; how much foreground usage of Mattress can we get away with to aggressively reload when the user’s running the app if they opt into that.
I think Kevin was the one; Kevin – maybe even Jaim actually. We’re really good at [inaudible] I was like, “Ah, this seems to work really good in the foreground,” that I think half of them were like, “Yeah, let’s take it easy with that because it could be a lot worse than it appears at first glance.” It’s potentially a lot of work.
KEVIN:
Yeah, I think a decent amount probably does occur on other threads like the JavaScript engine runs on other threads. I’m sure a good chunk of the work is done on threads other than [inaudible] but I’d imagine that there’s still a decent amount that’s done on [inaudible].
I definitely at least – if you're going to try caching things in the foreground, we’re running through instruments, see if it works for what you're going to do because it’s definitely something to look out for.
DAVID:
Yeah. If anyone is interested in using Mattress and has a use case for using it in the foreground on the app and not just background fetch, we’d love to hear about it. We haven’t yet dug into doing that instrumentation and checking it out, but I think it’d be really nice to do.
One of the downsides is obviously – and I think part of the reason we do this only on background fetch isn’t just the performance but – also performance-related but not CPU time but rather the amount of data that is downloaded. Somebody’s webpages can be very large; a lot of webpages don’t do mobile-friendly images. In the Buzzfeed News App for instance, we’re not just loading Buzzfeed pages; sometimes it might be New York Time, CNN, et cetera so we don’t know what we’re going to get. A lot of the request can be very, very large.
We don’t want to be like throttling user’s data who are opting in to this to some degree. I think background fetch is a good use case for that where users who are using background fetch understand that that’s going to use a little bit more battery and data than it would normally.
KEVIN:
That’s what [inaudible] too is you can also optimize it a little bit. I believe in the News App, it’s checking to see if the user’s on WiFi or if they're on their cellular connection. If they're on WiFi, it’ll do a full-caching of the page and so it’ll download the images and try to load other assets and things like that. But if they're on cellular, it’ll kind of just cache like the base HTML and – I’m not sure – probably the CSS file in JavaScript and stuff like that. Is that right, Dave?
DAVID:
Yeah. On WiFi, we wait for the dom state to be complete and on cell, as soon as we hear the WebView has finished loading, we say we’re done. We don’t care if the dom is complete or interactive or whatever, once we get notified, it’s successful. It’s good enough for us. So we hopefully won’t be getting, in most cases, large images and stuff.
Additionally, we found – we had to do time-based backing off. For instance, I think it was four hours we capped ourselves to so we don’t make these requests more than every four hours. With background fetch, you don’t know when you're going to get called, so we found we were getting called a bit more than we really thought we would be. That was necessary when it was clear that we were using a lot of battery in data more than we expected.
JAIM:
Moving on a little bit from the implementation and [inaudible] stuff, I’m curious how did this project come to be? Was this meant to be an open source library?
DAVID:
I think the reason it’s open source is probably – essentially, Kevin’s idea and mostly he’s doing – Kevin, you brought this from a private repo to open source.
KEVIN:
Yeah, so they have to, pretty much all of the initial development for the most part. There’s definitely others [inaudible] in there but I know Dave did it – the vast majority of it, initial development. We’ve been wanting to contribute to the open source community for quite a while and this seem like a good candidate. I went through and just tied up – some of the documentation, added a little bit here and there where it seem like there could be – we can expand a little bit more on things; got the repo ready and I got it set up for Carthage and CocoaPods, updated the Read Me and just got it ready for an open release like how I would like to see a lot of great release ideally. I hope that the Read Me and example project and stuff – the example project was not there to begin with but since I added an example project which is always nice.
Our goal is we really don’t want to just contribute something, like throw it out there and then ignore it which happens sometimes. It’s a shame because you go and use a library and there’s this awesome library, then you go and realize it hasn’t been committed to in two years and there’s fifteen pull requests open in 300-ish years so we’re really trying to stand on top of that stuff also.
JAIM:
So what was it like releasing this into the open source world?
KEVIN:
It was pretty awesome. It was fairly well received. I think the Buzzfeed name definitely helped with that, but we got at iOS Dev Weekly newsletter which was awesome and that got us a lot of [inaudible] on there. Yeah, I think it was pretty well-received. I haven’t – I think it’s still early and there’s definitely – it seems like there’s been quite a bit of interest on GitHub and people checking it out. I’ve had a few small requests and issues and things come in so it seems like people are checking out and hopefully implementing in their apps, but I guess we’ll see where it goes from here.
DAVID:
It was also a little bit terrifying for me [chuckles] just because I think my assumption was when we make this open source, we’re just going to flatten out the history and post in a new repo; we actually posted it – Kevin just opened up the existing repo which means everyone can go see all my embarrassing, old commits. That’s actually – after seeing Swift open source that way and seeing people doing really cool stuff, like visualizing the entire Git history since 2010, that gave me a new appreciation for offering the history of a repo when you make it open source even if it once was private was actually a cool thing to do. I think if somebody wants to see how something came to flourish, like how it grew, that allows them to do that rather than just ‘there’s this cool thing we made; we went from nothing to this perfect framework’ and you don’t get to see how it was made behind-the-scenes.
KEVIN:
For sure. I think it also gives people a pretty good idea of how we do things at Buzzfeed. You can see the pull request and the coder view and all that kind of stuff. We definitely thought about it before we released it, whether we should keep all this history in there and got the sign to just keep the history. I think that’s a good thing.
JAIM:
Well, it makes sense to point out that no software is an endless stream of perfect commits. That’s just not how it works. You try things – ‘oh, that didn’t work at all’ and you roll things back. I’ve got maybe a handful of commits in the Mattress repository, and things that I was trying to get fixed because there was a release coming up. It was like, “Well, let’s try this,” and it works. Looking back, I’m like ‘oh’ – don’t [inaudible] just want to commit; it’s part of a process.
ANDREW:
Speak for yourself, Jaim. [Chuckles]
JAIM:
Other than Andrew.
ANDREW:
Yeah. I think it’s good that you guys released it with the full history. Actually, before we started talking about this, I read through the history. I think it’s instructive to see how something evolved and developed.
I’m curious – this is a Swift library. I don’t know if we’ve mentioned that at all but the whole thing’s written in Swift. I’m curious about two things regarding that; one, have you seen that affect adoption at all? Because I’m not exactly sure when you released this but it seems like at least it’s been in development since Swift wasn’t a lot newer than it is now. The second question is will it work in an Objective-C app or does it require Swift features? I’m not bridged well to Objective-C.
DAVID:
I don’t know. Kevin can speak more to the adoption maybe; I don’t if anybody’s commented ‘oh, I’d love to use this’ but we only use CocoaPods and we don’t use like [inaudible] use frameworks. But I would be surprised just because it seems like using Swift frameworks is something people are just going to have to start getting used to, for better or worse. In our case, we use what we do in the news app, and I think in some of our other apps is we use CocoaPods for non-dynamic frameworks, and Carthage for dynamic frameworks so that we can do both.
There is a solution for that and it does work in an Objective-C library and should be just as straightforward. We don’t want to do anything fancy there which seems like the automatic bridging stuff.
ANDREW:
But you're not – because there are certain things in Swift that will make something not useable from Objective-C like if you're using generics for public facing stuff or you're using straps or whatever.
DAVID:
The API is actually really small. The only thing that you even see is the URL cache and you just instantiate that cache and then you call a method on it. That method takes foundation type stuff. It takes an NSURL and then some completion clock if you're in Objective-C.
ANDREW:
Cool.
DAVID:
Kevin, have you heard anybody mention ‘oh, I wish this were in Objective-C so I get to throw it in CocoaPods easier’ or something? We do handle CocoaPods but it’s just if you're already using it for non-dynamic frameworks, you can’t mix dynamic and non-dynamic in CocoaPods.
KEVIN:
Yeah, I think that would be – probably the only issue. It’s hard to judge whether it had an effect on adoption just because we haven’t open-sourced anything before. So I’m not really – I never really had a good idea like what to expect on adoption rate, my [inaudible] people react and things like that. I think it’s been pretty positive but – there was one person who opened an issue and was having problems bringing it in CocoaPods but I think the issue really ended up being they were trying to build it with CocoaPods and had to have the used frameworks for CocoaPods. One of the other libraries, they were including in CocoaPods when [inaudible] as a dynamic framework. That definitely can be a problem; I don’t think it’s really necessarily a problem with Mattress but it’s something – that’s something that people might run into.
Otherwise, it should work fine. I think what Dave mentioned is using Carthage for dynamic frameworks. We already had CocoaPods and a lot of the apps for other stuff so using CocoaPods for the legacy stuff and then using Carthage for the dynamic frameworks has worked pretty well for us.
DAVID:
Yeah, as far as it being in Swift and why we would do that, this is really part of – because we’ve actually been working on this for a while now. It was part of our push into Swift at Buzzfeed where we decided we want to be writing new stuff in Swift, so any new discreet units, we should do so and so this was a good use case for that.
As far as if it was worth it, because Mattress is almost entirely subclasses of foundation in UI kit objects, it’s really not leveraging any of the strengths in Swift so you're not getting the benefits of good type safety and stuff. It’s mostly just – I don’t think that makes it any worse off either than Objective-C, it’s just – I definitely didn’t run into problems writing it where it would’ve been easier in Objective-C but it’s just makes it a dynamic framework which could be a turn-off for some, but I expect more people to be hitting on solutions now where they're able to incorporate both ObjectiveC and dynamic Swift frameworks into their apps.
ANDREW:
Yeah, I love dynamic frameworks. I’m mostly a Mac developer, more so than an iOS developer and we’ve had frameworks forever. I’ve just been happy that they came to iOS but I probably should’ve worded my question differently because I didn’t necessarily mean negative impact from adoption, just an impact one way or another. I know that CocoaPods has their new – not relatively new but you can go check the stats for the pod and they have a quality rating. It’s just sort of a number between zero and 100 that’s supposed to be the idea of a quality of a particular library. They actually give points for having your pod written in Swift. They consider that a good thing [crosstalk].
KEVIN:
That’s kind of interesting.
ANDREW:
As if it’s a – I think Swift is the future. It’s sort of the idea. I expected that some people were eager to use it because it’s in Swift because it’s modern and new.
KEVIN:
I haven’t really heard too much on that one way or another but I definitely feel like Apple is, for sure, pushing everyone towards doing more and more Swift. It seems silly to, at least to me – to a degree, if you're creating something new, from a brand new, fresh slate to do an Objective-C. It seems to me that it just makes more and more sense to write in Swift or else you're just giving yourself more work down the road but – yeah.
ANDREW:
Is there anything else about Mattress or having this open source library? Anything that you guys want to talk about before we wrap up?
DAVID:
Honestly, not just to hype people up on Mattress, but if you're loading WebViews in your app, I urge you to give this a shot because this – Mattress is a win for your users. It’s open source now so we want people using it and contributing. We’re not going to be the maintainers who are like, “Oh, we’re going to ignore your pull request”; we really want people to contribute to make this better both – obviously, any improvements, we get to take advantage of but also just because the reality is a lot of apps use WebViews and a lot of apps will use them in different ways. Most of them are probably going to benefit from having that stuff, having that their content loading available offline, or also just for speeding it up.
So if you're using it, give Mattress a shot and we’d love to hear from you if you are using it.
ANDREW:
I just thought of another question. Where did the name ‘Mattress’ come from?
DAVID:
That’s Kevin.
KEVIN:
We started a theme on names for libraries and frameworks. The general theme is housewares and things you’d find in the kitchen in the house, so Mattress just fit in with that.
The original idea was it was a cache, and some people hide their cash under their mattress and so that’s where the name came from. I don’t know if this was the first one in that line of names but we’ve got a whole bunch of internal libraries and frameworks all in that [inaudible] now.
DAVID:
Yeah, I think Mattress was the one that kicked off the houseware theme. It started with mattress because you put your cash under the mattress, and something else was also houseware themed so it’s kind of thing.
JAIM:
Mattress is a pretty cool piece of software. Are there any other projects in the pipeline?
DAVID:
Yeah, what’s next Kevin? [Chuckles] Anything we can – what do you think is coming out next?
KEVIN:
Not totally sure yet. We have some things that we’re working on and there’s some potential things. We’re definitely planning on releasing more in the future, but not totally positive on what the next one will be.
DAVID:
Yeah, I’ve got some that I’m working on now that we’re using internally that I would love to make open source. One I’m working on in particular is geared toward alleviating design issues, things like – the fact that UI label doesn’t offer line height. There’s a lot that goes into simple – you get a design spec from a designer and making that is much harder than it should be so I’m working right to alleviate that.
A lot of the work which has been done on the news app so it’s just providing that. I’d love to find a way to make that a framework that’s available for wider consumption and use.
KEVIN:
Yeah, that’s definitely one of the things in the near term future. Buzzfeed on the website just released Solid which is a CSS style framework. This does a similar – the thing that [inaudible] been working on does a similar thing on the iOS side. There’s definitely a possibility we might release that, too, as a companion to what they’ve been releasing on the website.
JAIM:
Very cool. Let’s get to the picks. Alondo, what do you have for us?
ALONDO:
I have one pick this week and it is tangentially related. It is an app that we’ve been using at work on our projects to manage our day to day stand up communications between the team. One of the things that happened is they had trouble with discovery because of naming, so they actually wrote a blog post that the app was called Flock, and now they renamed it to Jell. They did a nice little blog post about why and how – what the cost of having the wrong name was for them.
I’ve actually encountered that on the other projects I’m working on, too, trying to come up with the right name and getting the right domain and everything like that. That’s my pick this week.
JAIM:
Andrew, what do you have for us?
ANDREW:
My first pick is an app called Patterns. It’s a Mac app for working with regular expressions. It’s actually a really simple tool; it lets you type in regular expression, shows you – you can put in some search text and it will – live while you're typing the regular expression, show you matches. It also supports doing replacement and that’s also live.
I use it as a way to do search and replace stuff, text manipulation because I’m not really good at regular expressions and it’s really helpful to me to be able to see what I’m doing while I’m doing it so that I can keep making mistakes and iterating until it actually works. It has a little cheat sheet with all the different parts of regular expressions. Another cool thing it does is you can choose a language – programming language including Objective-C and hit ‘copy code’ and it will copy a little snippet of code that does the regular expression in that language. That’s pretty fun.
My next pick is another app by the same guy that I think I’ve picked before but I just love it. It’s called CodeRunner, now in version 2. This is a really simple app that hides a lot of complexity. It just knows how to run code in a whole bunch of different languages. You hit command and you get an empty file, you choose what language you write and start writing code. You can hit run and it will compile and run it. It has built-in compilers for a bunch of different language. It’s got syntax highlighting and code completion and stuff so it’s pretty useful for playing around with a new language you're trying to learn, writing little, quick snippet of code that you want to test out. I use that a lot.
My last pick is somewhat self-serving but I mentioned it a little at the beginning that we launched a new app today at MixedInKey we did and it’s called Odesi. I’m really excited about this; we’ve been working on it for about a year and a half. It’s a music composition app that helps you get started on composition – music composition. It helps you write chord progression and basslines and rhythms. We’ve done some pretty cool, fun stuff with it. I worked on the Mac app which has a pretty fullfeatured audio engine. This is the app that drove a lot of the improvements in MIKMIDI which we talked about a couple of weeks ago. That’s Odesi by MixedInKey. Those are my picks.
JAIM:
Cool. Charles, do you have any picks?
CHUCK:
I have a crying baby; does that count?
JAIM:
Earplugs. [Chuckles]
CHUCK:
A couple of things that I’ve just been thinking about lately – hang on, let me pick her up.
JAIM:
Last week on the show, we had the baby eating quietly.
CHUCK:
Yeah, not the case this week.
JAIM:
You have a crappy baby.
CHUCK:
The show is right when my wife has to go pick up my kids from school. Since the baby is so new, I have her this week and next week probably while she goes to pick up kids from school. And look at that, she calmed down when she heard me talking. Anyway, there are a couple of things that I’ve been thinking about lately. I don’t do these deep thought ones very often but there are a couple of things that have gone on that have made me think. The first one is just spending time with family; I’m going to pick that. My dad went in for open heart surgery yesterday.
He’s fine; he’s in the ICU now. But it’s a common enough operation that you assume that everything’s going to work out okay but at the same time, you recognize that they're going to open this chest and stop his heart so they can work on his heart and that’s kind of scary. Just recognizing that there are things that are often more important than code that you need to dedicate your time and your life to so I’m going to pick that.
The other thing that I’m going to pick, and it’s something that I’ve done over the last couple of days, is clean my office. I found that just having an orderly or semi-orderly space to work in just takes a whole load off of my mind so I’m going to pick that as well. So two meta picks, nothing that you can link to. Anyway, really liking those.
JAIM:
Alright, thanks. So I’ve got two picks and they're just a couple of blog posts that were helpful to me when I was doing a little hacking on Mattress. So if you're interested in hacking on Mattress or doing any stuff with NSURLCache or NSURLProtocol, these are some good posts. One, almost obligatory NSHipster article [chuckles]. There’s another one that I found; it’s not just esoteric stuff where they're explaining it; this has a practical application. Let’s say you have an app and you want to replace all the images with pictures of David Hasselhoff, this post by ObjectiveToast will tell you how to do that. Here we go; I’m just putting it out there.
David, do you have any picks for us?
DAVID:
Yeah. I’m just going to go with Swift.org because I’m excited that Swift is open source now I’m looking forward to how Swift is going to grow now and be able to follow along with what’s happening in the future and see things like the package manager they're working on. Obviously, I would also love to see if Xcode got open source so we can put some pull requests into that to fix some bugs, but we’ll take what we can get and having Swift open sourced is really cool. It’ll be nice to squash some bugs.
The other one, I reposted the Twitter.com/wkwebview. If you're not following WKWebView, make sure to do so. It’ll make your Twitter timeline more fun.
JAIM:
Okay. Kevin.
KEVIN:
So yeah, I have two picks. Neither are iOS related but one, maybe this is a website people already know about. I have no idea but the website hackaday.com. I’ve been really into, in my free time, doing electronics and building circuits and PCB design and all kinds of stuff like that embedded. It’s a pretty awesome website where they just post a lot of projects and news and things like that in that world. It just makes it really relevant by showing cool projects that people build so that’s one.
The other one is the soda, Ting, which, here in St. Kitts, is probably the most amazing soda that you could ever have. It’s available all throughout the Caribbean. I’m sure you can find it in the US somewhere. I think it’s on Amazon but it’s a great fruit-flavored soda and it is awesome. So if you ever get a chance to try it, you should try it.
JAIM:
We’re getting a plus one from Alondo on the Ting soda.
ALONDO:
Oh yeah.
DAVID:
And a great name.
JAIM:
Where can you get it in the States? [Inaudible]
ALONDO:
[Crosstalk] I used to just get it when I go to eat Jamaican food. We try to buy it in the actual grocery store. I think there are a couple of markets where I could meet patties or something, you can get them. Again, very Jamaican-oriented. [Chuckles]
KEVIN:
Yeah, Tastee patties is also great. I’m not in Jamaica but they have a lot of Jamaican stuff here. Ting is – actually [inaudible] it here on the island, too, I believe. So this is like local Ting but I’m pretty sure you can buy Ting straight from Amazon. I’m not sure if it’s very cost-effective but I think you can get it.
JAIM:
It’s good to know. Well, that about wraps things out. Kevin, Dave – I want to thank you on for coming on the show. Everyone else, let’s get hacked in on Mattress and check it out
[Hosting and bandwidth provided by the Blue Box Group. Check them out at BlueBox.net.]
[Bandwidth for this segment is provided by CacheFly, the world’s fastest CDN. Deliver your content fast with CacheFly. Visit cachefly.com to learn more]