Skip to content

Snapshot has incorrect corner mask when using layer.maskedCorners #358

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
ryanmeisters opened this issue Jun 18, 2020 · 13 comments
Open

Comments

@ryanmeisters
Copy link

Thanks for an awesome library! I've been enjoying it immensely since adding to my projects last week 🙌

I'm not sure if this is a UIKit issue or a SnapshotTesting issue, but I get an incorrect snapshot when using CALayer's maskedCorners property (introduced in iOS 11)

e.g.

func test_maskedCorner() {
    let v = UIView()
    v.frame = CGRect(x: 0, y: 0, width: 100, height: 40)
    v.backgroundColor = .blue
    v.layer.cornerRadius = 12
    v.layer.maskedCorners = [.layerMaxXMaxYCorner, .layerMinXMaxYCorner]
    assertSnapshot(matching: v, as: .image, record: true)
  }

This should produce a blue rectangle with the bottom two corners rounded, but instead produces the image as if maskedCorners was not applied.

Result:
test_sdfads 1

@chefnobody
Copy link

Shootin' from the hip a little bit here, but I wonder if this has anything to do w/ the snapshotView function that attempts to render the view's layer into the provided graphics context and a warning in the CALayer docs for that function call.

view.layer.render(in: ctx.cgContext)

(line 716 of View.swift)

If you explore the CALayer render method docs they say this:

    /* Renders the receiver and its sublayers into 'ctx'. This method
     * renders directly from the layer tree. Renders in the coordinate space
     * of the layer.
     *
     * WARNING: currently this method does not implement the full
     * CoreAnimation composition model, use with caution. */

Maybe this warning has something to do with it?

Alternatively, I haven't yet tried the drawHeirarchy(in:afterScreenUpdates:) approach that draws the view into a key window, as my project uses a framework and so it has no host application.

@chefnobody
Copy link

Going a little further, I found docs for render(in:) online whose warning is more explicit:

Important
The OS X v10.5 implementation of this method does not support the entire Core Animation composition model. QCCompositionLayer, CAOpenGLLayer, and QTMovieLayer layers are not rendered. Additionally, layers that use 3D transforms are not rendered, nor are layers that specify backgroundFilters, filters, compositingFilter, or a mask values. Future versions of macOS may add support for rendering these layers and properties.

Emphasis added ^^

@jibeex
Copy link

jibeex commented Aug 6, 2020

Is there any solution/workaround?

@Nikoloutsos
Copy link
Contributor

Facing the same problem. Is there any workaround?

@dmhts
Copy link

dmhts commented Jul 6, 2021

Same here

@penelopearaujo
Copy link

penelopearaujo commented Jul 22, 2021

Did anyone find any solution or workaround for this? I'm facing the same issue.

@dk53
Copy link

dk53 commented Aug 9, 2021

Won't add a lot of value here, just saying I face the same issue overthere

@stephencelis
Copy link
Member

As someone brought up previously in this issue, I believe you may need to introduce a host application and set drawHierarchyInKeyWindow for this to render properly. Anyone give that a shot?

@chefnobody
Copy link

chefnobody commented Aug 18, 2021

@stephencelis I took a crack at this and I think I've verified that using .image(drawHeirarchyInKeyWindow: true) does seem to fix the issue.

I think another possible alternative is to try a UIBezierPath (see below) and set that path to a mask and then that mask on the layer. This seems to work w/o the need for a host app as I've tested this code in a separate Unit Test target which does not have a host application.

init(roundedRect rect: CGRect, byRoundingCorners corners: UIRectCorner, cornerRadii: CGSize)

At any rate, here's a sample project with a Unit Test target whose host application is the main app target: https://github.com/chefnobody/snapshot-masked-corners

And a screenshot of the results.

  • Green uses the UIBezierPath > Mask > Layer technique.
  • Red is the issue as outlined in the original post.
  • Blue uses drawHeirarchyInKeyWindow.

Screen Shot 2021-08-18 at 11 39 23 AM

@domagojstankovic
Copy link

@chefnobody .image(drawHierarchyInKeyWindow: true) works for me. Thanks!

@Nikoloutsos
Copy link
Contributor

@domagojstankovic Be careful with this.
Indeed solve the problem with corner radius but introduce new problem with different colours on different machines.

@domagojstankovic
Copy link

@Nikoloutsos you are right, it didn't work when testing on CI so we had to remove those tests. Thank you for mentioning it anyway!

@alimkhan6
Copy link

@chefnobody thanks for suggest of drawHierarchy method

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

10 participants