0

I have a UIView that contains drop shadows and corners which I am loading four of in my UIViewController and I am seeing a performance hit when the screen loads. Since I am using the same white background with shadows and corner radii I figured I would store the UIView in NSCache.

When I run the app there is a large gap where the first UIView should be, however, it is not showing up. What does show up is the last view in my list of views. If I comment out the last one and run it again, the third one shows up. It seems like I am having an issue with the pointer in memory but not sure. Perhaps I am using NSCache incorrectly?

(Note: The first view shown is not using the NSCache)

enter image description here

Here is how I am using the NSCache:

.h file

@interface LunchDetailViewController : UIViewController <UIScrollViewDelegate>

@property (nonatomic) IBOutlet UIScrollView *scrollView;
@property (nonatomic, strong) NSCache *entreeViewsCache;

@end

.m file

@synthesize scrollView;
@synthesize entreeViewsCache;

- (void)viewDidLoad
{
    [super viewDidLoad];

    self.entreeViewsCache = [[NSCache alloc] init];
    UIView *entreeView = [[UIView alloc] init];
    entreeView.backgroundColor = [UIColor whiteColor];
    entreeView.layer.masksToBounds = NO;
    entreeView.layer.cornerRadius = 3.0;
    entreeView.layer.shadowOffset = CGSizeMake(1.1, 2.1);
    entreeView.layer.shadowOpacity = 0.2;

    [self.entreeViewsCache setObject:entreeView forKey:@"EntreeView"];
}

- (void) configureScrollView
{
    // This line of code allows the scroll view to be 'scrollable'.
    self.scrollView.contentSize = CGSizeMake(320, 620);

    UIView *elementaryRoundedCornerView = [self.entreeViewsCache objectForKey:@"EntreeView"];
    elementaryRoundedCornerView.frame = CGRectMake(15,15,290,180);

    UIView *middleRoundedCornerView = [self.entreeViewsCache objectForKey:@"EntreeView"];
    middleRoundedCornerView.frame = CGRectMake(15,210,290,180);

    UIView *highRoundedCornerView = [self.entreeViewsCache objectForKey:@"EntreeView"];
    highRoundedCornerView.frame = CGRectMake(15,404,290,180);

    NSMutableArray *entreeItems = [[NSMutableArray alloc] initWithObjects:@"Pancakes w/ Sausage Patties", @"Corn Dog", @"Grilled Cheese Sandwhich", @"Chicken Tender Wraps", nil];


    UIView *elementaryLunchMenuDetails = [[UIView alloc] initWithFrame:CGRectMake(10, 10, 240, 160)];
    [elementaryLunchMenuDetails addSubview:[self returnNativeCode:entreeItems rectDimensions:CGRectMake(2, 5, 215, 160) schoolType:@"Elementary"]];
    [elementaryRoundedCornerView addSubview:elementaryLunchMenuDetails];

    UIView *middleLunchMenuDetails = [[UIView alloc] initWithFrame:CGRectMake(10, 10, 240, 160)];
    [middleLunchMenuDetails addSubview:[self returnNativeCode:entreeItems rectDimensions:CGRectMake(2, 2, 215, 160) schoolType:@"Middle"]];
    [middleRoundedCornerView addSubview:middleLunchMenuDetails];

    UIView *highLunchMenuDetails = [[UIView alloc] initWithFrame:CGRectMake(10,10, 240, 160)];
    [highLunchMenuDetails addSubview:[self returnNativeCode:entreeItems rectDimensions:CGRectMake(2, 2, 215, 160) schoolType:@"High"]];
    [highRoundedCornerView addSubview:highLunchMenuDetails];

    [self.scrollView addSubview:elementaryRoundedCornerView];
    [self.scrollView addSubview:middleRoundedCornerView];
    [self.scrollView addSubview:highRoundedCornerView];
}
Flea
  • 11,176
  • 6
  • 72
  • 83

1 Answers1

0

Wow. That's clever. But not correct.

Instead of using NSCache to duplicate a view, you probably want to create a UIView subclass that formats the view the way you want. Then just throw a bunch of those views on your scrollview.

ABCView.m

@implementation ABCDayView

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        self.backgroundColor = [UIColor whiteColor];
        self.layer.masksToBounds = NO;
        self.layer.cornerRadius = 3.0;
        self.layer.shadowOffset = CGSizeMake(1.1f, 2.1f);
        self.layer.shadowOpacity = 0.2f;
    }
    return self;
}

- (void)setItems:(NSArray *)items
{
    if ([_items isEqualToArray:items] == NO) {
        _items = items;
        [self createItemViews];
        [self setNeedsLayout];
    }
}

// You'll also need to add -createItemViews and -setNeedsLayout methods.

.m file

- (void)configureScrollView
{
    NSMutableArray *entreeItems = @[@"Pancakes w/Sausage Patties",
                                    @"Corn Dog",
                                    @"Grilled Cheese Sandwhich",
                                    @"Chicken Tender Wraps"];

    CGRect frame = CGRectMake(15,15,290,180);
    ABCDayView *elementaryView = [[ABCDayView alloc] initWithFrame:frame];
    elementaryView.items = entreeItems;

    CGFloat y = CGRectGetMaxY(elementaryView.frame) + 10.0f;
    frame = CGRectMake(15, y, 290, 180);
    ABCDayView *middleView = [[ABCDayView alloc] initWithFrame:frame];
    middleView.items = entreeItems;

    ...

    CGFloat length = // Use CGRectGetMaxY on the last frame to get the length.
    self.scrollView.contentSize = CGSizeMake(320, length);
}

That's by no means perfect code. But hopefully it will give you an idea of a better way to implement this.

Dave Batton
  • 8,795
  • 1
  • 46
  • 50