How to built a Control Center layout with 25 lines of Swift code

Control Center using GridLayout

Recreating a layout similar to Control Center is easy with GridLayout, a library that uses AutoLayout to organize view in a grid like layout.

The key to building this layout is seing it as a grid with 4 equal columns and 6 equal rows. Placing items on the grid is then a matter of picking the right column and row and the right column span and row span.

    func buildControlCenter() -> UIView {
        var items = [GridItem]()
        items.append(GridItem(buildPanel(), position: Position(rowSpan: 2, columnSpan: 2), margin: 8).stretched())
        items.append(GridItem(buildButton(), margin: 12).stretched())
        items.append(GridItem(buildButton(), row: 1, margin: 12).stretched())
        items.append(GridItem(buildButton(), column: 1, margin: 12).stretched())
        items.append(GridItem(buildButton(), row: 1, column: 1, margin: 12).stretched())
        items.append(GridItem(buildButton(), row: 2, margin: 12).stretched())
        items.append(GridItem(buildButton(), row: 2, column: 1, margin: 12).stretched())
        items.append(GridItem(buildButton(), position: Position(row: 3, columnSpan: 2), margin: 12).stretched())
        items.append(GridItem(buildButton(), row: 4, margin: 12).stretched())
        items.append(GridItem(buildButton(), row: 4, column: 1, margin: 12).stretched())
        items.append(GridItem(buildButton(), row: 5, margin: 12).stretched())
        items.append(GridItem(buildButton(), row: 5, column: 1, margin: 12).stretched())
        items.append(GridItem(buildPanel(), position: Position(column: 2, rowSpan: 2, columnSpan: 2), margin: 8).stretched())
        items.append(GridItem(buildButton(), position: Position(row: 2, column: 2, rowSpan: 2), margin: 8).stretched())
        items.append(GridItem(buildButton(), position: Position(row: 2, column: 3, rowSpan: 2, columnSpan: 2), margin: 8).stretched())
        items.append(GridItem(buildButton(), row: 4, column: 2, margin: 8).stretched())
        items.append(GridItem(buildButton(), row: 4, column: 3, margin: 8).stretched())

        return UIView.gridLayoutView(items: items,
                                     rows: [.fill, .fill, .fill, .fill, .fill, .fill],
                                     columns: [.fill, .fill, .fill, .fill])
    }

You can find the entire sample on GitHub.

If you haven’t already, give GridLayout a try, it can save you time when building complex layouts.

I use GridLayout in several of my games. If you would like to check them out, visit my website.

5 Rules for Creating App Screenshots

Screenshots are one of the crucial ingredients contributing to the success of your app.
Great apps have great screenshots and Store assets. The purpose of the screenshots is to communicate the strong points of your app. Imagine having a pitch your idea in person to someone in person. The sentences you use to describe your app should be the inspiration for your screenshots.

1. Screenshots should surface your content using a compelling narrative

The screenshots should be accompanied by short 3 to 5 words sentences. These sentences should either summarise the focus of the screenshots or tell part of the app story.
Remember: users are motivated by stories and convinced by compelling graphics.

2. Use your best screenshot first

First impressions matter so make good use of the first screenshot slot. Ask yourself If the user only looks at one screenshot, what screenshot should that be? Assume you have only one chance to convince the user and focus on capturing the essence of the app in the first screenshot.

3. Avoid using screenshots of the user interface

Screenshots of settings, options, about us or similar supporting views should not be captured in screenshots. If possible you can even remove elements of the user interface from the screenshots to avoid distracting the user attention. (E.g. remove a distracting back button if it sits on top of aesthetically pleasing content before taking the screenshot). Feel free to break this rule if the user interface is award winning or designed by a renowned artist.

4. Use all available screenshots slots in the Store

If the app does not offer a lot of content use the screenshots for telling a story instead.

E.g.

  • A weather app that only has only a view that displays the weather in your current location, and does not allow seeing the forecast or the weather in other locations: take screenshots during different time of the day and in differ physical locations. Use 3 to 5 screenshots to show the main view with different content while explaining to the user the ideal use case for the app.

  • A note taking app with only one view should focus on how the app can be used instead of enumerating features. The main features of the app should be obvious from the usage scenario.

5. The last screenshot should either be memorable or contain a call to action

Use one of the most attractive screenshots as the last screenshot along with your tag line. Alternatively, use a call to action to instruct the user what to do next.

Rules can only get you so far. To really stand out, feel free to take creative liberties. After all, if your are doing what everyone else is doing, you won’t be any better than the rest.

