Tech

Breaking labeled scopes

2 min read

break is used to exit the current scope, for example a for loop:

for i in 1...10 {
	guard i < 9 else { break }
	// Code here.
}

But what if we have nested loops, and we want to break a specific one? Swift has us covered, with labels:

outer: for i in 1...10 {
	inner: for j in 1...10 {
		guard i < 9 else { break outer }
		guard j < 8 else { break inner }
		// Code here.
	}
}

But today I found something interesting: you can label if blocks, as well:

// Works with non optional binding ifs as well.
abCheck: if let a = b() {
	guard a.condition else { break abCheck }
	// Code here.
}
Continue reading →

Assign if not nil; if nil, then assign

1 min read

I always found Ruby's ||= operator interesting, which says (roughly) assign the right hand side to the left hand side, if the latter is nil (or false). But what about assigning the right hand side to the left hand side, if the former is not nil?

Here's my take on these two, with rather intuitive operators (if you ask me, of course):

infix operator ??= // If left is nil, then assign
func ??=<T>(lhs: inout T?, rhs: T?) {
	guard lhs == nil else { return }
	lhs = rhs
}
 
infix operator =?? // Assign if right is not nil
func =??<T>(lhs: inout T, rhs: T?) {
	guard let rhs = rhs else { return }
	lhs = rhs
}

Now we can write:

var s1: String? = nil
var s2 = "s2"
 
s2 =?? s1 // s1 is nil, nothing happens
s1 ??= "first" // s1 is nil, assigns the string to it
 
s2 =?? s1 // s1 isn't nil, assigns s1's value to s2
s1 ??= "second" // s1 isn't nil, nothing happens

Vertical scrolling parallax

12 min read

If you're using WhatsApp, you probably saw the images have a small parallax effect, in the opposite scrolling direction. This gives the impression that the image is on a deeper level, and the "image container" is a window: if you climb on a chair, it's as if you lowered the window (you scrolled down), and now you can see more of the landscape below the window (it scrolled up); and crouching would have the opposite effect.

One of the biggest downsides to this, is that you need to force your image to be bigger than what the user sees: if you want to have a +/- 10px movement, you need to make it 20px taller, and wider by an amount that would keep the ratio the same.

Continue reading →

Thinking outside of the box

4 min read

Recently, I stumbled upon a small problem: we have a product details controller which calls a factory method that creates a view with a few UITextViews that detect a website, a phone, and an address, respectively, but the latter was not working reliably. Said method only needs the product object to be passed in to properly create the view.

One simple solution would have been to also pass the controller as the target, and a local method as the selector, replace the UITextView with a button, set its title to the address and its target & action to the passed in params. Then, inside the product details controller we'd have access to product.mapUrl, which points to Google Maps.

Continue reading →

Slightly easier Core Data manipulation

5 min read

Working with Core Data is getting easier and easier, but there are a couple of improvements I'd like to talk about, and I'd like to start with the auto-generated, generic NSFetchRequest. It's a step in the right direction, but the problem is that trying to use it without explicitly declaring its type won't work:

class ProductModel: NSManagedObject { }
 
let request = ProductModel.fetchRequest() // <- Ambiguous use of fetchRequest().
let request1: NSFetchRequest<ProductModel> = ProductModel.fetchRequest() // <- Works properly.

Update, Oct 10, 2017: It has been solved, all of this is now redundant. Yay!

Continue reading →

LTHRadioButton

2 min read

I was in need of a radio button recently, and it had to be designed like a Google Material Design radio button. Nothing too fancy, but I wanted to spice it up a little bit, by adding a nice animation. The idea was to:

  • start with a gray border, with an empty center
  • fill the center inwards with a blue color
  • slightly increase its width
  • as it reaches max width, release a wave outwards
  • reduce the center's width back to normal
  • color the gray border blue, as the wave passes "over" it
  • fade out the wave and reduce its width as it moves out

This is the result:

Continue reading →

Adding string attributes slightly easier

2 min read

Say we have a composed string that looks like this:

let date = "22 July, 2017"
let value = "€ 148"
let quantity = 5
let string = "\(quantity) of your items, in value of \(value), have been delivered on \(date)."
// 5 of your items, in value of € 148, have been delivered on 22 July, 2017.

It would be nice to emphasize the important bits, and the usual approach would be to create an NSMutableAttributedString, and to add the required attributes:

let attributedString = NSMutableAttributedString(
  string: string,
  attributes: [
      .font: UIFont.systemFont(ofSize: 14)
      .foregroundColor: UIColor.gray
  ]
)
Continue reading →

Combining protocols

2 min read

Let's say we have a controller that can fetch some data. What would this imply? A loading spinner, the fetching of the data and the update of the UI. We can create a protocol for this, maybe Fetchable:

protocol Fetchable {
  
  func showSpinner()
  func fetchData()
  func updateUI()
  
}
 
[...]
 
class Controller: UIViewController, Fetchable {
  // showSpinner, fetchData and updateUI are required.
}

But showing a spinner and updating the UI could be useful by themselves, so we could extract those into separate protocols:

protocol Loadable {
  func showSpinner()
}
 
protocol Fetchable {
  func fetchData()
}
 
protocol UIUpdateable {
  func updateUI()
}
 
[...]
Continue reading →

Queueing up async jobs

3 min read

I recently had this problem: at the start of the app there's a call to fetch some reference data, on which other calls depend, but it shouldn't hinder the app launch itself, nor anything else that doesn't depend on it. So, after several approaches, I decided to use DispatchGroups.

First, a struct to abstract a DispatchQueue and a DispatchGroup:

struct Queue {
 
  let group = DispatchGroup()
  let queue: DispatchQueue
 
  init(label: String) {
    queue = DispatchQueue(label: label)
  }
 
}

This class should have a way to add a closure to the queue, that won't require waiting, basically just abstracting async(execute:):

Continue reading →