• Nintendo Switch Review

    Nintendo Switch

    The Nintendo Switch is the first games console I’ve owned in years, the last was a Nintendo Wii that I shared with my brothers. I bought it last year on a whim when I was living in a flat where I had no TV and I wanted some games to play other than League of Legends. Since then I’ve spent hundreds (yes hundreds) of hours playing various games and thought it would be worth writing about my experience with it.

    Design

    I love the size, feel and appearance of this console. It is both perfectly sized and perfectly weighted. The controllers - Joycons - feel great in your hand. When playing with them detached from the console they can be a little small in the hand. There are small slide on grips that make them a slightly better fit, but I never bother with these as I love to be able to drop the Joycons back onto the console in a moment.

    My biggest criticism of the console hardware wise is the quality of the screen, which is fairly dark and plastic-y. It would be cool to see how good the screen could be if the Switch wasn’t limited by hitting a price point. It certainly wouldn’t be as popular and accessible as it is - but I think it would be cool to see.

    Battery Life

    The battery life on the Switch is reasonable. I believe that it’s rated to last around 3 hours on a charge for most games, which I think is fine. There is rarely a case where I want to play for any longer. Whenever I’m not playing I leave the Switch in its dock which means that it’s always charged and ready to go when I pick it up.

    Nintendo, brilliantly, included a USB-C charging port on the switch. This is great for many, many reasons which you can read about elsewhere. But the key thing to note is that I can charge this using any battery pack or directly from my laptop, which is great when traveling, which this console excels at doing.

    Software

    The operating system on the Switch is also brilliant. I haven’t used other modern consoles extensively, but I do know that they are cursed with long load times. The Switch OS wakes from sleep as fast as any modern smartphone and moving around the system is equally as fast. There are sound effects with most button movements which aren’t annoying - an achievement in itself.

    Beyond the speed of the system, there are some things that certainly would be nice to have. The Switch comes with screenshot functionality built in, but these screenshots are incredibly awkward to get off the device - you only get the option to share to Facebook or Twitter. It would also be great to be able to have a media player on the Switch that you could sync stuff to remotely. I would love to be able to chuck films and things on it and watch them on the go. No device can switch between being portable and being on your TV like the Switch can, and I would love to be able to utilize this ability further.

    Nintendo Switch

    Games

    Games on the Switch are great. I don’t think there’s a game I’ve bought that I regret purchasing. Here’s a quick list of my favourites.

    • The Legend of Zelda, Breath of the Wild
    • Splatoon 2
    • Snipperclips
    • Rocket League
    • Mario Kart 8 Deluxe
    • Doom

    I’m currently eyeing up the new Donkey Kong game which I keen to buy as soon as Nintendo stop charging £50 it.

  • Peak Design Everyday Backpack Review

    Strap on carry

    I’ve had the Peak Design Everyday Backpack for a year and a half. I backed it on Kickstarter and waited 6 months for it to arrive, running my already tired Herschel Supply Co bag into the ground in the process. I’m hoping it’s the last backpack I buy. It comes with a lifetime warranty and 18 months on it’s still solid.

    Munro

    Perhaps my favourite thing about the bag is just that it feels great - it is made from a sturdy water-resistant material that provides it a solid shape; the straps are made from the same material as seatbelts and can hold any weight your through at them with ease; the back of the bag sits firmly, assuringly against your back; and the inside of the bag is made from a soft material that I feel happy throwing my camera inside. There are very few bags that blend utility with aesthetics like this bag does.

    Speaking of utility, this bag can do everything. There’s a reason that Peak Design call it the everyday backpack. The inside of the bag is one big space that is separated by flex fold dividers. These are like you’d expect to find in a camera bag but a hundred times better. They are slim rather than bulky, they are easy to move around and they can be folded up or down to create little compartments in your bag to keep your stuff separated. This is extremely useful when you have a bunch of stuff in your bag. My camera has its own space on the right hand side, if I’m grabbing shopping on my way home then it stays in the top of the bag, kept tidily away from everything else. When you need to get something out of the bottom of your bag, you just turn it on its side and reach into that compartment. There are also two expanding side pockets that I use for my bike D-lock and for a water bottle, The laptop compartment is completely separate to the rest of the bag and can be accessed at the back of the bag. It can take a 15” MacBook Pro, an iPad and some charging cables. When you have filled up the insides of the bag, there are a number of straps and anchor points on the outside of the outside of the bag that you can pull out at any time to strap stuff to your bag. I use these for carrying all sorts of things that a regular backpack could not do. I’ve strapped on clothes, boxes of cereal, packages that I have had delivered to my office, my bike helmet and even a pack of three pillows.

    Munro

    The only wish I had for this bag was that it was bigger. Peak Design do make a 30L version of this bag but it looks bulky and unwieldy compared to the 20-litre model. Since buying it 18 months ago, I have been using this bag every day, it has been brilliant.

  • Fresh Pasta

    A couple of months ago I first made fresh pasta and was amazed at how easy it was to do - it requires just two ingredients and can be done in 15 minutes. In the summer my Mum’s hens lay more eggs than she knows what to do with at times and this is a delicious way to make use of them.

    Pre roll

    + 175g 00 flour
    + 2 medium eggs (the fresher the better)
    + 25g fine semolina (or 25 more grams of flour)

    If you don’t have any eggs or want to make vegan pasta, you can simply swap the eggs for 200g of water.

    The method is to simply mix the ingredients together, then wrap in clip film and refrigerate for at least 30 minutes before rolling out and cooking. To mix the ingredients you can either use your hands (takes around 10 minutes) or blitz it in a food processor for 30 seconds. At first, it seems like the dough will not come together, but just keep mixing - it will get there eventually.

    After refrigerating, you just need to roll out your pasta into whatever shapes you like. The easiest is most likely tagliatelle - you just need a rolling pin, a knife, and some elbow grease. You can also get a pasta roller for fairly cheap which will roll your sheets out in seconds.

    Rolling

    Pasta cut

    Pasta cut

    One last thing to note is that fresh pasta cooks much quicker than dried pasta - if you chuck this in this boiling water, it’ll be ready within 5 minutes. Also, you can leave the dough in your fridge for up to a week before using it.

    Pasta cut

    My carbonara skills aren’t quite where I want them to be yet - I’m prone to scrambling the eggs when mixing everything together - but the flavor is that of some of the best pasta that I’ve had.

  • Animating Tab Bar Controller Taps

    Following on from my previous animation posts (here and here), this post is about animating the taps on an iOS tab bar - an effect used by Spotify in their app. UITabBarController is an old piece of UIKit that draws its architecural design from AppKit. Configuring your tabs requires you to use UITabBarItem, you have no access to the internal UIBarButton class. Because of this, we have to use some less than ideal valueForKey method - however, in this case I feel this is OK as there is no crticial operation relying on it, just an animation.

    For this effect, we also must subclass UITabBarController as we require access to the didSelectItem method, the only available method for UITabBarControllerDelegate is the didSelectViewController version. You could perhaps look at the tabBarItems of a UITabBarController and look at its subviews and try and relate the two, but I imagine that it is unlikely you can guarantee that they will be equally ordered.

    The next best option I can think of is to roll your own version of UITabBarController where you control all the views and touch events and can do all the animation you want. But, if a subclass and short solution suits you, then read on.

    class AnimatedTabBarController: UITabBarController {
    
        override func tabBar(_ tabBar: UITabBar, didSelect item: UITabBarItem) {
            guard let barButtonView = item.value(forKey: "view") as? UIView else { return }
            
            let animationLength: TimeInterval = 0.3
            let propertyAnimator = UIViewPropertyAnimator(duration: animationLength, dampingRatio: 0.5) {
                barButtonView.transform = CGAffineTransform.identity.scaledBy(x: 0.9, y: 0.9)
            }
            propertyAnimator.addAnimations({ barButtonView.transform = .identity }, delayFactor: CGFloat(animationLength))
            propertyAnimator.startAnimation()
        }
        
    }
  • Animating UICollectionView or UITableView Cell Touches

    Following on from my previous post about the animation of UIButtons, I wanted to look at animating UITableView or UICollectionView cell touches. This effect is used in the AppStore on the Today page alongside a great transition delegate for opening and closing articles.

    I’m fairly happy with how this implementation works but will need to some more testing on a device to finalise the ‘feel’. Also, I would not be surprised if there is a simpler way of doing this. This here has been my first stab at it, and if I come up with something better I will be sure to post an update.

    To create this effect I used a UILongPressGestureRecognizer.

    let longPressRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(didTapLongPress))
    longPressRecognizer.minimumPressDuration = 0.05
    longPressRecognizer.cancelsTouchesInView = false
    longPressRecognizer.delegate = self
    collectionView.addGestureRecognizer(longPressRecognizer)

    We then need to conform to UIGestureRecognizerDelegate and implement the following method. If you have other gesture recognizers for this delegate then you will likely need more logic here, but for this simple example we are just going to return true all the time.

    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
        return true
    }

    Now for handling that gesture recognizer.

    @objc func didTapLongPress(sender: UILongPressGestureRecognizer) {
        let point = sender.location(in: collectionView)
        let indexPath = collectionView.indexPathForItem(at: point)
            
        if sender.state == .began, let indexPath = indexPath, let cell = collectionView.cellForItem(at: indexPath) {
            // Initial press down, animate inward, keep track of the currently pressed index path
                
            animate(cell, to: pressedDownTransform)
            self.currentIndexPath = indexPath
        } else if sender.state == .changed {
            // Touch moved
            // If the touch moved outwidth the current cell, then animate the current cell back up
            // Otherwise, animate down again
            
            if indexPath != self.currentIndexPath, let currentIndexPath = self.currentIndexPath, let cell = collectionView.cellForItem(at: currentIndexPath) {
                if cell.transform != .identity {
                    animate(cell, to: .identity)
                }
            } else if indexPath == self.currentIndexPath, let indexPath = indexPath, let cell = collectionView.cellForItem(at: indexPath) {
                if cell.transform != pressedDownTransform {
                    animate(cell, to: pressedDownTransform)
                }
            }
        } else if let currentIndexPath = currentIndexPath, let cell = collectionView.cellForItem(at: currentIndexPath) {
            // Touch ended/cancelled, revert the cell to identity
            
            animate(cell, to: .identity)
            self.currentIndexPath = nil
        }
    }

    Here, I am handling three different ‘states’ for the gesture recognizer. If we a touch began, then so long as that touch was on a cell, we animate the cell. If a touch moved outside a cell, we animate it back to normal, if it move back inside the cell, we animate to pressed again. Finally, if the touch ends or is cancelled, then we animate back to normal.

    You might notice as well a couple of new variables here being used.

    var currentIndexPath: IndexPath?
    let pressedDownTransform =  CGAffineTransform.identity.scaledBy(x: 0.98, y: 0.98)

    ‘currentIndexPath’ is just a reference to the index path of the cell that was pressed down. The transform is being stored as an instance variable simply to avoid redoing the scale everytime the gesture recognizer is called.

    Now the only missing piece is the animation function. This is very simple and acts much like the one I used in my animating UIButton post.

    private func animate(_ cell: UICollectionViewCell, to transform: CGAffineTransform) {
        UIView.animate(withDuration: 0.4,
                        delay: 0,
                        usingSpringWithDamping: 0.4,
                        initialSpringVelocity: 3,
                        options: [.curveEaseInOut],
                        animations: {
                        cell.transform = transform
            }, completion: nil)
    }
  • Animating UIButton Presses In Swift

    Animation can vastly improve user experience in an application. I love buttons that animate and give you the feeling that you are actually pressing something. These combined with the great TapticEngine APIs (UIFeedbackGenerator) can completely change the way your application feels.

    Here are a couple of ways of doing button animations in Swift - both of which utilise UIButton addTarget methods.

    Vanilla UIKit Method

    extension UIButton {
        
        func startAnimatingPressActions() {
            addTarget(self, action: #selector(animateDown), for: [.touchDown, .touchDragEnter])
            addTarget(self, action: #selector(animateUp), for: [.touchDragExit, .touchCancel, .touchUpInside, .touchUpOutside])
        }
        
        @objc private func animateDown(sender: UIButton) {
            animate(sender, transform: CGAffineTransform.identity.scaledBy(x: 0.95, y: 0.95))
        }
        
        @objc private func animateUp(sender: UIButton) {
            animate(sender, transform: .identity)
        }
        
        private func animate(_ button: UIButton, transform: CGAffineTransform) {
            UIView.animate(withDuration: 0.4,
                           delay: 0,
                           usingSpringWithDamping: 0.5,
                           initialSpringVelocity: 3,
                           options: [.curveEaseInOut],
                           animations: {
                            button.transform = transform
                }, completion: nil)
        }
        
    }

    If you are not using RxSwift or RxCocoa, this method should work just as well. The only downside is that you once a button becomes animatable, you have no way of making it un-animatable.

    RxSwift + RxCocoa

    This is my preferred method of making generic animations. The benefit of using RxSwift is that you start and stop animating button presses - should you wish to - simply by disposing the DisposeBag that you pass in. It also avoids you having to @objc expose your control event methods.

    import RxSwift
    import RxCocoa
    
    extension UIButton {
        
        func animateWhenPressed(disposeBag: DisposeBag) {
            let pressDownTransform = rx.controlEvent([.touchDown, .touchDragEnter])
                .map({ CGAffineTransform.identity.scaledBy(x: 0.95, y: 0.95) })
            
            let pressUpTransform = rx.controlEvent([.touchDragExit, .touchCancel, .touchUpInside, .touchUpOutside])
                .map({ CGAffineTransform.identity })
            
            Observable.merge(pressDownTransform, pressUpTransform)
                .distinctUntilChanged()
                .subscribe(onNext: animate(_:))
                .disposed(by: disposeBag)
        }
        
        private func animate(_ transform: CGAffineTransform) {
            UIView.animate(withDuration: 0.4,
                           delay: 0,
                           usingSpringWithDamping: 0.5,
                           initialSpringVelocity: 3,
                           options: [.curveEaseInOut],
                           animations: {
                            self.transform = transform
                }, completion: nil)
        }
        
    }

    This bit of Rx revolves around mapping button events to an animation state. For touch-down or touch-drag-enter events, we want to animate the press down action of the button, this ‘pressed’ state is represented by CGAffineTransform.identity.scaledBy(x: 0.95, y: 0.95). For all other touch events we want to animate back to the identity (the default) transform. For more info on how transforms work, check out this article by HackingWithSwift. These transform mappings are both merged and subscribed to the animate transform function which simply calls the animateTransform function whenever a new event is received.