Follow these rules to improve your Store conversion rate and to make users understand your app faster.

I have used these rules successfully on several of my games that I published in the Microsoft Store and in the App Store. You can find links to all the games that I built on my website: frenzygames.net

Building App of the Day card in 50 lines of Swift using GridLayout

In this tutorial I’m going to explain how to build an App of the Day card in Swift using GridLayout.
GridLayout is a Swift library for displaying UI elements in a grid like structure. GridLayout is available on GitHub.

To install GridLayout add the following to your Podfile:

pod 'GridLayout'

Here is the final layout that was build in this tutorial:

https://newtechcode.files.wordpress.com/2018/05/appoftheday.png)

Watch the tutorial on Youtube

Watch tutorial on YouTube

Try out the sample on GitHub

The entire sample code can be found on GitHub.

Summary of the solution

The solution uses the following UI elements:

        let mainImageView: UIImageView
        let logoImageView: UIImageView
        let header: UILabel
        let title: UILabel
        let subtitle: UILabel
        let getButton: UIButton
        let purchaseDisclaimer: UILabel
        let overlay: UIVisualEffectView

and builds the following approach to build the desired layout:

let titleContainer =  UIView.gridLayoutView(items: [GridItem(title,
                                                                     horizontalAlignment: .left),
                                                            GridItem(subtitle,
                                                                     row: 1,
                                                                     horizontalAlignment: .left)],
                                                    rowDefinitions: [RowDefinition(),
                                                                     RowDefinition(isAuto: true)],
                                                    columnDefinitions:[ColumnDefinition()])

        let buttonContainer =  UIView.gridLayoutView(items: [GridItem(getButton,
                                                                      row: 1),
                                                            GridItem(purchaseDisclaimer,
                                                                     row: 2,
                                                                     verticalAlignment: .top)],
                                                    rowDefinitions: [RowDefinition(),
                                                                     RowDefinition(isAuto: true),
                                                                     RowDefinition(),],
                                                    columnDefinitions:[ColumnDefinition()])

        let container = UIView.gridLayoutView(items: [GridItem(mainImageView,
                                                               position: .init(rowSpan: 2, columnSpan: 3)),
                                                      GridItem(overlay,
                                                               position: .init(row: 1, columnSpan: 3),
                                                               horizontalAlignment: .stretch,
                                                               verticalAlignment: .stretch),
                                                      GridItem(header,
                                                               position: .init(columnSpan: 3),
                                                               horizontalAlignment: .left,
                                                               verticalAlignment: .bottom,
                                                               margin: .init(top: 0, left: 12, bottom: 12, right: 0)),
                                                      GridItem(logoImageView,
                                                               row: 1,
                                                               horizontalAlignment: .left,
                                                               margin: .init(top: 8, left: 8, bottom: 8, right: 8)),
                                                      GridItem(titleContainer,
                                                               row: 1,
                                                               column: 1),
                                                      GridItem(buttonContainer,
                                                               row: 1,
                                                               column: 2)],
                                              rowDefinitions: [RowDefinition(),
                                                               RowDefinition(isAuto: true)],
                                              columnDefinitions: [ColumnDefinition(isAuto: true),
                                                                  ColumnDefinition(),
                                                                  ColumnDefinition(isAuto: true)])

        logoImageView.heightAnchor.constraint(equalToConstant: 100).isActive = true
        logoImageView.widthAnchor.constraint(equalToConstant: 100).isActive = true

        buttonContainer.widthAnchor.constraint(equalToConstant: 120).isActive = true

If you find this tutorial useful, try out GridLayout and let me know what you think.

Automatic Dependency Injection in Swift

In this article, I’m going to explore several Swift mechanisms that offer similar benefits to Automatic Dependency Injection, and evaluate their strengths and weaknesses.

I’m a big fan of Automatic Dependency Injection.
It saves time, it makes the code cleaner, and it works great for testing.
In the past, I built and used several Dependency Injection libraries, most recently in C# and in Objective-C.

How Does Dependency Injection Work?

Most dependency injection libraries build objects and resolve properties using the built-in language Reflection capabilities.
Swift has limited Reflection capabilities that allows inspecting objects, but not creating objects.

How Is It Done in Objective-C?

One way of overcoming this limitation is to use Objective-C APIs. Doing so requires that all objects that need to be created inherit from NSObject, and I would like to move away from having to use NSObject inheritance for Swift classes.

Let’s Get Started

