Performance issue with UIVisualEffectView in UITableViewCell - ios

I have UITableView with 10 big images like Instagram and i have some blurview on that images. I add my visualeffects UITableViewCell like that;
_blurButtonEffect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleLight];
_visualButtonEffectView = [[UIVisualEffectView alloc] initWithEffect:_blurButtonEffect];
_visualButtonEffectView.layer.cornerRadius = 10.0f;
_visualEmojiEffectView = [[UIVisualEffectView alloc] initWithEffect:_blurButtonEffect];
_visualEmojiEffectView.layer.cornerRadius = 24.0f;
_visualButtonEffectView.layer.masksToBounds = YES;
_visualEmojiEffectView.layer.masksToBounds = YES;
_visualButtonEffectView.frame = CGRectMake(20.0f, _button.frame.origin.y + 7.0f, 48.0f, 48.0f);
_visualEmojiEffectView.frame = CGRectMake(_emoji.frame.origin.x - 4.0f, _button.frame.origin.y + 22.0f, ([UIScreen mainScreen].bounds.size.width/2) - 25.0f, 30.0f);
If button title is null, i show _visualEmojiEffectView and hide _visualButtonEffectView. Otherwise _visualButtonEffectView is always shown. While i'm scrolling my UITableView, performance is perfect but this blur effects shown so annoying, they seems like flashing with every scroll movement and touches. I can block this with this in cell;
self.layer.shouldRasterize = YES;
self.layer.rasterizationScale = [UIScreen mainScreen].scale;
If i'm rasterize my cell like that, blur effect works perfect but scrolling performance is awful even on iPhone 6. What is the correct way to configure UIBlurEffectView with UITableViewCell?

I know it is too late to reply but still i hope this helps someone. You can give a white background colour to the visual effect view with a very low alpha. Something like this:
[_visualButtonEffectView setBackgroundColor:[UIColor colorWithWhite:1.0 alpha:0.2]];
You may also try using UIToolbar instead of a visual effect view. It does not give exactly the same effect but will still be good enough.

Related

Set CALayer as SCNMaterial's diffuse contents

