SDWebImage / SDWebImageSwiftUI

SwiftUI Image loading and Animation framework powered by SDWebImage
https://sdwebimage.github.io/SDWebImageSwiftUI
MIT License
2.16k stars 223 forks source link

Fix the issue that using `Image(uiImage:)` will result wrong rendering mode in some component like `TabBarItem`, while using `Image(decorative:scale:orientation:)` works well #177

Closed dreampiggy closed 3 years ago

dreampiggy commented 3 years ago

This is Apple's bug. Which does not setup the correct renderingMode when using Image from UIImage, only for CGImage

Apple SwiftUI on iOS, seems treat the GraphicsImage, the image from Image(decorative:sclae:orientation) first class citizen. Many edge cases will use that to bridge to the UIKit component, like UITabbarItem when using TabbarItem.

So, we should avoid using that Image(uiimage:) initializer as much as possible, to avoid some bugs.

This close #175

dreampiggy commented 3 years ago

Before fix:

image

After fix:

image

dreampiggy commented 3 years ago

Apple's implementation (via disassembly result):

 struct SwiftUI.Resolved {

    // Properties
    var image : GraphicsImage
    var label : String?
    var platformItemImage : UIImage?
    var decorative : Bool
 }

 struct SwiftUI.GraphicsImage {

    // Properties
    var contents : Contents
    var scale : CGPoint
    var unrotatedPixelSize : CGSize
    var orientation : Orientation
    var maskColor : _Resolved
    var resizingInfo : ResizingInfo
    var isAntialiased : Bool
    var interpolation : Interpolation
 }

extension UIBarButtonItem {
    // This method is used when SwiftUI create the navigation bar for `UINavigationController`, SwiftUI's briding code
    static func make(item: SwiftUI.ToolbarStorage.Item, in: SwiftUI.EnvironmentValues, targets: inout [SwiftUI.UIBarItemTarget], viewController: UIViewController, navController: UINavigationController?) -> UIBarButtonItem {
        // ...some process logic
       // for each item loop
    var item: UIBarButtonItem?
    if let uiImage = platformItem.platformItemImage {
        let imageView = UIImageView(image: uiImage)
        item = UIBarButtonItem(customView:imageView)
    } else if platformItem.decorative {
        let image = UIImage(cgImge:platformItem.contents)
        let renderingMode = context.flags.renderingMode ?? .alwaysOriginal
        let image2 = image.renderingMode(renderingMode)
        item = UIBarButtonItem(image: image2, .plain, target, selector))
    } else {
       let hostingView = context.hostingView
       item = UIBarButtonItem(customView:hostView)
    }
    return item
}
codecov[bot] commented 3 years ago

Codecov Report

Merging #177 (f6074c2) into master (88f2d67) will increase coverage by 1.21%. The diff coverage is 100.00%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #177      +/-   ##
==========================================
+ Coverage   73.78%   75.00%   +1.21%     
==========================================
  Files          11       11              
  Lines         965      960       -5     
==========================================
+ Hits          712      720       +8     
+ Misses        253      240      -13     
Flag Coverage Δ
ios 71.06% <100.00%> (+1.72%) :arrow_up:
macos 74.47% <100.00%> (-0.15%) :arrow_down:

Flags with carried forward coverage won't be shown. Click here to find out more.

Impacted Files Coverage Δ
SDWebImageSwiftUI/Classes/WebImage.swift 89.32% <100.00%> (-0.30%) :arrow_down:
SDWebImageSwiftUI/Classes/Image.swift 43.18% <0.00%> (+29.54%) :arrow_up:

Continue to review full report at Codecov.

Legend - Click here to learn more Δ = absolute <relative> (impact), ø = not affected, ? = missing data Powered by Codecov. Last update 88f2d67...f6074c2. Read the comment docs.