Consider the following scenario:

  • SoundServiceProtocol protocol
  • SoundService class that implements SoundServiceProtocol protocol
  • Animal and Vehicle
protocol SoundServiceProtocol {
    func makeSound()
}

class SoundService: SoundServiceProtocol {
    func makeSound() {
        print("makeSound was called")
    }
}

class Animal {
    func action() {
        // use SoundService and call makeSound()
    }
}

class Vehicle {
    func action() {
        // use SoundService and call makeSound()
    }
}

Goal: use SoundService in Animal and Vehicle classes in an easy, concise and decoupled way.

1st Approach: Manually Adding Dependencies

class Animal {
    private var soundService: SoundServiceProtocol

    init(soundService: SoundServiceProtocol) {
        self.soundService = soundService
    }

    func action() {
        soundService.makeSound()
    }
}

class Vehicle {
    private var soundService: SoundServiceProtocol

    init(soundService: SoundServiceProtocol) {
        self.soundService = soundService
    }

    func action() {
        soundService.makeSound()
    }
}

Calling code:

let soundService = SoundService()
let animal = Animal(soundService: soundService)
let vehicle = Vehicle(soundService: soundService)

animal.action()
vehicle.action()

While this approach works, I find the infrastructure code to be too lengthy. Furthermore, a parent object that handles the lifetime of a child object must pass along dependencies, making the code lengthier. Even if the parent object does not need the dependency, it still needs to receive it in the init, to use it for constructing the child object.

Take the following example:

  • Class Horn needs the SoundServiceProtocol dependency.
  • Class AdvancedVehicle does not need the SoundServiceProtocol dependency for itself, but it does need it in order to construct the child object.
class Horn {
    private var soundService: SoundServiceProtocol

    init(soundService: SoundServiceProtocol) {
        self.soundService = soundService
    }

    func action() {
        soundService.makeSound()
    }
}

class AdvancedVehicle {
    private var horn: Horn

    init(soundService: SoundServiceProtocol) {
        horn = Horn(soundService: soundService)
    }
}

As you can imagine, the hierarchy of dependencies will grow as the parent and the children objects grow in complexity, resulting in time consuming code to maintain.

2nd Approach: Singleton Service Locator

class ServiceLocator {
    private static var instancePrivate: ServiceLocator?

    public static var instance: ServiceLocator {
        return instancePrivate!
    }

    public private(set) var soundService: SoundServiceProtocol

    init(soundService: SoundServiceProtocol) {
        self.soundService = soundService

        ServiceLocator.instancePrivate = self
    }
}

class Animal {
    func action() {
        ServiceLocator.instance.soundService.makeSound()
    }
}

class Vehicle {
    func action() {
        ServiceLocator.instance.soundService.makeSound()
    }
}

Calling code:

let soundService = SoundService()
let _ = ServiceLocator(soundService: soundService)
let animal = Animal()
let vehicle = Vehicle()

animal.action()
vehicle.action()

This approach moves the verbosity away from each class that needs access to a SoundService. Instead, the singleton ServiceLocator will have to be instantiated once, and afterwards all objects that need access to the service will have to use the static instance variable available on ServiceLocator.

While the code is much shorter than the 1st approach, when used by a consumer, the code used to call the service in each caller classes got bigger:

  • 1st approach: soundService.makeSound()
  • 2nd approach: ServiceLocator.instance.soundService.makeSound()

3rd Approach: Protocol Extensions

Building on 2nd approach, we can take advantage of the Swift protocol extension and the fact that you can define methods and properties that apply for all classes conforming to a protocol.

We define a new protocol named HasSoundService which only contains a computed property that is meant to simplify the access to the ServiceLocator.

protocol HasSoundService {
}

extension HasSoundService {
    var soundService: SoundServiceProtocol {
        return ServiceLocator.instance.soundService
    }
}

Any class that needs access to SoundService must conform to HasSoundService protocol:

class Animal: HasSoundService {
    func action() {
        soundService.makeSound()
    }
}

class Vehicle: HasSoundService {
    func action() {
        soundService.makeSound()
    }
}

Notice that we had to introduce a new protocol HasSoundService and write a computed property in an extension for that protocol. At the same time, each class that needs access to that property must conform the new HasSoundService protocol.

The calling code remains unchanged:

let soundService = SoundService()
let serviceLocator = ServiceLocator(soundService: soundService)
let animal = Animal()
let vehicle = Vehicle()

animal.action()
vehicle.action()

Conclusion