I've been searching all over the internet over the past couple of days to no avail. Unfortunately, the apple documentation about this specific issue is vague and no sample code is available (at least thats what I found out). What seems to be the issue you may ask...
I'm trying to set a uiview's layer as the contents of the material that is used to render an iPhone model's screen (Yep, trippy :P ). The iPhone's screen's UV mapping is set from 0 to 1 so that no issue persists in mapping the texture/layer onto the texels.
So, instead of getting this layer to appear rendered on the iPhone, same as left image, Instead, I get this rendered onto the iPhone like right image
Correct Render                                        Incorrect Render
Also note, that when I set a breakpoint and debug the actual iPhone node and view it in Xcode, a completely different render is shown and the layer gets half-fixed when I continue execution:
Now then... HOW do I fix this issue??? I've tried playing with the diffuse's contents transform matrix but nothing gets fixed. I've also tried resizing the UIView to 256x256 (since the UV seems to be 256x256 as shown in blender - the 3d modelling package), but that doesn't fix anything.
Here is the code for the layer:
UIView *screen = [[UIView alloc] initWithFrame:self.view.bounds];
screen.backgroundColor = [UIColor redColor];
UIView *temp = [[UIView alloc] initWithFrame:CGRectMake(0, 0, screen.bounds.size.width, 60)];
temp.backgroundColor = [UIColor colorWithRed:0 green:(112.f/255.f) blue:(235.f/255.f) alpha:1];
UILabel *label = [[UILabel alloc] initWithFrame:CGRectInset(temp.bounds, 40, 0)];
label.frame = CGRectOffset(label.frame, 40, 0);
label.textColor = [UIColor colorWithRed:0 green:(48.f/255.f) blue:(84.f/255.f) alpha:1];
label.text = #"Select Track";
label.font = [UIFont fontWithName:#"HelveticaNeue-Light" size:30];
label.minimumScaleFactor = 0.001;
label.adjustsFontSizeToFitWidth = YES;
label.lineBreakMode = NSLineBreakByClipping;
[temp addSubview:label];
UIView *separator = [[UIView alloc] initWithFrame:CGRectMake(0, temp.bounds.size.height - 2, temp.bounds.size.width, 2)];
separator.backgroundColor = [UIColor colorWithRed:0 green:(48.f/255.f) blue:(84.f/255.f) alpha:1];
[temp addSubview:separator];
[screen addSubview:temp];
screen.layer.contentsGravity = kCAGravityCenter;
Edit
What's even weirder is that if I capture a UIImage of the view using:
- (UIImage *) imageWithView:(UIView *)view
{
UIGraphicsBeginImageContextWithOptions(view.bounds.size, view.opaque, 0.0);
[view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage * img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return img;
}
and use that as the diffuse's content... everything works out perfectly fine?! It's really weird and frustrating since the image's size is exactly the same as the uiview's...
Edit 2
I ended up just using an image of the view as the texture, which makes things much more static than I needed. I won't set this as the answer because I'll still be waiting for a correct fix to this issue even if it in a long time. So, if you have an answer and this topic has been opened for a long time, please bump it if you can. The documentation on this section is just so poor.
New post on an old thread, but this day-in-age, it's possible to set the UIView itself as SCNMaterialProperty (diffuse) contents. Intention to support this feature is communicated directly from SceneKit engineering at Apple, though the documentation has not yet been updated to reflect it.
To tied back to the original post, do not set a UIView.layer as material property contents; instead set contents to the UIView itself.
[Update: according to Lance's comment below, support for views may be getting worse rather than getting better.]
The SceneKit docs pretty strongly suggest that, while there are cases where you can use animated CALayers as material content, that doesn't include UIView layers:
SceneKit cannot use a layer that is already being displayed elsewhere (for example, the backing layer of a UIView object).
That suggests that if you want to make animated content for your material, you're better off with either Core Animation used entirely on its own or SpriteKit.

Strange blur artefacts with UIVisualEffectView

I have a UIVisualEffectView which is causing some strange artefacts right when it appears. The UIVisualEffectView is added in code after the view loads because it's not available in iOS 7.
Look at the blurred text background over the street view image: http://s.swic.name/Z3UL
The blur takes a good 0.1 seconds to appear, and before that it's just a lower resolution background shining through like the blur hasn't been calculated yet.
Any idea what is going on? I'm adding the blur in awakeFromNib using this code
- (void)addBlurWithColor:(UIColor *)color andStyle:(UIBlurEffectStyle)style andVibrancy:(BOOL)vibrancy
{
if (UIDevice.supportsVisualEffects && NSClassFromString(#"UIVisualEffectView") && !UIAccessibilityIsReduceTransparencyEnabled()) {
self.backgroundColor = color;
UIBlurEffect *blurEffect = [UIBlurEffect effectWithStyle:style];
UIVisualEffectView *visualEffectView = [[UIVisualEffectView alloc] initWithEffect:blurEffect];
visualEffectView.frame = self.bounds;
visualEffectView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
NSArray *subviews = self.subviews;
[self addSubview:visualEffectView];
[self sendSubviewToBack:visualEffectView];
if (vibrancy) {
UIVibrancyEffect *vibrancyEffect = [UIVibrancyEffect effectForBlurEffect:blurEffect];
UIVisualEffectView *vibrancyEffectView = [[UIVisualEffectView alloc] initWithEffect:vibrancyEffect];
[vibrancyEffectView setFrame:self.bounds];
vibrancyEffectView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
for (UIView *subview in subviews) {
[vibrancyEffectView.contentView addSubview:subview];
}
[[visualEffectView contentView] addSubview:vibrancyEffectView];
}
}
}
Edit: The video just has slow animations enabled, the transition is a regular push segue.
Edit2: I get the same strange behaviour if i just drag drop a "UIVisualEffectView with Blur" in Interface Builder, so the code above shouldn't be to blame.
Found the problem, when the view appears I'm reloading the tableview inside [UIView transitionWithView:...] which alters the alpha which apparently is a big no-no when it comes to UIVisualEffectViews!
According to UIVisualEffectView Documentation;
When using the UIVisualEffectView class, avoid alpha values that are
less than 1. Creating views that are partially transparent causes the
system to combine the view and all the associated subviews during an
offscreen render pass. UIVisualEffectView objects need to be combined
as part of the content they are layered on top of in order to look
correct. Setting the alpha to less than 1 on the visual effect view or
any of its superviews causes many effects to look incorrect or not
show up at all.
https://developer.apple.com/library/ios/documentation/uikit/reference/UIVisualEffectView/index.html

How to set shadow gradient image on UIImageView iOS

Hey I'm new to iPhone and I have been trying to set shadow for UIImageView using shadow gradient image i.e. "Image-Shadow.png" using below code.
imageView.layer.shadowColor = [UIColor colorWithPatternImage:[UIImage
imageNamed:#"Image-Shadow.png"]].CGColor;
imageView.layer.shadowOffset = CGSizeMake(0, 1);
imageView.layer.shadowOpacity = 1;
imageView.clipsToBounds = NO;
imageView.layer.shouldRasterize = YES;
My problem is, i am not getting shadow in my UIImageView using above code. Can you please tell me that is this the correct way to add shadow image in UIImageView or it is possible with some other way?
Problem is with the image. I don't think you can provide a pattern image to create a shadow!
Give a proper color like [UIColor blackColor].CGColor and it should work.
The problem is with this line:
imageView.layer.shadowOffset = CGSizeMake(0, 1);
where you are setting the shadow, but not giving it a visible space to display itself.
Positive or negative values should be given to both parameters.
Positive values stretch "down" and "to the right" of your view, negative values stretch "to the left" and "to the up" of your view.
here is my solution as per my requirement :
//set shadow gradient on image view
UIView *shadowView = [[UIView alloc] initWithFrame:imageView.frame]; //add view behind the image view
shadowView.layer.contents = (id) [UIImage imageNamed:#"Image-Shadow.png"].CGImage;
[imageView addSubview:shadowView];
Thanks to all.

Giving a shadow cause to slowly scroll down

I have white background and white label on it, so I need to give a shadow all side of characters I use this code and it works! but it cause to slowly scroll do you have any idea how can solve this problem?
cell.L_name.layer.shadowOpacity = 1.0;
cell.L_name.layer.shadowRadius = 1.0;
cell.L_name.layer.shadowColor = [UIColor blackColor].CGColor;
cell.L_name.layer.shadowOffset = CGSizeMake(1.0, 1.0);
try setting
cell.L_name.layer.shouldRasterize = YES;
this will render your label as a bitmap and might improve scrolling smoothness
additionally you could set
cell.opaque = YES;
which will optimize drawing performance as well.
Setting a shadowPath for the layer would probably increase the performance greatly.
cell.L_name.layer.shadowPath = [UIBezierPath pathWithRect:L_name.bounds].CGPath;
Besides, you can cache the generated shadow as a bitmap, which also increases the performance considerably. Do not forget to set rasterizationScale for retina displays.
cell.L_name.layer.shouldRasterize = YES;
cell.L_name.layer.rasterizationScale = [UIScreen mainScreen].scale;

Tableview scrolling lack of performance using cornerRadius, whats alternatives?

I can't find a solution for my issue, so I hope some experts could help me.
I have tableview with lots of cells. For each cell I have an image view with rounded corners:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UIImageView *exampleView;
...
exampleView.layer.cornerRadius = 5.f;
exampleView.clipsToBounds = YES;
[cell.contentView addSubview:exampleView];
...
}
Resulting in a big lack of scrolling performance issue - when using cornerRadius and clipsToBounds = YES, any alternative solutions?
(The rounded corner image view contains pictures, and if the corner isn't set. The scrolling is smooth. So the problem is here)
EDIT #1: to clarify that I have already read other posts:
...
exampleView.frame = CGRectMake(5.0f,size.height-15.0f,30.0f,30.0f);
exampleView.layer.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.5].CGColor;
exampleView.layer.cornerRadius = 5.0f;
exampleView.layer.borderWidth = 0.3f;
exampleView.layer.borderColor = [UIColor blackColor].CGColor;
exampleView.layer.masksToBounds = NO;
exampleView.layer.shouldRasterize = YES;
//exampleView.clipsToBounds = NO;
[exampleView setImage: myImage ];
EDIT #2:
It's like myImage is lapping over the rounded corner view. How do I make the image fit the rounded corner view correct? or am I missing something?
Just change the following line
exampleView.layer.masksToBounds = YES;
To round out the corners in your imageView. See images below.
The tableview scrolling is a issue with view compositing. In addition to suggestions above, this will certainly help -
Set the opaque property of the UITableViewCell's contentView property, and backgroundView property. Go:
[cell.contentView setOpaque:YES];
[cell.backgroundView setOpaque:YES];
This will help reduce the view compositing effort at the earliest possible stage.
There are additional, advanced, techniques which would require you to use asynchronous processing to process your images as you scroll. They may be overkill if the above techniques work.

Resources