Tawa / TNTutorialManager

Tutorial Handler that helps you implement interactive on boarding and tutorials inside your iOS Apps.
MIT License
108 stars 6 forks source link

Masked UIBlurEffect doesn't work on iOS 10 due to acknowledged Apple bug #16

Open shirakaba opened 6 years ago

shirakaba commented 6 years ago

The UIBlurEffect is not applied, meaning that the shaded area for the tutorial is just a grey-tinted area. Without this blur, it is hard to read the tutorial texts when they are overlaying other texts.

Acknowledged on:

Here are several of the recommendations made by Apple staff member Rincewind in that thread:

Your issue is also using CALayer.mask, using UIView.maskView would probably work better for your needs (modulo bugs that exist in Beta3 at the moment).

However, fundamentally the best way to create a mask view that uses a shape layer is to create your own UIView subclass that overrides .layerClass() to return CAShapeLayer.self. That removes the extra 2 views/layers in your example and simplifies greatly by not using a mask of a subview of a view mean to be a mask.

Instead you can create a simple UIView subclass that uses a CAShapeLayer as its backing layer by overriding +layerClass.

The only solution that can work is to use UIView.maskView on the UIVisualEffectView. But without knowing what you tried its hard to understand where you might have gone wrong.

On iOS 10 blurs can't sample content "through" a mask – because you make the visual effect view a subview of a view with a mask you prevent it from sampling the content it needs to do the masking.

You need to apply the mask directly to the UIVisualEffectView, not to a superview. This works on iOS 11 due to improvements specifially made on that OS version.

So I think he recommends making a class like this:

@interface ShapeView: UIView
@end
@implementation ShapeView

+ (Class)layerClass
{
    return [CAShapeLayer class];
}
@end

... However, I'm not sure how to migrate from CALayer.mask to UIView.maskView (with the aforementioned ShapeView). I started trying to replace the relevant code after [tutorialView setNeedsDisplay], but I really don't know what I'm doing (not experienced in UI code):

ShapeView* shapeView = [[ShapeView alloc] initWithFrame:CGRectMake(0, 0, tutorialView.frame.size.width, tutorialView.frame.size.height)];
UIVisualEffect* blurEffect = [UIBlurEffect effectWithStyle: UIBlurEffectStyleRegular];
UIVisualEffectView* effectView = [[UIVisualEffectView alloc] initWithEffect:blurEffect];
shapeView.frame = effectView.frame;
[tutorialView addSubview:effectView];

/* The original code: */
// CALayer* maskLayer = [CALayer layer];
// maskLayer.frame = CGRectMake(0, 0, tutorialView.frame.size.width, tutorialView.frame.size.height);
// maskLayer.contents = (__bridge id)[image CGImage];
// 
// tutorialView.layer.mask = maskLayer;

My code snippet compiles, but doesn't do anything useful (no blur, no masking of highlighted areas). Hopefully it can be of help as a starting point, though. The other starting point is the commit made in the Instructions repository, but it's rather big and hard to read through.

Tawa commented 6 years ago

Honestly, since this is an iOS 10 issue, I'm gonna try to find the time to fix it, but it's a very low priority. What do you think?

shirakaba commented 6 years ago

Sorry for the very late response!

I would be very thankful if you could fix it if you might know how to do so, as I'm all out of ideas. If a solution is clear to you, I would encourage pursuing it if it's no bother. Otherwise, if it's a complete shot in the dark, then I can live with it affecting just older iOS users.

I've since seen another user for whom the shaded area becomes completely black, however, so I can add that the failure mode is both inconsistent and also very obstructive to introducing the interface.

Tawa commented 6 years ago

Honestly I have a tight schedule now and too much to do, I can't find the time to work on fixing this. Let's leave it like this for now. Since this is happening on an older version of iOS, it's low priority for me.

shirakaba commented 6 years ago

Understood!