I found the 3rd approach to be the most versatile. By using the suggested infrastructure, the consumers gain easy access to the service they are interested in by conforming to a protocol.
I prefer this version because the syntax is concise and easy to remember as it does not alter the original methods of SoundServiceProtocol.
The only caveat is that infrastructure code must be written. The good news is that it only needs to be written once and makes consuming the resulting code much easier.

By using the Swift language features we managed to build a Dependency Injection-like mechanism that makes it easier to handle complex dependencies while keeping the code decoupled.

Where Is It Used

I use this approach on my new iOS game, Hexa Word Search. The goal of the game is to find words in a honeycomb structure.
Give it a try and if you have any feedback let me know.

You can find the entire code sample on GitHub.

Windows 10 Halloween games

I have updated my games to run on Windows 10.
The update includes:

  • bug fixes
  • speed improvements
  • Halloween theme

(click on each game icon to download)

Puzzle Frenzy

Jigsaw Puzzle Frenzy

Puzzle Frenzy Kids

Easy Peasy Puzzles

Quiz for Geeks

Quiz for Geeks

Fun with Words

Fun with Words

The Halloween theme includes these background images:

Refactoring XAML ResourceDictionaries

Code reuse of any kind is a priority for all developers. Design elements and UI resources are no exception.
In this tutorial you will learn how to correctly organize your resources for maximum reuse.

Considering the following scenario:
You have two apps: App1 and App2 int which you want to use the same resource but with slightly different properties.
App1 needs a style for a TextBlock

<Style x:Name="myTextBlockStyle" TargetType="TextBlock" >
    <Setter Property="Foreground" Value="Green"/>
    <Setter Property="FontSize" Value="24"/>
</Style>

while App2 needs a very similar style

<Style x:Name="myTextBlockStyle" TargetType="TextBlock" >
    <Setter Property="Foreground" Value="Orange"/>
    <Setter Property="FontSize" Value="24"/>
</Style>

Notice that the only different thing about the two styles is the color used as Foreground, the rest is similar. For the sake of simplicity I kept the myTextBlockStyle quite small, with only two properties.

For maximizing our code reuse we can try to refactor the two styles into a separate style as follows:

<Style x:Name="commonTextBlockStyle" TargetType="TextBlock" >
    <Setter Property="Foreground" Value="Green/Orange"/>
    <Setter Property="FontSize" Value="24"/>
</Style>

Now, the magical part!

If you use a common ClassLibrary you can move the style into a dictionary which both apps reference.

The style definition becomes:

<Style x:Name="commonTextBlockStyle" TargetType="TextBlock" >
    <Setter Property="Foreground" Value="{StaticResource brush1}"/>
    <Setter Property="FontSize" Value="24"/>
</Style>

Notice how the Foreground value is not longer set to either Green or Orange, but it references another resource named brush1.

In order for the whole setup to work this resource has to be defined in the ClassLibrary as follows:

<SolidColorBrush x:Key="brush1" Color="Red" />

And overriden in App1:

<SolidColorBrush x:Key="brush1" Color="Green" />

and in App2:

<SolidColorBrush x:Key="brush1" Color="Orange" />

At runtime, each app will have to reference the dictionary file where commonTextBlockStyle using an absolute path

The dictionary file that defines commonTextBlockStyle will in turn have to reference another dictionary path that contains the definition of brush1 using a relative path.

The following diagrams illustrate the setup in greater detail:

Project structure

ClassLibrary1 structure

StandardStyles in the ClassLibrary referenes a Common style referenced in the same project

App1 at runtime

App1 references StandardStyles and overrides Common with the desired color Green

App2 at runtime

App2 references StandardStyles and overrides Common with the desired color Orange.

This project structure and reference mechanism should greatly reduce your dictionary size while giving you all the flexibility you need for using your styles in whatever way you need.

Listen to your users, they know what they want

While developing Puzzle Frenzy, I took tons of wrong decision. On multiple occasions I assumed what my game players want and I implemented several features which were never used, or used by very few users.

However, over time I started to listen to what the users were asking for. By putting together all the communication channels I was able to come up with totally different features that I originally had in mind. And guess what?! by implementing those features suddenly I got more user engagement, better ratings and more downloads.

Being an game or app developer is not easy and surely poses a lot of challenges. For me, one of the biggest problem was that I was putting my judgement ahead of my users feature requests.

I soon as I realized that 50.000 voices are stronger than 1 (my own) the game development started to flourish.

For anyone out there interested in satisfying their users I have one golden advice:

Listen to your users, they know what they want!