codeandtheory / YCoreUI

Core components for iOS and tvOS to accelerate building user interfaces in code.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Add `ImageAsset` protocol

mpospese opened this issue · comments

Intro

It's a common pattern to have a string-based enum to hold the names of image assets in an asset catalog. In each case you need to add some sort of computed property or func to return the image loaded from the asset catalog. It would be nice to have a protocol that we could simply have our enum conform to and skip having to write that implementation again and again. (This is especially true for cases where you might wish to organize your images into multiple enums, which would require writing that image loading property/func once per enum.)

So let's declare a public protocol named ImageAsset.
(It is patterned off the protocol Localizable that is already part of YCoreUI. ImageAsset will do for image assets what Localizable does for string assets and Colorable does for color assets).

Tasks

  • declare a public protocol ImageAsset
    • declare a static get var bundle of type Bundle
    • declare a static get var namespace of type String?
    • declare a static get var fallbackImage of type UIImage
    • declare a loadImage func that takes no parameters and returns UIImage?
    • declare a get var image of type UIImage
  • add default implementations to all 4
  • bundle defaults to Bundle.main
  • namespace defaults to nil
  • fallbackImage defaults to a custom-drawn image that will be obvious to visual QA is not correct. Perhaps a 16x16 image filled with UIColor.systemPink
  • loadImage attempts to load the named image using (optional namespace prepended to) rawValue and bundle (but returns nil if the image does not exist in the asset catalog).
  • image uses loadImage but nil-coalesces the result back to fallbackImage so that it always returns something.

Acceptance Criteria

  • Implement ImageAsset as described in Tasks above
  • SwiftLint analysis has 0 violations
  • fully unit test the new code by adding images to an asset catalog in the test target only, declaring an enum that lists the names of the images, and test that it loads. Also test expected failures (e.g. blank name or random name does not load, wrong bundle, etc)
  • the sample image assets used in our test target need to be as small as possible freely distributable. (I might just create some simple pixel art images to use.)
  • fully document all public interfaces on the new code (as per Jazzy documentation coverage tests)

Uses these assets and the following enums for testing:

    enum Flags: String, CaseIterable, ImageAsset {
        case unitedStates = "flag_us"
        case india = "flag_in"
        case brazil = "flag_br"
        case switzerland = "flag_ch"

        static var bundle: Bundle { .module }
    }

    enum Icons: String, CaseIterable, ImageAsset {
        case plus
        case minus

        static var bundle: Bundle { .module }
        static var namespace: String? { "Icons" }
    }

    enum Missing: String, CaseIterable, ImageAsset {
        case notHere
        case gone

        static var fallbackImage: UIImage {
            let image: UIImage! = UIImage(systemName: "x.squareroot")
            return image
        }
    }

Images:
ImageAssets.zip

Put all 6 images into the assets catalog in the Test target.
You can leave the 4 flag images at root level. These are the Flags enum.
Create a folder "Icons", mark it as being a namespace and put plus and minus files inside it. These are the Icons enum.
The Missing enum is, well, missing, so we don't need any assets. This lets us test fallback.