022 iPhreaks Show – Networking with Steve Madsen

Download MP3

Panel Steve Madsen (twitter github Light Year Software) Andrew Madsen (twitter github blog) Ben Scheirman (twitter github blog NSSreencast) Jaim Zuber (twitter Sharp Five Software) Pete Hodgson (twitter github blog) Rod Schmidt (twitter github infiniteNIL) Charles Max Wood (twitter github Teach Me To Code Rails Ramp Up) Discussion 00:45 - Going Rogue Video 01:21 - Steve Madsen Introduction Light Year Software 02:00 - Networking with iOS WiFi Connection Speedtest.net HTTP Live Streaming 07:58 - Bandwidth and Quality of Connection 12:23 - Network Link Conditioner 15:29 - Reachability 24:27 - Networking Gotchas 26:54 - NSOperation Dependency 29:41 - AFNetworking RestKit 33:54 - Logging of Networking Requests and Response Runscope 38:49 - Networking Technologies 41:27 - WebSockets faye SocketRocket 45:48 - Fallacies of Distributed Computing Picks ARC vs. MRC Performance (Andrew) Machine language: how Siri found its voice (Andrew) Philips hue (Ben) hue (Ben) CopyPasteCharacter.com (Ben) Glyphboard (Andrew) Lawyers (Jaim) Runscope (Pete) estimote (Pete) Acme Pale Ale from North Coast Brewing (Pete) XCOM Enemy Unknown (Pete) RubyConf (Chuck) Airbnb (Chuck) Platform University (Chuck) Little Snitch (Steve) Upton Tea (Steve) Clojure: Enemy of the State (Rod) Hire Rod (Rod) Next Week Build Automation with Patrick Burleson Transcript CHUCK: Hey everybody and welcome to Episode 22 of The iPhreaks Show! This week on our panel, we have Andrew Madsen. ANDREW: Hi! I’m not a robot; I’m just going to [unclear][laughter] CHUCK: Ben Scheirman. BEN: Hello! I’m eagerly waiting of the arrival of GTA 5. So if the doorbell rings, I may run to go get it. CHUCK: Alright! Jaim Zuber. JAIM: Hello from Minneapolis! And also, not a robot. CHUCK: Pete Hodgson. PETE: Good morning from…I am not a robot. [Laughter] CHUCK: Rod Schmidt. ROD: Hello from Salt Lake! CHUCK: I’m Charles Max Wood from DevChat.tv. Before I introduce our guest, I just want to make a real quick announcement. This Friday, meaning last Friday when you get this episode, was my ‘Freedom Day’. It was the day I was laid off from my job 3 years ago and went freelance. I’m celebrating that by putting up a free video that kind of chronicles my journey through freelancing and going from laid off to actually making enough money to live on. I’m going to have a lot of lessons that I learned in there and stuff, so if you’re interested, you can get that at GoingRogueVideo.com. BEN: Whoo-hoo! Congrats! CHUCK: Thanks! We also have a special guest, and that is Steve Madsen. STEVE: Hello from the Columbus, Ohio. CHUCK: Can we get you to introduce yourself real quick? STEVE: Sure! I own Light Year Software, which is a small consultancy here in Columbus specializing in Rails and iOS development. I’ve been doing that for about 7 years now since relocating back from the San Francisco Bay Area. CHUCK: Was it named after the unit of measure, or the cartoon character? STEVE: Unit of measure. CHUCK: Okay. STEVE: I was looking for something science-y. CHUCK: Awesome. PETE: What’s the cartoon character? CHUCK: Toy Story. Buzz Lightyear. PETE: Oh! Oh, yeah. CHUCK: Alright, we brought you on to talk about “Networking”. STEVE: Yes! That’s a big topic! CHUCK: I was going to say [laughs] it was kind of a broad topic. What in particular is interesting about networking with iOS or Cocoa? STEVE: Specifically about iOS, obviously, we’re talking about mobile devices. I think it’s safe to say that since mobile devices became as popular as they did with the introduction of the iPhone, the possibilities on how for us to build apps that communicate back to servers or communicate with people nearby have gone up a lot. CHUCK: Yeah, that makes sense.


