Skip to content

Commit 06398c4

Browse files
Mark Pospeselmpospese
authored andcommitted
[Issue-51] Log warnings when fallback image is delivered.
1 parent d72ddbc commit 06398c4

File tree

6 files changed

+83
-4
lines changed

6 files changed

+83
-4
lines changed

Sources/YCoreUI/Protocols/ImageAsset.swift

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,17 +60,30 @@ extension ImageAsset {
6060
/// (prepended to `rawValue`) and `bundle`.
6161
/// - Returns: The named image or else `nil` if the named asset cannot be loaded.
6262
public func loadImage() -> UIImage? {
63+
UIImage(named: calculateName(), in: Self.bundle, compatibleWith: nil)
64+
}
65+
66+
internal func calculateName() -> String {
6367
let name: String
6468
if let validNamespace = Self.namespace {
6569
name = "\(validNamespace)/\(rawValue)"
6670
} else {
6771
name = rawValue
6872
}
69-
return UIImage(named: name, in: Self.bundle, compatibleWith: nil)
73+
return name
7074
}
7175

7276
/// An image asset for this name value.
7377
///
7478
/// Default implementation calls `loadImage` and nil-coalesces to `fallbackImage`.
75-
public var image: UIImage { loadImage() ?? Self.fallbackImage }
79+
public var image: UIImage {
80+
guard let image = loadImage() else {
81+
if YCoreUI.isLoggingEnabled {
82+
YCoreUI.imageLogger.warning("Image named \(calculateName()) failed to load from bundle.")
83+
}
84+
return Self.fallbackImage
85+
}
86+
87+
return image
88+
}
7689
}

Sources/YCoreUI/Protocols/SystemImage.swift

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,5 +50,14 @@ extension SystemImage {
5050
/// A system image for this name value.
5151
///
5252
/// Default implementation calls `loadImage` and nil-coalesces to `fallbackImage`.
53-
public var image: UIImage { loadImage() ?? Self.fallbackImage }
53+
public var image: UIImage {
54+
guard let image = loadImage() else {
55+
if YCoreUI.isLoggingEnabled {
56+
YCoreUI.imageLogger.warning("System image named \(rawValue) failed to load.")
57+
}
58+
return Self.fallbackImage
59+
}
60+
61+
return image
62+
}
5463
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
//
2+
// YCoreUI+Logging.swift
3+
// YCoreUI
4+
//
5+
// Created by Mark Pospesel on 3/16/23.
6+
// Copyright © 2023 Y Media Labs. All rights reserved.
7+
//
8+
9+
import Foundation
10+
import os
11+
12+
/// Y—CoreUI Settings
13+
public struct YCoreUI {
14+
/// Whether console logging for warnings is enabled. Defaults to `true`.
15+
public static var isLoggingEnabled = true
16+
}
17+
18+
internal extension YCoreUI {
19+
/// Logger for warnings related to image loading. cf. `ImageAsset` and `SystemImage`
20+
static let imageLogger = Logger(subsystem: "YCoreUI", category: "images")
21+
}

Tests/YCoreUITests/Protocols/ImageAssetTests.swift

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
//
88

99
import XCTest
10-
import YCoreUI
10+
@testable import YCoreUI
1111

1212
final class ImageAssetTests: XCTestCase {
1313
func test_bundle() {
@@ -37,21 +37,36 @@ final class ImageAssetTests: XCTestCase {
3737
func test_loadImageWithoutNameSpace() {
3838
Flags.allCases.forEach {
3939
XCTAssertNotNil($0.loadImage())
40+
XCTAssertNotEqual($0.image.pngData(), DefaultImageAssets.fallbackImage.pngData())
4041
}
4142
}
4243

4344
func test_missingImage() {
45+
YCoreUI.isLoggingEnabled = false
46+
4447
Missing.allCases.forEach {
4548
XCTAssertNil($0.loadImage())
4649
XCTAssertEqual($0.image, UIImage(systemName: "x.squareroot"))
4750
}
51+
52+
YCoreUI.isLoggingEnabled = true
4853
}
4954

5055
func test_imageAsset_defaultValues() {
5156
XCTAssertEqual(DefaultImageAssets.bundle, .main)
5257
XCTAssertEqual(DefaultImageAssets.defaultCase.image.pngData(), DefaultImageAssets.fallbackImage.pngData())
5358
XCTAssertNil(DefaultImageAssets.namespace)
5459
}
60+
61+
func test_calculateName_deliversCorrectName() {
62+
Flags.allCases.forEach {
63+
XCTAssertEqual($0.calculateName(), $0.rawValue)
64+
}
65+
66+
Icons.allCases.forEach {
67+
XCTAssertEqual($0.calculateName(), "Icons/\($0.rawValue)")
68+
}
69+
}
5570
}
5671

5772
enum DefaultImageAssets: String, CaseIterable, ImageAsset {

Tests/YCoreUITests/Protocols/SystemImageTests.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,19 @@ final class SystemImageTests: XCTestCase {
1818
func test_loadImage_deliversImage() {
1919
Symbols.allCases.forEach {
2020
XCTAssertNotNil($0.loadImage())
21+
XCTAssertNotEqual($0.image.pngData(), DefaultSymbols.fallbackImage.pngData())
2122
}
2223
}
2324

2425
func test_missingImage_deliversCustomFallback() {
26+
YCoreUI.isLoggingEnabled = false
27+
2528
MissingSymbols.allCases.forEach {
2629
XCTAssertNil($0.loadImage())
2730
XCTAssertEqual($0.image, UIImage(systemName: "x.squareroot"))
2831
}
32+
33+
YCoreUI.isLoggingEnabled = true
2934
}
3035

3136
func test_systemImage_deliversDefaultFallback() {
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
//
2+
// YCoreUI+LoggingTests.swift
3+
// YCoreUI
4+
//
5+
// Created by Mark Pospesel on 3/16/23.
6+
// Copyright © 2023 Y Media Labs. All rights reserved.
7+
//
8+
9+
import XCTest
10+
@testable import YCoreUI
11+
12+
final class YCoreUILoggingTests: XCTestCase {
13+
func testDefaults() {
14+
XCTAssertTrue(YCoreUI.isLoggingEnabled)
15+
}
16+
}

0 commit comments

Comments
 (0)