CHUCK: Hey everybody and welcome to Episode 22 of The iPhreaks Show! This week on our panel, we have Andrew Madsen. ANDREW: Hi! I’m not a robot; I’m just going to [unclear][laughter] CHUCK: Ben Scheirman. BEN: Hello! I’m eagerly waiting of the arrival of GTA 5. So if the doorbell rings, I may run to go get it. CHUCK: Alright! Jaim Zuber. JAIM: Hello from Minneapolis! And also, not a robot. CHUCK: Pete Hodgson. PETE: Good morning from…I am not a robot. [Laughter] CHUCK: Rod Schmidt. ROD: Hello from Salt Lake! CHUCK: I’m Charles Max Wood from DevChat.tv. Before I introduce our guest, I just want to make a real quick announcement. This Friday, meaning last Friday when you get this episode, was my ‘Freedom Day’. It was the day I was laid off from my job 3 years ago and went freelance. I’m celebrating that by putting up a free video that kind of chronicles my journey through freelancing and going from laid off to actually making enough money to live on. I’m going to have a lot of lessons that I learned in there and stuff, so if you’re interested, you can get that at GoingRogueVideo.com. BEN: Whoo-hoo! Congrats! CHUCK: Thanks! We also have a special guest, and that is Steve Madsen. STEVE: Hello from the Columbus, Ohio. CHUCK: Can we get you to introduce yourself real quick? STEVE: Sure! I own Light Year Software, which is a small consultancy here in Columbus specializing in Rails and iOS development. I’ve been doing that for about 7 years now since relocating back from the San Francisco Bay Area. CHUCK: Was it named after the unit of measure, or the cartoon character? STEVE: Unit of measure. CHUCK: Okay. STEVE: I was looking for something science-y. CHUCK: Awesome. PETE: What’s the cartoon character? CHUCK: Toy Story. Buzz Lightyear. PETE: Oh! Oh, yeah. CHUCK: Alright, we brought you on to talk about “Networking”. STEVE: Yes! That’s a big topic! CHUCK: I was going to say [laughs] it was kind of a broad topic. What in particular is interesting about networking with iOS or Cocoa? STEVE: Specifically about iOS, obviously, we’re talking about mobile devices. I think it’s safe to say that since mobile devices became as popular as they did with the introduction of the iPhone, the possibilities on how for us to build apps that communicate back to servers or communicate with people nearby have gone up a lot. CHUCK: Yeah, that makes sense. Does it change much if you’re talking over cellular data versus WiFi? Or, most of your apps just not care? STEVE: I don’t think most apps care. From an app developer’s point of view, the APIs are exactly the same; you have to do some work to actually find out if you’re on WiFi or cellular. Of course, there’s all kinds of issues about ‘do you even want to know’ because Google and other places, or even airplanes, are famous for having WiFi in their transportation, but the link back to the actual internet behind that WiFi is either a satellite connection or cellular. So if you make assumptions about what you can do with the network based on the fact that your iPhone thinks it’s on WiFi, you may find it. The reality of situation is extremely different. PETE: Yeah, same thing with my phone, like this little pocket WiFi thing. If you got an iPad that doesn’t have cellular, then you might be using that most of the time, but you’re still on the cellular network; it just looks like it’s a fast network until you – BEN: Yeah! A lot of us have been at conferences where you have WiFi – I use BackBox to backup my Mac – I was at CocoaConf recently and realized that it was trying to back up like 18 gigs of stuff on a conference WiFi. It was a little disappointing; do you have to turn that stuff off. But yeah, how are you really going to know what type of connection that you’re going to get? STEVE: You can’t. If your use case really does depend upon something to do with the network and in terms of its latency you’re dependent with, you’re  much better off to try and measure those things within the app and then make decisions based on what you measure as opposed to assumptions about what you think you have based on a connection type. PETE: I guess there’s different kinds of performance gotchas as well because there’s the role bandwidth, but then there’s also latency and stuff like that. So even if it seems like you’re getting really good connection, it might be very bursty where you get like chunks and chunks of data and then nothing comes through for a while, then you get chunks and chunks of data. So I think even doing something that measuring bandwidth or measuring latency is actually quite – there’s some subtlety to that beyond just like going to Speedtest.com or whatever and seeing all the little [unclear] I told you. STEVE: Exactly. Actually, it’s something you would have to measure sort of ongoing, not something you could do once and then just forget about it and assume that nothing changes. The network is a really interesting thing for us to develop against because you can never make any assumptions about it; things are constantly changing. Unlike a lot of other things where you can test, and you can test, and you can test, you can be relatively sure that things work, the network will always bite you [laughs]. Things will always fail in weird and non-predictable ways. HTTP Live Streaming that the Apple does for all of its videos and stuff actually does more or less what I’m talking about. The publisher on the server side actually publishes multiple streams at varying bit rates. And at runtime when you’re playing a video, the frameworks will actually switch to a lower or a higher bandwidth stream, depending upon the conditions that it’s absorbing and whether or not it’s able to keep up or whether it’s losing packets and falling behind, it kind of does exactly that. JAIM: I wonder if [unclear] that help you do this sort of thing? STEVE: I’m not aware of any off the top of my head. BEN: Do you mean specifically like consuming HTTP Live Streaming? JAIM: Not Live Streaming you’re talking about. A lot of us just do kind of we’re on WiFi or cellular, but next we’re checking, your bandwidth, your latency, if you’re dropping packets, and kind of adjusting your app accordingly, are there any kind of toolkits that help you with this? Or, what APIs you’re actually using to figure this stuff out? PETE: I wonder what the HTTP Live Streaming, whether it’s a private API that Apple has access to that we don’t or whether they’re just doing the same stuff that we could do if we took the time to do it. BEN: I think they’re using the same, like they’re starting at a much lower level like measuring the packet loss and that sort of thing. But specifically for HTTP Live Streaming, you can inspect like keep the log and you can use that log for introspection to see like what type of rate you were getting specifically for an HTTP Live Stream. It’s interesting, but that’s not going to help you out if you’re just dealing with like a general API. I work on a streaming radio app and we have to determine whether or not to send a high-quality content and we’re not yet using HTTP Live Streaming. So right now, we make that determination on whether or not you’re on WiFi, which is sometimes a mistake depending on how good your connection is. PETE: It sounds like the best solution there is to be streaming a video over cats doing a funny dance in the background. [Laughter] PETE: And then you watch the log, and then if the logs says you’ve got bad network, then you stop streaming the video of the cat. BEN: Yeah, and you can show it to the mess and he’s dragged. CHUCK: [Laughs] All joking aside, though, how do you figure out what kind of quality bandwidth do you have? Is it something like that? Or, you’re requesting something that requires a fair bit of bandwidth and then seeing how much is stutters? STEVE: If I were building a video app, and for some reason you couldn’t use HTTP Live Streaming, first of all, you’re probably get rejected from the App Store [laughs], but that aside, I think you’d watch how much data you’re getting back because it’s the request you made. If you ask for what you expect to be about maybe, say, 10 seconds worth of data and you can buffer that in 5, then you should be able to assume then, “Well, you’ve got a pretty good connection, maybe move up to a higher quality bit stream, or stay where you are. CHUCK: That makes sense. PETE: I kind of feel like the most robust way of doing this is to follow that same principle of like “Don’t check WiFi to see if you’ve got a good connection” because really, you don’t care whether you’re on WiFi or not; you care about the quality of the connection. I’d always tag it as the same with the latency and the bandwidth stuff don’t explicitly measure that, but look at how much whether you’re able to keep up with the amount of days you need, and if you’re not, then adapt a bit or whatever, for the video example. But trying to develop some super sophisticated heuristic seems pointless when you can actually just find out whether you’re keeping up or not by seeing if you’re keeping up or not, like look at the Android – ANDREW: Yup, exactly. BEN: And there’s no like scaling down quality of like a full JSON response so this only matters for media in which you have multiple encodings so that you can adapt. But if you’re just like consuming an API, you still need all that data so it doesn’t necessarily matter. But you might record failures or something so that you know like maybe you’re just treated as offline if all these requests are failing. PETE: I think that’s the – I guess maybe this is often a slightly different tangent – but from a user experience point of view, what I would really like to do is be able to fail fast if I know that I’ve got a network connection that’s not really going to work. So the thing is really frustrating for me as a consumer, as a user of applications, is when I’m on public transit or something and I’ve got a really spotty cellular connection and I go to load something and it doesn’t say, “You don’t have a network,” it just sits there and doesn’t do anything. Unfortunately, I don’t think this is really a solvable problem. But really, what I want my apps to do is to tell me when I don’t have a network connection so I don’t sit there staring at this kind of bar that’s like perpetually at 20% across their  host system. BEN: That’s particularly problematic with Verizon in an elevator. I’m on Verizon and it works in my house, yay! So that’s why I am on Verizon. But in my elevator – I have 2 elevator rides when I go to work – it just doesn’t work at all so I’ve just gotten used to not even opening it. One of the problems it has is recovering from being inside of an elevator, it takes a long time to just switch back to like an active cell tower so I can see that the request are going to fail; just one of those things you learn to avoid. But yeah, it would be nice if I can just [unclear] cancel everything you’re doing and I will start to begin later. ROD: Are you saying you have a connection but it’s really slow? Or, you just have no connection? BEN: Yeah, I have like 2 bars and it drops from LTE to 3G, and sometimes from 3G down to like GPRS or something. On iOS 7, it says 1x, I don’t know what that means, but I’m guessing that’s GPRS, and it just never finishes anything. It takes about probably almost a full minute after I get out of the elevator to reestablish a good connection. PETE: It’s kind of like the opposite of Denial of Service Attack… [Laughter] PETE: This is service that doing a Denial. They’re like kind of slow rolling you where they’re like, “Oh, yeah! Here’s a bit,” and it’s there comes up. [Laughter] PETE: The other one right here somewhere, let me just look around. Yup! There is another bit. CHUCK: It’s a Denial of Service because your service is denied. PETE: Yeah. JAIM: I think the one access actually carry your pigeon. [Laughter] ANDREW: It does help, like working on a streaming radio app, it helps me test scenarios like that. But we rely heavily on the Network Link Conditioner as well. Once you’ve solved this problem, where it’s good enough in most cases, you don’t necessarily have to continue testing it, Network Link Conditioner on iOS is super, super handy. Just remember to turn it off when you’re done. PETE: [Chuckles] I think we’ve talked briefly about that in another episode, but we should probably, since this is in an episode about networking, we should probably talk about in more detail because it’s a super useful tool. CHUCK: Yeah. PETE: But I haven’t used it. STEVE: It used to work for me. I have Xcode 5 gm on my main machine now, and I sat down and do something with the Network Link Conditioner last night. It turns out that it seems like there needs to be a very specific matchup between your tools and the prefPane and I don’t’ have that right now, so it just utterly does not work, so be forewarned. If it works for you, don’t touch anything. PETE: How would I even use this Network Link Conditioner thing? Where is it and what do I do with it? STEVE: It’s in 2 places actually. It started life on the Mac as part of the Xcode tools, and I think they – I don’t know if they came with the Xcode bundle originally, but it’s in what they call the “Hardware IO Tools” now which is a separate download. You just install it to prefPane, it shows up in System Preferences, and then you can go in and turn it on or off. When you turn it on, you can pick a profile that dictates the downlink and the uplink bandwidth as well as the latency of packets, and you can even have a drop rate so you can make a link glossy to see what will happen if you’re on, say, a bad cellular connection where 1% or 2% of packets just never arrives. When it works, it works perfectly well; it gates all traffic in and out of your Mac, though. So again, if you have it on and then you forget about it and you go on Safari, and you wonder why everything is taking forever to load, it’s probably because you forgot. And then I don’t remember if it was iOS 5 or iOS 6, but app that’ll actually bundle the Network Link Conditioner and iOS as well so now it’s buried under the – I don’t remember which…Does anyone remember which menu it is under Settings? BEN: I think you have to enable your phone for development, and then there’s a Develop Menu somewhere in there. STEVE: Yeah. And so you get all the same options there, but then for traffic in or out of your device, which is really great. ANDREW: Yeah, it’s under Developer so that you get a developer section of System Preferences if you turn on developer mode, and the Network Link Conditioner is one of the things is in there. PETE: I think on OS X, the Network Link Conditioner is just a GUI in front of the iptables or whatever the FreeBSD or the BSD equivalent of iptables is; it’s just messing with your Firewall that’s built in to the Mac basically. STEVE: I thought that last night, and I’m not so sure anymore. PETE: Oh, really? STEVE: Yeah. PETE: Interesting. STEVE: When I started getting the [unclear], it wasn’t working for me. I dug in the console, and then dug into the prefPane bundle itself, and they’re actually using XPC services in there, sort of like a helper application that runs. I don’t know what they’re doing [laughs], but it’s not a simple wrapper around PF or whatever the packet filter that OS X uses now. PETE: Oh, interesting. Okay, well, my information is out of date. CHUCK: So what libraries do you guys use for networking? ROD: One thing that might come in handy for the situations we’re talking about is the Reachability CocoaPod that you can use that will tell you if you have a connection or not. If you don’t have a connection, you can display UI and it says “I don’t have a network connection”. I’m not sure if that will work with a really slow connection; they’ll probably not. STEVE: I don’t think so. I’m relatively sure that Reachability basically just monitors the routing table so it’s not a “I can reach the server” but it’s an “I should be able to” based on the routes. ANDREW: Alright, we’d confirm that. So Reachability won’t tell you if you have a network connection that’s just not working; it will only tell you if the phone truly thinks you don’t have connection. BEN: Do you guys have like a good strategy for managing Reachability in your app? Because a lot of times, you’ll say, “Push this button” and then it will like execute some network request or maybe unviewed load, I’m going to load some data for the screen. You want to check at that moment, “Do I have a network connection?” But Reachability is an asynchronous call so you can get a callback if Reachability changed, but that’s not guaranteed to ever change. So as soon as you initialize the Reachability API, you’re not necessarily guaranteed to have a realistic answer whether or not you have network, correct? So one of the things that I’ve done is just keep like a global Reachability monitor in the app and just consult that. That way, if app start up, I maintain the state of Reachability callbacks. Is that something that you guys do? Or, is there a different way you handle that? ANDREW: That’s the same approach I’ve taken, so I have nothing to add [unclear]. ROD: Yeah. JAIM: I do the same thing. I do the same thing. CHUCK: What do you do in the case where you do a Reachability test or whatever you verify that your server is there and it can connect, and then mid-response, it goes away? So you only got half of the response, and you don’t really know if it’s going to come back or not. BEN: In that case, you will get the failure callback in Reachability so you can mark your own flag as “I’m offline now”. And then the request that’s in flight will fail, so your failure callback handler will happen and you’re probably present alert saying, “Sorry, this connection failed. Try again later.” Or, if network connection sort of gets interrupted in the middle and then comes back, by the time the failure callback happens, you should probably check if you have network connection again so that you can automatically retry the request, because there are times like me stepping in an elevator where I might have the internet interrupted for a minute, but then it will come back on its own. One of the piece of advice that I got from WWDC Session – I don’t remember which one it was, it was one on networking – the Apple engineer was saying, “If somebody is sitting there and staring at a screen, go ahead and retry the request,” you don’t necessarily have to present on alert every time a connection fails, because people realize that they fail, they realize that they’re in a tunnel or in an elevator or whatever. CHUCK: What if it doesn’t go all the way the way, but just slows down to the point where it’s pretty much useless? So you’re still getting packets in, does that trigger the Reachability? Or, does it keep [unclear] in that bandwidth? BEN: I’m guessing is Reachability just like a DNS query or a ping or whatever? I think if you can reach it, Reachability is going to say you can reach it and it’ll tell you on which radio you can reach it like reachable view at WiFi or cellular. ANDREW: Right. BEN: But it’s not going to give you any indication of speed. ROD: Right. BEN: I think it’s important to, like if you’re sitting there staring at the screen and you’re waiting for the screen to load content like if you hit the Back button to cancel current requests so that the user is no longer interested in whatever data that was. So we should stop spending any system resources trying to go get it. STEVE: Yup, that seems like a wise advice. Specifically, at Reachability, I’m not sure that any packets actually go out on the network when you configure Reachability. I think it’s all based on the routing table so when you get a cellular connection, iOs, at a very low level at a route that knows how to get to the internet through that cellular connection. So Reachability is very much a theoretical like “I believe I had a route that I can use to reach a given host, or I don’t”, but there is no guarantee that the server is up or if there’s something along the way that would keep the packets from getting more than you need to go. So it’s a very much sort of a preflight check, but there’s no guarantee it’s going to succeed. So if bytes are dribbling over an extremely slow connection, then Reachability should still tell you that you have a connection because you do. The question of whether or not it’s fast enough for the purposes that you have is really, I guess ultimately, is up to a user. BEN: Yeah. And the user I can tell whether or not they’re getting a good connection because the Network Spinner at the top will actually slow down depending on whether or not you’re getting a fast connection or a slow connection. CHUCK: Do you ever just give them like the blatant button that says, “If it takes too long to load, do you want to keep waiting or do you want to move on?” Or, do you just do that for them and intelligently decide to try again and let them know that it’s not working? STEVE: I think it depends on your app. I think it’s probably the same WWDC Session from a couple of years ago that the advice they gave at the time, which I think is really sound advice, is “You don’t know the situation that your user is in.” They could be in an elevator, they could be coming out of a tunnel; you just don’t know the situation there. So really, if you can give your user the choice to either continue to let a connection proceed or a template proceed or to cancel it or to retry, being able to make those decisions in your app, you never really know what your user wants. So giving them the control to retry and to cancel is often the best choice because only they know the situation that they’re in. CHUCK: Yeah, that makes sense. So do you just assume the screen should load within so many seconds or milliseconds and then give them a button that says “Move on”? How do you usually handle that? STEVE: I guess it depends on the app. A lot of the apps I’ve done lately, the networking tends to be sort of a background thing so the user isn’t explicitly telling it to go do stuff; it tends to be more like data is getting created and it’s getting the stuff into a Core Data store or database somewhere. And then later on, when time permits and the network is up and available, I’ll try to sync that up to a server somewhere. But if it’s something else like a newsfeed and then app or something, it’s some way to pull the Refresh maybe like in Twitter clients, or a button somewhere that lets you cancel. It just really depends on the app. PETE: I think that’s a really good point. This isn’t me being smart, it’s me listening to someone else being smart, but someone was saying that you should really change the way that your axis based on whether it’s an intentional action or a kind of a background thing. Like if you’re loading in the background and there’s a bad connection, all of a sudden you say to the user while they’re in the middle of doing something else, “Hey, the network is down!” It’s like, “I don’t care right now, thank you.” But if the user is explicitly down to pull to refresh, then you want to show it that you’re doing some loading and you want to tell them that their explicit action has failed. BEN: Amen. STEVE: Yup! JAIM: And you don’t want to be reading like halfway through an article and say, “Your network is down,” like, “I don’t care right now.” PETE: That’s my pet – absolute most irritating thing about my iPhone is when I’m halfway through, I’m like using the iPhone and I’m scrolling for something, and that freaking WiFi notification comes up and says, “There’s 17 locked private WiFi networks near you. Would you like to try and go one a night,” and I accidentally tap on one. [Laughter][crosstalk] PETE: Yeah. BEN: That’s like the first thing I turn off. PETE: I don’t know why…I’m going to turn off right now. [Laughter] JAIM: That happened to me driving to a neighborhood once. I’m like, “What?” PETE: It happens to me all the time. BEN: [Chuckles] You got to be useful for about 4 seconds. PETE: You know what, though, it’s useful for finding out what buses are nearby. The Google Bus always shows up on my WiFi – it’s the GBus. So maybe I will turn it off. CHUCK: It’s always fun looking at the WiFi in my neighborhood and trying to figure out which neighbor is which WiFi. ANDREW: There is some terrible WiFi networks around here like names that are horrible. CHUCK: My favorites are Linksys and Netgear… [Chuckles] CHUCK: I love those WiFi networks. ANDREW: Yeah, I’m not talking about that [chuckles]. CHUCK: [Laughs] PETE: I know the kind that you’re talking about; there are some of those near my house, too. [Laughter] PETE: Me and my kid are going to have a conversation as soon as he gets his first iPhone. [Laughter] CHUCK: So what are some of the gotchas with networking that you guys run into? We’ve talked about some of the connection issues, are there other gotchas that people mess up? STEVE: Oh, yeah [chuckles]. BEN: I think I was talking about cancelling request; I think this is one of the reasons why I really like AFNetworking because it’s built upon NSOperations, and NSOperations can be inherently cancelled. So if you’re just using like an NSURLConnection that use one of the black based ones, there’s no cancelling that request as far as I know. And I would say another anti-patterns’ probably any use whatsoever of NSString stringWithContentsOfURL. What do you guys think? ROD: Any other contents with URL. [Crosstalk] STEVE: Well, if there’s a bunch of them, too. ANDREW: I think the first day I started trying to write Cocoa, I wanted to pull some data from the web and I use that NSString stringWithContentsOfURL and I was just amazed of how easy it was. BEN: I know. It’s so easy and so tempting to use it. ANDREW: [Laughs] BEN: But every time I see it, I’m like, “There is just literally no good use case for it.” ANDREW: Right. BEN: People will be like, “Well, I’m just going to dispatch async and then do it.” But you have no failure callback, you have no progress, you have no cancel, like I really can’t think of a single use other than it’s easier. ANDREW: And even then you’ve got that queue tied up waiting for your synchronous request for no reason. [Crosstalk] ANDREW: Right. And NSURLConnection has synchronous request support anyway. So if you really truly want to be the synchronous request if it’s – BEN: I think if it was literally like you have to only do this once, then you should probably look into the GCD barrier blocks so that you can still have async, but nothing else runs during that time. I haven’t personally had a need for that, but the GCD WWDC video talks about barrier blocks, and that seems like it would be a better use case so you’re not tying up a queue for any period of time. ANDREW: Right. And if you’re using AFNetworking or some other NSOperation base system, you can set up the tendencies between blocks that way, too, or between operations. BEN: Maybe this is a topic for a future show, but the whole NSOperation dependency stuff, I’ve never found a use for that. Do you guys use that a lot? ANDREW: Yes, I’ve used it occasionally. BEN: One of the things I would say – I’m trying to think of a good example we can maybe describe the scenario – but once this thing is done, then I want to do this other thing. One thing we do in DeliRadio is like if you use *Band and you’re not logged in, then we prompt you to log in or sign up, but we carry along  a block or what to do when that sign up is finished so that we can * it once you have signed in. I think that that might be a good use, but we just retain the block, pass that along with the operation, and if that block is present afterwards, we execute it. So I’m wondering what are maybe some benefits of doing the dependent operations; does it get scenario where I should have looked at using dependency? ANDREW: It seems like what you just described sounds reasonable for me. But one place I’ve used it is we have a bunch of concurrent operations that are quite CPU intensive and also have a network request components. So they do a bunch of work on the CPU that takes a long time, and then they take that data and do a network request and get some data back, and then you’re done. And the data that they get back, it wasn’t to a Core Data database, and we want to save as soon as they’re all [unclear] or as soon as a certain number of them are done periodically. So we set up an operation to save the Core Data store; I see dependency of those operations. BEN: So like the input of one of those jobs depends on the output of the first job, right? So once you’ve downloaded the file, then you want to process the file, and then you want to save it or something like that. ANDREW: Sure. BEN: Why wouldn’t one operation just throw like a delegate callback and then whoever is handling that would then queue up the second operation? Because it seems like if one of them is dependent on the data from the first, then queuing it up, you’d be queuing up an operation that can’t run because you don’t have the data. I’m wondering how you even create it. ANDREW: Actually, the operations I’m talking about to do that entire thing in a single NSOperation; they do the local processing, network request, get the data back from the server, and put that in Core Data. The only thing I was saying we make dependent is the calling save on the managedObjectContext… BEN: Oh, okay. ANDREW: And we sort of [unclear] there… BEN: So they’re already kind of decoupled… ANDREW: Right. BEN: Alright. Sorry for that little drive on NSOperations. ANDREW: I actually wanted to hear Steven talk a little bit about AFNetworking and if there are any other libraries. I think somebody asks question, but it really didn’t get answered other than Reachability, but do you use AFNetworking or other third-party networking libraries? If so, what are the advantages? If not, why not? STEVE: I do use AFNetworking. At this point, I think it’s pretty much the undisputed king of the hill in terms of third-party open source networking libraries. I still use NSURLConnection directly for pretty simple things like if I only need to fetch, say, one or two URLs to grab some data dead apps start, I typically won’t retry AFNetworking just because the needs are so simple. But if I’m integrating with an API or anything on the backend that I need to do more stuff with, then AFNetworking is just the obvious choice. It’s so well-supported at this point; it’s so well-tested that it’s another one of those things where if I can use a chunk of somebody else’s code and have a very high confidence that it works and it does what it says it does, then one last thing I have to think about. JAIM: Do you use any other libraries that kind of build on AFNetworking like a RESTKit or something like that? STEVE: I don’t. I looked at RESTKit once a while back, and I forget why, but it didn’t seem particularly appropriate for my needs at the time. A lot of times, I’m sending in and consuming JSON data, and in the past, I’ve written a couple of categories that’s in NSManagedObject that will take care of serializing attributes from a Core Data object into something for JSON and then back. That’s done the job pretty well. But I know there’s RESTKit and then there was something – I can’t remember what it was – but there was something objective resource maybe I want to say. There was something a few years ago that they would integrate with Rails’ backend specifically so it fall all at the same naming conventions and we’d sort of just make everything magically hook up with very, very little effort. But I haven’t used any of that stuff myself recently. BEN: I spent a little bit of time learning RESTKit and I did 3 NSScreencast episodes on it. At the end of it all, it kind of appreciated some of the little pieces involved, but what is required to take advantage of those is really confusing. Going back over that code, it’s no longer obvious why certain things were done. I don’t know. I think there are pieces certainly that could learn from. I think the mapping is really, really powerful so you can like flatten hierarchies of JSON into like a differently shaped NSManagedObject, but I probably won’t ever use it in the shipping app. JAIM: I found that documentation kind of very powerful once you understand it, but easy to forget what those things do. BEN: One of the largest entry point into NSScreencast is in terms of searches because there’s no documentation so there’s like a Stack Overflow question like, “Anybody using RESTKit, too?” and like tons of traffic coming into that episode because I’m apparently the only resource of RESTKit, too. I had to figure all that crap myself, which was frustrating without any documentation. So a lot of people email me asking questions about RESTKit, I’m like, “I am not at all an expert. I just figured out enough to cover the topic.” Anyway, it’s interesting that it’s kind of a useful idea. But in practice, I think it’s too complex. JAIM: Yeah. And they can put to change the API perform version 2. So most of the stuff that you see on the Stack Overflow is not quite up to date, and almost useless. STEVE: That is frustrating. CHUCK: Yeah, but if the API gets better, then I guess you can argue whether or not the tradeoff is worth it. JAIM: Yeah. I used it heavily on my last project, and it was very powerful; once you kind of get the corks, I could wire up a new end-to-end point in like 20 minutes and it’s ready to go and it got my JSON objects, and I can go. In that case, once you kind of figured it out, it worked pretty well. CHUCK: So do you guys do much logging of network request in response, or only in the context of having to debug something? STEVE: I constantly. One of the things about networking that makes debugging such a frustrating experience at times is that we test things in our desktops, in our WiFis, in our offices, and then we get out in the real world and things are very different. It’s not even a series of steps. If a user in the field has a beta version of our app or even a production version and they say, “I did this, this, and this,” and you can do that network just fine, it’s because where they were, their network was a little wonky, and a request failed and we didn’t handle it properly, that’s why they’re having problems. So I found that logging is critical to debugging those kinds of issues. BEN: Yeah, but you probably shouldn’t ship with your NSLogs visible because anybody could just plugin their phone and see request and response. Not that it’s really difficult to get at it for like a determined individual, but certainly, you don’t want to make things that blatantly obvious of how your API is talking to the server. STEVE: Yeah, that’s true. BEN: So I usually conditionally compile those out in Release builds. ROD: Yup, I do the same thing. Yeah. STEVE: Depending on the app, if it’s a mass market app and you’re talking about hundreds of thousands of downloads, then obviously, your support gets trickier. But if you’re building an app for business customer and you can shift somebody from an App Store version to an Ad Hoc version, then you can Instrument the build and get a lot more information out of it. BEN: Have you guys looked at Runscope at all? It’s a complete path through a proxy of your own API; it will forward all headers and whatever else parameters to the real API, but log and provide instrumentation metrics and whatever so that you can see what’s going on out in the field. That kind of gives you that same approach; you can inspect or request some responses. STEVE: What was that called? BEN: It’s called Runscope. If you had an API kind of like myAPI.com, then you would be myAPI.com.runscope.com; it’s complete passer; it’s really pretty cool technology. PETE: There goes one of my picks. [Laughter] BEN: I’m really good at this game. PETE: [Laughs] Yeah. CHUCK: [Laughs] PETE: Would you use Runscope in kind of in production, the shipping app? BEN: No, I will definitely not. I like the idea and I would love to see the data, but you’re completely dependent upon their uptime… PETE: Right. BEN: I don’t know. I’ve chosen dependencies like AWS for instance or Heroku, and they go down or whatever. But those are kind of conscious decisions that I make and the more of those types of like kind of massive dependencies you have on uptime. What if your app became as popular as Angry Bird, all of the sudden, they have to have the scaling to support that? I don’t know what their pricing models like, but they’d probably want you to not run it in production. PETE: Because they’re paying for all the backworks, right? BEN: Yeah. ANDREW: Price. BEN: Yeah. Maybe they just charge you enough to support that. But I don’t know. I know one of the founders and he’s a really smart guy and I’m sure they’re up to the task of scaling it, but you want to be in-control of your own destiny. So I think for an Ad hoc build, definitely; but not for a shipping app. [Crosstalk] ANDREW: Privacy concerns are there, too. You wouldn’t want to rat all your API calls and responses through somebody else if you didn’t have to. BEN: Right. I’m guessing they’ve got to have some sort of way of saying, “Well, this time of parameter, I don’t want you to log.” Unlike Rails for instance, it automatically filters out fields that are called ‘Password’ because you don’t want that stuff to be logged in. I’m guessing they have something similar to that so that you don’t log secrets. CHUCK: What is your Social Security number? BEN: [Laughs] CHUCK: What is your bank account number? What is your mother’s maiden name? Be back in a minute. [Crosstalk] BEN: That practice of like bank saying, “What’s your username? Let me show you an image that you picked along with a phrase,” I have no idea why they think that’s secure. That bugs the crap out of me because I were to be the spammer, I would just set up a page that looks just like it, you would type in your username, and I’ll be like, “Okay, hang on one second and let me go that page,” login as you. I don’t know. CHUCK: Download the image, yeah. BEN: Yeah! It bugs me! It’s just like you could just…anyway. ANDREW: Yeah, it’s like secret questions; they’re not really very secure. CHUCK: Yup. BEN: Most of them are public info anyway. ANDREW: Right. CHUCK: And you can socially engineer your way into the rest of the room. JAIM: So Steve, for a long time, most of what we’ve talked about network is like streaming media, or it’s getting data over HTTP either with XML or JSON, but I started doing like heavy data stuff; we’re pretty more low-level sockets – TCP, UDP, that kind of thing. Is there any use for kind of the different networking technologies for today’s app developers? STEVE: Absolutely. Most of what we do, we are talking about talking to web services so HTTP works just fine for that. But if you were to sit down and write a multiplayer game or build another mail client or something like that, then none of the NSURLConnection stuff or AFNetworking helps you at all because they’re designed to talk at web servers. So Apple has given us – we actually still have access to that Rob Berkeley sockets through Foundation Networking so we’ve got NSString and then there’s the CFString counterpart, and there’s CFSockets; we can still do all that stuff if we need to. It’s not nearly as nice as NSURLConnection is; you still have to push and pull all the bytes yourself. With the low-level stuff, if you tell it “Write a thousand bytes”, it may come back and say, “Well, I’m done, but I only wrote 500,” so you have to buffer the rest yourself. So it’s not nearly as user friendly, but they definitely give us the ability to still get down to that level if we need to. And then actually GameKit introduced some pure-to-pure networking stuff that if you’re just talking about devices in close proximity, there’s a whole API that lets you discover other devices that are running your same app, and you can get them to join a session and then you can send data packets back and forth among of the peers, and it’s really easy to use. I think in iOS 7, that work basically getting that, but rebranded under this multi pure connectivity, so it seems like it’s mostly the same API with some new additions, but the same sort of “I want to be able to discover and talk,” without actually having to dip down to the socket level. I used that a couple of years ago to do some rudimentary syncing in an iOS app, and it was great! It made that job fantastically easy compared to doing the raw sockets myself. JAIM: You know what protocol that uses under the hood? STEVE: I believe it uses either TCP or UDP, depending on whether or not you tell it that you want a reliable transmission or not. JAIM: Okay. ROD: Has anyone used WebSockets? Or, was that kind of the same thing? PETE: WebSockets is not the same…WebSockets is like trendy people rediscovering UDP. [Laughter] STEVE: Well, not quite. PETE: That was like instantly triggered my annoyance at WebSockets. WebSockets don’t scale just like Rails. [Laughter] JAIM: We need [unclear] DBE WebSockets. STEVE: I actually just [unclear] WebSockets in a production app right now, and it’s working pretty well for the use case. PETE: That’s good [unclear], what’s the use case? Maybe I can have someone that has actually used them to tell me one big irrational. STEVE: The use case that we’re using it for is we have an app that communicates to a backend and data can change on that backend in lots of different ways, not just through a single instance of the app. So you want to be able to get that data up to date on the app, but I didn’t want to have to build the app to constantly be pulling because the load on the server would scale up pretty fast as the app got popular. So WebSockets, and I’m actually using something called “faye” on the backend. WebSockets allows the app to make a single connection to the server that just stays up forever. And then as the server gets new data coming in from other sources, it can push that data down to the client through that WebSocket connection, and keep the client up to date so I can have a piece of data change on the server and it shows up in the app within a second; it’s really great. PETE: Presumably this is a web app, not a native app? STEVE: No, it’s a native iPad app, but then there are other ways to inject it into the backend that there’s a web component, there’s iPhone and Android components, so data can feed in a lot of different ways. PETE: Interesting. Has anyone of you using WebSockets on a native with a non-web browser client. JAIM: I think there are some libraries that do it with WebSockets for iOS, I can’t remember what they are. ROD: Are they socket level? Or, are you using some kind of HTTP to do that? PETE: WebSockets is technically…is it technically HTTP or is it not HTTP, that’s confusing to me. STEVE: It’s initiated over HTTP and then I believe it uses some sort of – it’s kind of like more esoteric part of the HTTP spec where you can tell the connection to shift into a slightly different mode. So they kind of shift it from HTTP into something else. At the level I’m using that out, actually I’m just jamming based on down the pipe from the server of client. Technically, it’s by directional. PETE: That use case of warning to have a connection open so that you can instantly update all of your clients when something changes, it makes sense to me. The thing that doesn’t make sense to me quite so much is having a connection open to every single client. That means (a) you’re going to run out of connections pretty soon if you’re using Ruby, and (b) website due to the battery life of the client. STEVE: So this particular application, it’s designed that the iPad would be sitting in one place for the most part. So the theory is that it should be plugged in because the app is designed to be used for 6+ hours at the time. PETE: That makes sense. JAIM: So socket rocket is the Objective C library for WebSockets. STEVE: Yeah. Then another thing called “FayeObjC” that it didn’t use socket rocket originally. The thing it did use, it’s sort of not been maintained so I forked it and I’m using socket rocket now on my fork. It’s great and it just works fabulously well. I think we’ve had it in production for like a year or 1 ½ now and we haven’t had a single problem with that component. CHUCK: Cool. Looks like that one is written by square. Any other questions or comments or bits of wisdom you want to share about this before we get into the picks? STEVE: I guess the only thing I wanted to mention is there’s an interesting list of the fallacies of distributed computing that I always talk about when I do this – I do a networking talk for CocoaConf – and it’s something that was I think originally drafted up by somebody at Sun, I believe but I’m not sure about that. It’s an interesting read of like all the things you may assume going into building a distributed system, and really were apps that talked to web services. Well, I’ll send the link out. It’s an interesting read to go through and just really to fundamentally understand how evil and how dangerous the network environment is when we sit down to use it. CHUCK: Awesome. Are you going to be speaking at any CocoaConfs coming up? STEVE: I am. We have another CocoaConf here Columbus in a week and a half. I think this would be the third one CocoaConf. I believe it originally started here in Columbus and they’ve come back the last 2 falls so we’ve got another one coming up. But I’m really, please, that Apple listen to my please to release iOS 7 so that I can talk about some new stuff this year. CHUCK: Awesome. Alright, well, let’s go ahead and do the picks then. Andrew, why don’t you start this off this week? ANDREW: Sure. I have 2 picks. The first is kind of an article, it’s really a summary of some other people’s stuff by Michael (I don’t know how to say his name) Tsai about possible performance implications of using art. I just thought it was interesting because I think the line from Apple and the general has spent that ARC – among its many other benefits can produce performance improvements and this is sort of counterpoint to that. It’s just an article called “ARC vs. MRC Performance”. I think anyone, even the people who are bringing this up would say it’s not a reason to ditch ARC – there are a lot of benefits to ARC – I’m not saying that, but I just thought it was interesting to know about. Then second one is actually an article on the verge about Siri and sort of the history, and the girl in that Siri, “Machine learning” but natural language processing that I thought was interesting. I don’t know if too many people know, but Siri actually started – Siri was an app that was on the App Store before Apple bought it and that was a project from the SRI, Stanford Research Institute. It’s surely interesting technology and an interesting history of the company, and how does she learning language processing in general.  There you go. BEN: Is Siri still in beta? ANDREW: No, it’s officially out of beta as of tomorrow, iOS 7. CHUCK: Who do you think they are, Google? ANDREW: [Laughs] Yeah. BEN: Well, when they launched it, it was 6 there like, “Yeah, it’s in beta.” ANDREW: Well, iOS 5. ANDREW: Oh, yeah. It’s been a long time, and it was kind of weird because Apple doesn’t really stings at their beta. But Siri did. ROD: Yes, no longer on the web page; no more beta. BEN: Maps certainly didn’t have the beta moniker at all. CHUCK: [Laughs] Are you crying about that? BEN: Perhaps. I live in Houston and it was pretty darn accurate here, but I recognize that other places were not so fortunate. CHUCK: Yeah, the maps on my iPhone got me lost a few times. Ben, what are your picks? BEN: I have 3 picks today. One of them client came by the office and dropped off a package of hue light bulbs, the “Phillips Hue” they’re WiFi enabled then you can change the color and color temperature and saturation and brightness, and it’s got a programmable API. They said “Do something cool with it,” so I grabbed the “hue gem” by Sam Soffes and I had to modify a little bit to use UPnP’s assess DP simple service device protocol or something like that in order to discover the bridge IP address of the unit. Once you do that, you can just use the command-line to set the color, temperature, or whatever. We hooked this up to our Jenkins build so now we have like a deep-rich-red lamp when the build is broken, which is pretty awesome. ROD: Or make it green one; breaking band is on or something. [Laughter] BEN: We have 2 others we’re trying to find GUIs for them. They’re a little pricey, but it’s pretty fun. It’ll only take an hour or so to get it up and running with a Ruby API. So that was pretty cool. And then my last pick is “CopyPasteCharacter.com”. If you are looking to paste like the Alt symbol on the Mac or the Command symbol or some of these other symbols that are not frequently used or easily accessible on your keyboard, you can go there and just copy and paste it from that site. CHUCK: Awesome. ANDREW: There’s also a – if I can rift off that a little bit – there’s also kind of cool little web app that was written by Neven Mrgan, the designer of Mechanic, called “Glyphboard”, sort of similar thing. I don’t know if it has the Alt symbol, but it’s meant to be an app that you add to your iOS homescreen so it’s one of those rare made it looking web apps for iOS. BEN: Yeah, that’s cool. CHUCK: Nice! Jaim, what are your picks? JAIM: My pick today is a “Lawyer” or “Lawyers” in general. [Laughter] JAIM: I used to be of the opinion that lawyers are like hand guns; you don’t really need one unless the other guy has one. But I found them, especially if you’re independent developer like me, so you have someone on your court and your side that can look over things before you sign them, and I’m finding out that they can be very valuable and keep you out of a lot of trouble. So rethink your possible opinion on lawyers. CHUCK: So true. Pete, what are your picks? PETE: I had one pick that someone stole from me… [Laughter] BEN: Sorry. PETE: I won’t name names. So “Runscope” is going to be one of my picks, we’ve already talked about that. And I was at Tech Ranch last week and a very cool stuff up there – actually it’s really cool [unclear] called “Estimote”. These guys are making these little i-beacon things – have you guys heard of i-beacon? ROD: Yes. PETE: It’s this low-powered Bluetooth thing that is coming out in iOS 7. I never even heard about it until I saw these guys. It’s a really cool technology, you can get this developer kit from them from $99 box which includes 3 little Estimote things which are made of soft silicons so they’re very fun to fundle while you’re talking to the guys at Estimote at their booth, a little side bar. My third pick is a beer pick; I’m going to pick “Acme Pale Ale” from North Coast Brewing. It is very good. Almost every beer from North Coast Brewing is very good, but the particular one I’m going to pick this week is Acme Pale Ale. And then my last pick is a game called “XCOM Enemy Unknown”. BEN: Yes. PETE: Yeah. If you’re at my age, then you may have played the original version of this, which came out like 10 years ago or 20 years ago, long time ago. They basically remade the game; it’s almost the exact same mechanic, the same awesome game, but with awesome graphics using unrail, something rather graphics. So it’s like awesome 3D graphics, but the same original game. It’s like, in my mind, the perfect game remake where you have all of the fun that it actually is you have kind of hazy memories of what the graphics look like or actually in hearts into like awesome modern graphics artist. So XCOM Enemy Unknown is my next pick. BEN: You’re playing that on the iPad? Or, on the Mac? PETE: I got a new work laptop so I have this tiny little 11” MacBook which I use for all of my work and no one believes me, but I really do. And then I got this like big honking MacBook Pro with rest in the display from my company, the only thing I’ve used it for is playing XCOM. [Laughter] CHUCK: Nice. BEN: I bought XCOM on the iPad and it’s nice. I like the touch controls, but it’s not quite as fluid as I would expect an iPad app to be. The other thing is it’s not very friendly to just like quitting out and doing something else because you actually have to save your game, which I thought was really weird. PETE: Yeah, that’s weird. BEN: I bought it; it was like $20 on the iPad. I guess it’s the same on the Mac App Store or at Steam. PETE: It’s like more expensive on Steam. BEN: But it is definitely fun to play; I just wish it was more like friendly to the I-have-to-go-do-something-let-me-just-quit or multitask or whatever. CHUCK: Awesome. Sounds like fun! PETE: It is. CHUCK: [Laughs] Alright, I’ve got a couple of picks. My first pick is another shameless self-promotion; I’m going to be speaking at “RubyConf” this year. So if you want to learn about some Ruby and enjoy some Miami Beach, then go sign up at RubyConf.org. While booking the trip, I actually was looking at “AirBnB”, and I found several places that are whole lot cheaper than a hotel. So I’m going to pick them as well. I’ve used them once or twice before, and I always had a good experience with it, so AirBnB.com is my second pick. My last pick is more along the lines of marketing and business. There’s a fellow out there named Michael Hyatt, he has podcast called This is Your Life, but he also has a paid membership site called “Platform University” because he wrote a book called Platform. It talks about building your platform and using it to make sales for business and things like that. I highly recommend it. He just raised the price to $30 a month, but it’s well-worth every penny. You can get that at PlatformUniversity.com. Steve, what are your picks? STEVE: I have 2 picks. The first one, I’m going stick with the theme of the show and it’s “Little Snitch”. Little Snitch is a little application that you can install on your Mac that will actually monitor outgoing network connections. It’s kind of got 2 menus for me. The first is that I’m naturally curious and I like to know what other apps are trying to do on my machine behind my back, so this actually tells me and it gives me the option to block or allow kind of consoling app by app basis and then to a particular host. The other useful that I have for it is that, since I also do a lot of Rails backend work, it’s very handy for actually speeding up integration test because I can actually block outgoing connections to things like a W tight kit or edge fonts so that it’s not bothered and actually going pull that data across for a test that doesn’t need to use it. That was my first one. My second pick is not computer-related, and it’s “UptonTea.com”. Upton Tea is a tea company. I sort of back the trend on coffee and nerds because when I first started working in the Valley about 15 years, maybe more, startup companies bought decent coffee, but almost nobody there seem to know how to make it properly. I found that loose leaf tea was a much better way of getting my caffeine fixed without having to drink something that was brewed by someone who didn’t know what they were doing. That’s my second pick. CHUCK: Awesome. Well, thanks for coming on the show Steve, it was a pleasure to have you and – ROD: Don’t forget my picks. CHUCK: Oh, did I not let you go, Rod? ROD: Nope. BEN: Burn. CHUCK: [Laughs] Rod, what are your picks? ROD: Alright, my first pick is a talk around across the internet called “Clojure: Enemy of the State”  and it’s about how functional programming teaches data, treats data, and how to mutable versus [unclear] and all that stuff. It’s the first video that kind of let me see how the functional approached the data might be better than the object during end approach. So I found that very interesting. My second will be “myself”. I’m looking for full-time work or contract work in Salt Lake or if you’re open to remote work anywhere. So that’s it. CHUCK: Alright. Now we’ll wrap up the show. Thanks for coming, Steve. STEVE: Thanks for having me. BEN: Yeah, thanks! CHUCK: Alright, well, we’ll look forward to show next week!

Sign up for the Newsletter

Join our newsletter and get updates in your inbox. We won’t spam you and we respect your privacy.