Properties Accessor Method Implementation - ios

I'm trying to make another custom view available at rood VC's viewdidload.
MSHView *customTextView = [[MSHView alloc] initWithFrame:self.view.bounds];
customTextView.textView.text = #"abc";
[customTextView layoutSubviews];
[self.view addSubview:customTextView];
MSHView Header file:
#property(nonatomic, strong) UITextView * textView;
#property (nonatomic, strong) UIImageView* translucentIV;
MSHView implementaion file:
-(UIImageView*) translucentIV {
if(!_translucentIV) {
_translucentIV.frame = self.frame;
//NSLog(#"frame for translucent IV, %#", _translucentIV.frame);
_translucentIV.backgroundColor = [UIColor whiteColor];
_translucentIV.alpha = 0.5;
}
return _translucentIV;
}
-(UITextView* ) textView{
if(!_textView){
/*
float height = self.bounds.size.height - 5;
float width = self.bounds.size.width - 5;
_textView.frame = CGRectMake(5,5,width,height);
_textView.text = #"test text";
*/
NSLog(#"textview property being initialized");
}
return _textView;
}
-(void)layoutSubviews {
self.textView.frame = self.frame;
self.translucentIV.backgroundColor = [UIColor whiteColor];
self.alpha = 0.5;
NSString *abc = #"abc";
self.textView.text = [NSString stringWithFormat:#"%#",abc];
NSLog(#"layout subview being called");
}
-(void) setTextView:(UITextView *)textView {
if(textView != _textView) {
_textView = textView;
_textView.text = #"setter method called";
}
}
Still cannot see the textview from MSHView. I think I'm not doing properties properly. any help or explanation?
Thanks in advance.

You are not creating the UIImageView and UITextView.
Try something more like:
-(UIImageView*) translucentIV {
if(!_translucentIV) {
_translucentIV = [[UIImageView alloc] initWithFrame:self.frame];
//NSLog(#"frame for translucent IV, %#", _translucentIV.frame);
_translucentIV.backgroundColor = [UIColor whiteColor];
_translucentIV.alpha = 0.5;
}
return _translucentIV;
}
-(UITextView *)textView {
if(!_textView) {
float height = self.bounds.size.height - 5;
float width = self.bounds.size.width - 5;
_textView = [[UITextView alloc] initWithFrame:CGRectMake(5,5,width,height)];
}
return _textView;
}
You'll also want to add them to the parent view somewhere.

Related

Detect button click event on customcell

I have added a custom cell as follows for stepper progress. UI perspective, it looks what I want, but I could not able to figure out how I could able to determine whether or not button has been clicked.
I have inspired via https://github.com/yenbekbay/AYStepperView, but this one has PageViewController which I could not able to add it in the tableCell.
#import "StepperProgressTableViewCell.h"
#import "AYStepperView.h"
static CGFloat const kFormStepperViewHeight = 80;
#interface StepperProgressTableViewCell ()
#property (nonatomic) AYStepperView *stepperView;
#property (nonatomic) NSUInteger currentIndex;
#property (nonatomic) NSUInteger currentStep;
#end
#implementation StepperProgressTableViewCell
- (void)awakeFromNib {
[super awakeFromNib];
// Initialization code
[self setUpViews];
self.currentIndex = 0;
self.currentStep = 0;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
}
#pragma mark Private
- (void)setUpViews {
self.stepperView = [[AYStepperView alloc]initWithFrame:CGRectMake(0, 40 , self.frame.size.width, kFormStepperViewHeight)
titles:#[NSLocalizedString(#"Start", nil),
NSLocalizedString(#"Cooking", nil),
NSLocalizedString(#"Ready", nil)]];
self.stepperView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin;
self.stepperView.userInteractionEnabled = YES;
[self addSubview:self.stepperView];
self.containerView = [[UIView alloc] initWithFrame:CGRectMake(0, CGRectGetMaxY(self.stepperView.frame), CGRectGetWidth(self.bounds), CGRectGetHeight(self.bounds) - CGRectGetMaxY(self.stepperView.frame))];
[self addSubview:self.containerView];
}
#end
AYStepperView.m
#import "AYStepperView.h"
#import <pop/POP.h>
static UIEdgeInsets const kStepperViewPadding = {
15, 0, 15, 0
};
static CGFloat const kStepperLabelsSpacing = 10;
static CGFloat const kStepperPipeHeight = 5;
#interface AYStepperView ()
#property (nonatomic) UIView *pipeView;
#property (nonatomic) UIView *labelsView;
#property (nonatomic) UIView *pipeBackgroundView;
#property (nonatomic) UIView *pipeFillView;
#property (nonatomic) NSMutableArray *stepLabels;
#end
#implementation AYStepperView
#pragma mark Initialization
- (instancetype)initWithFrame:(CGRect)frame titles:(NSArray *)titles {
self = [super initWithFrame:frame];
if (!self) {
return nil;
}
_titles = titles;
self.backgroundColor = [UIColor colorWithRed:0.98f green:0.98f blue:0.98f alpha:1];
self.tintColor = [UIColor colorWithRed:0.2f green:0.29f blue:0.37f alpha:1];
self.pipeView = [[UIView alloc] initWithFrame:CGRectMake(kStepperViewPadding.left, kStepperViewPadding.top, CGRectGetWidth(self.bounds) - kStepperViewPadding.left - kStepperViewPadding.right, CGRectGetHeight(self.bounds) / 2 - kStepperViewPadding.top)];
[self addSubview:self.pipeView];
self.labelsView = [[UIView alloc] initWithFrame:CGRectMake(kStepperViewPadding.left, CGRectGetMaxY(self.pipeView.frame) + kStepperViewPadding.top, CGRectGetWidth(self.bounds) - kStepperViewPadding.left - kStepperViewPadding.right, CGRectGetHeight(self.bounds) / 2 - kStepperViewPadding.top - kStepperViewPadding.bottom)];
[self addSubview:self.labelsView];
self.pipeBackgroundView = [[UIView alloc] initWithFrame:CGRectMake(0, (CGRectGetHeight(self.pipeView.bounds) - kStepperPipeHeight) / 2, CGRectGetWidth(self.pipeView.bounds), kStepperPipeHeight)];
self.pipeBackgroundView.backgroundColor = [UIColor lightGrayColor];
[self.pipeView addSubview:self.pipeBackgroundView];
CGRect pipeFillViewFrame = self.pipeBackgroundView.frame;
pipeFillViewFrame.size.width = 0;
self.pipeFillView = [[UIView alloc] initWithFrame:pipeFillViewFrame];
self.pipeFillView.backgroundColor = self.tintColor;
[self.pipeView addSubview:self.pipeFillView];
_stepButtons = [NSMutableArray new];
_stepLabels = [NSMutableArray new];
for (NSUInteger i = 0; i < titles.count; i++) {
UIButton *stepButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, CGRectGetHeight(self.pipeView.bounds), CGRectGetHeight(self.pipeView.bounds))];
stepButton.center = CGPointMake(CGRectGetWidth(self.pipeView.bounds) * (i + 0.5f) / titles.count, stepButton.center.y);
stepButton.clipsToBounds = YES;
stepButton.tag = i;
stepButton.layer.cornerRadius = CGRectGetHeight(stepButton.bounds) / 2;
stepButton.backgroundColor = [UIColor lightGrayColor];
[self.pipeView addSubview:stepButton];
[self.stepButtons addObject:stepButton];
UILabel *stepLabel = [UILabel new];
stepLabel.font = [UIFont systemFontOfSize:[UIFont smallSystemFontSize]];
stepLabel.textColor = self.tintColor;
stepLabel.textAlignment = NSTextAlignmentCenter;
stepLabel.text = titles[i];
stepLabel.numberOfLines = 0;
stepLabel.frame = (CGRect) {
stepLabel.frame.origin, [stepLabel sizeThatFits:CGSizeMake(CGRectGetWidth(self.pipeView.bounds) / titles.count - kStepperLabelsSpacing, 0)]
};
stepLabel.center = CGPointMake(CGRectGetWidth(self.labelsView.bounds) * (i + 0.5f) / titles.count, CGRectGetHeight(self.labelsView.bounds) / 2);
[self.labelsView addSubview:stepLabel];
[self.stepLabels addObject:stepLabel];
}
_currentStepIndex = 0;
[self completeStepAtIndex:0 until:1 completionBlock:nil];
return self;
}
#pragma mark Public
- (void)updateCurrentStepIndex:(NSUInteger)currentStepIndex completionBlock:(void (^)())completionBlock {
if (currentStepIndex >= self.titles.count || currentStepIndex == self.currentStepIndex) {
if (completionBlock) {
completionBlock();
}
} else {
NSUInteger previousStepIndex = self.currentStepIndex;
_currentStepIndex = currentStepIndex;
if ((NSInteger)currentStepIndex - (NSInteger)previousStepIndex > 0) {
[self completeStepAtIndex:previousStepIndex + 1 until:currentStepIndex + 1 completionBlock:completionBlock];
} else {
[self uncompleteStepAtIndex:previousStepIndex until:currentStepIndex - 1 completionBlock:completionBlock];
}
}
}
#pragma mark Setters
- (void)setTintColor:(UIColor *)tintColor {
_tintColor = tintColor;
self.pipeFillView.backgroundColor = tintColor;
for (UILabel *label in self.stepLabels) {
label.textColor = tintColor;
}
[self.stepButtons[self.currentStepIndex] setBackgroundColor:tintColor];
}
#pragma mark Private
- (void)completeStepAtIndex:(NSUInteger)index until:(NSUInteger)until completionBlock:(void (^)())completionBlock {
if (index == until) {
if (completionBlock) {
completionBlock();
}
} else {
[UIView animateWithDuration:0.2f animations:^{
CGRect pipeFillViewFrame = self.pipeFillView.frame;
NSLog(#"%lu, %lu",until, index);
if(index == _titles.count - 1)
{
pipeFillViewFrame.size.width = CGRectGetWidth(self.pipeBackgroundView.bounds) * (index + 1.0f) / self.titles.count;
}
else
{
pipeFillViewFrame.size.width = CGRectGetWidth(self.pipeBackgroundView.bounds) * (index + 0.5f) / self.titles.count;
}
self.pipeFillView.frame = pipeFillViewFrame;
} completion:^(BOOL finishedWidthAnimation) {
[self completeStepAtIndex:index + 1 until:until completionBlock:completionBlock];
UIView *stepButton = self.stepButtons[index];
stepButton.backgroundColor = self.tintColor;
POPSpringAnimation *scaleAnimation = [POPSpringAnimation animationWithPropertyNamed:kPOPLayerScaleXY];
scaleAnimation.velocity = [NSValue valueWithCGSize:CGSizeMake(3.f, 3.f)];
scaleAnimation.toValue = [NSValue valueWithCGSize:CGSizeMake(1.f, 1.f)];
scaleAnimation.springBounciness = 5.f;
[stepButton.layer pop_addAnimation:scaleAnimation forKey:#"scaleAnimation"];
}];
}
}
- (void)uncompleteStepAtIndex:(NSUInteger)index until:(NSUInteger)until completionBlock:(void (^)())completionBlock {
if (index == until) {
if (completionBlock) {
completionBlock();
}
} else {
if (index > until + 1) {
UIView *stepButton = self.stepButtons[index];
stepButton.backgroundColor = [UIColor lightGrayColor];
POPSpringAnimation *scaleAnimation = [POPSpringAnimation animationWithPropertyNamed:kPOPLayerScaleXY];
scaleAnimation.velocity = [NSValue valueWithCGSize:CGSizeMake(3.f, 3.f)];
scaleAnimation.toValue = [NSValue valueWithCGSize:CGSizeMake(1.f, 1.f)];
scaleAnimation.springBounciness = 5.f;
[stepButton.layer pop_addAnimation:scaleAnimation forKey:#"scaleAnimation"];
}
[UIView animateWithDuration:0.2f animations:^{
CGRect pipeFillViewFrame = self.pipeFillView.frame;
pipeFillViewFrame.size.width = CGRectGetWidth(self.pipeBackgroundView.bounds) * (index + 0.5f) / self.titles.count;
self.pipeFillView.frame = pipeFillViewFrame;
} completion:^(BOOL finishedWidthAnimation) {
[self uncompleteStepAtIndex:index - 1 until:until completionBlock:completionBlock];
}];
}
}
#end
If you want to catch events from a cell to the view controller, the simplest way is to create a protocol and set the view controller as the cell's delegate. I'm sure there are many similar questions here that can help you like this one for example.

iOS Implicit conversion of 'int' to 'UIColor*' is disallowed with ARC

I have a pickerview that is getting its information from a separate AFPickerView file. I'm getting the error "Implicit conversion of 'int' to 'UIColor*' is disallowed with ARC". Any suggestions on an easy fix for this?
Here is the code that it effects:
[visibleViews minusSet:recycledViews];
// add missing pages
for (int index = firstNeededViewIndex; index <= lastNeededViewIndex; index++)
{
if (![self isDisplayingViewForIndex:index])
{
UILabel *label = (UILabel *)[self dequeueRecycledView];
if (label == nil)
{
label = [[UILabel alloc] initWithFrame:CGRectMake(_rowIndent, 0, self.frame.size.width - _rowIndent, 39.0)];
label.backgroundColor = [UIColor clearColor];
label.font = self.rowFont;
label.textColor = RGBACOLOR(0.0, 0.0, 0.0, 0.75);
}
[self configureView:label atIndex:index];
[contentView addSubview:label];
[visibleViews addObject:label];
}
}
}
Here is the full code:
#import "AFPickerView.h"
#implementation AFPickerView
#pragma mark - Synthesization
#synthesize dataSource;
#synthesize delegate;
#synthesize selectedRow = currentRow;
#synthesize rowFont = _rowFont;
#synthesize rowIndent = _rowIndent;
#pragma mark - Custom getters/setters
- (void)setSelectedRow:(int)selectedRow
{
if (selectedRow >= rowsCount)
return;
currentRow = selectedRow;
[contentView setContentOffset:CGPointMake(0.0, 39.0 * currentRow) animated:NO];
}
- (void)setRowFont:(UIFont *)rowFont
{
_rowFont = rowFont;
for (UILabel *aLabel in visibleViews)
{
aLabel.font = _rowFont;
}
for (UILabel *aLabel in recycledViews)
{
aLabel.font = _rowFont;
}
}
- (void)setRowIndent:(CGFloat)rowIndent
{
_rowIndent = rowIndent;
for (UILabel *aLabel in visibleViews)
{
CGRect frame = aLabel.frame;
frame.origin.x = _rowIndent;
frame.size.width = self.frame.size.width - _rowIndent;
aLabel.frame = frame;
}
for (UILabel *aLabel in recycledViews)
{
CGRect frame = aLabel.frame;
frame.origin.x = _rowIndent;
frame.size.width = self.frame.size.width - _rowIndent;
aLabel.frame = frame;
}
}
#pragma mark - Initialization
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self)
{
// setup
[self setup];
// backgound
UIImageView *bacground = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"pickerBackground.png"]];
[self addSubview:bacground];
// content
contentView = [[UIScrollView alloc] initWithFrame:CGRectMake(0.0, 0.0, frame.size.width, frame.size.height)];
contentView.showsHorizontalScrollIndicator = NO;
contentView.showsVerticalScrollIndicator = NO;
contentView.delegate = self;
[self addSubview:contentView];
UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(didTap:)];
[contentView addGestureRecognizer:tapRecognizer];
// shadows
UIImageView *shadows = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"pickerShadows.png"]];
[self addSubview:shadows];
// glass
UIImage *glassImage = [UIImage imageNamed:#"pickerGlass.png"];
glassImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0.0, 76.0, glassImage.size.width, glassImage.size.height)];
glassImageView.image = glassImage;
[self addSubview:glassImageView];
}
return self;
}
- (void)setup
{
_rowFont = [UIFont boldSystemFontOfSize:24.0];
_rowIndent = 30.0;
currentRow = 0;
rowsCount = 0;
visibleViews = [[NSMutableSet alloc] init];
recycledViews = [[NSMutableSet alloc] init];
}
#pragma mark - Buisness
- (void)reloadData
{
// empry views
currentRow = 0;
rowsCount = 0;
for (UIView *aView in visibleViews)
[aView removeFromSuperview];
for (UIView *aView in recycledViews)
[aView removeFromSuperview];
visibleViews = [[NSMutableSet alloc] init];
recycledViews = [[NSMutableSet alloc] init];
rowsCount = [dataSource numberOfRowsInPickerView:self];
[contentView setContentOffset:CGPointMake(0.0, 0.0) animated:NO];
contentView.contentSize = CGSizeMake(contentView.frame.size.width, 39.0 * rowsCount + 4 * 39.0);
[self tileViews];
}
- (void)determineCurrentRow
{
CGFloat delta = contentView.contentOffset.y;
int position = round(delta / 39.0);
currentRow = position;
[contentView setContentOffset:CGPointMake(0.0, 39.0 * position) animated:YES];
[delegate pickerView:self didSelectRow:currentRow];
}
- (void)didTap:(id)sender
{
UITapGestureRecognizer *tapRecognizer = (UITapGestureRecognizer *)sender;
CGPoint point = [tapRecognizer locationInView:self];
int steps = floor(point.y / 39) - 2;
[self makeSteps:steps];
}
- (void)makeSteps:(int)steps
{
if (steps == 0 || steps > 2 || steps < -2)
return;
[contentView setContentOffset:CGPointMake(0.0, 39.0 * currentRow) animated:NO];
int newRow = currentRow + steps;
if (newRow < 0 || newRow >= rowsCount)
{
if (steps == -2)
[self makeSteps:-1];
else if (steps == 2)
[self makeSteps:1];
return;
}
currentRow = currentRow + steps;
[contentView setContentOffset:CGPointMake(0.0, 39.0 * currentRow) animated:YES];
[delegate pickerView:self didSelectRow:currentRow];
}
#pragma mark - recycle queue
- (UIView *)dequeueRecycledView
{
UIView *aView = [recycledViews anyObject];
if (aView)
[recycledViews removeObject:aView];
return aView;
}
- (BOOL)isDisplayingViewForIndex:(NSUInteger)index
{
BOOL foundPage = NO;
for (UIView *aView in visibleViews)
{
int viewIndex = aView.frame.origin.y / 39.0 - 2;
if (viewIndex == index)
{
foundPage = YES;
break;
}
}
return foundPage;
}
- (void)tileViews
{
// Calculate which pages are visible
CGRect visibleBounds = contentView.bounds;
int firstNeededViewIndex = floorf(CGRectGetMinY(visibleBounds) / 39.0) - 2;
int lastNeededViewIndex = floorf((CGRectGetMaxY(visibleBounds) / 39.0)) - 2;
firstNeededViewIndex = MAX(firstNeededViewIndex, 0);
lastNeededViewIndex = MIN(lastNeededViewIndex, rowsCount - 1);
// Recycle no-longer-visible pages
for (UIView *aView in visibleViews)
{
int viewIndex = aView.frame.origin.y / 39 - 2;
if (viewIndex < firstNeededViewIndex || viewIndex > lastNeededViewIndex)
{
[recycledViews addObject:aView];
[aView removeFromSuperview];
}
}
[visibleViews minusSet:recycledViews];
// add missing pages
for (int index = firstNeededViewIndex; index <= lastNeededViewIndex; index++)
{
if (![self isDisplayingViewForIndex:index])
{
UILabel *label = (UILabel *)[self dequeueRecycledView];
if (label == nil)
{
label = [[UILabel alloc] initWithFrame:CGRectMake(_rowIndent, 0, self.frame.size.width - _rowIndent, 39.0)];
label.backgroundColor = [UIColor clearColor];
label.font = self.rowFont;
label.textColor = RGBACOLOR(0.0, 0.0, 0.0, 0.75);
}
[self configureView:label atIndex:index];
[contentView addSubview:label];
[visibleViews addObject:label];
}
}
}
- (void)configureView:(UIView *)view atIndex:(NSUInteger)index
{
UILabel *label = (UILabel *)view;
label.text = [dataSource pickerView:self titleForRow:index];
CGRect frame = label.frame;
frame.origin.y = 39.0 * index + 78.0;
label.frame = frame;
}
#pragma mark - UIScrollViewDelegate
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
[self tileViews];
}
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{
if (!decelerate)
[self determineCurrentRow];
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
[self determineCurrentRow];
}
#end
This should work with ARC. Replace RGBACOLOR with colorWithRed:green:blue:alpha
label.textColor = [UIColor colorWithRed:0.0f green:0.0f blue:0.0f alpha:0.75f];

Core Animation Strange Display after addSubview then removeFromSuperview

I have a view controller with a central container that gets flipped to show different views on each side. One of the views is a table view and the other is a custom view of mine. It is working perfectly as per screenshot 1.
My problem is that after I have added a subview over this viewcontroller (its a transparent UIView for showing help screen) and then remove this subview from the viewcontroller
, when I try re-flip the central view strange results occur. There still seems to be a flipping animation between the two views, but as you can see from the last 2 screenshot an extra central table view just sits there. I can't quite explain this exactly so I'm hoping a combination of the pictures, and some code will help:
MainPageVC.h
#interface MainPageVC : UIViewController <UITableViewDataSource, UITableViewDelegate>
#end
MainPageVC.m
#interface MainPageVC ()
#property (nonatomic, strong) NSArray *dataArr;
#property (nonatomic, weak) IBOutlet UIView *flipContainerView;
#property (nonatomic, strong) UIView *detailFlipView;
#property (nonatomic, strong) UITableView *listFlipView;
#property (nonatomic) BOOL isTransitioning;
#property (nonatomic) BOOL isFlipped;
#end
#implementation MainPageVC
#synthesize dataArr = _dataArr;
#synthesize flipContainerView = _flipContainerView;
#synthesize detailFlipView = _detailFlipView;
#synthesize listFlipView = _listFlipView;
#synthesize isTransitioning = _isTransitioning;
#synthesize isFlipped = _isFlipped;
- (void)viewDidLoad {
[super viewDidLoad];
self.dataArr = [NSArray arrayWithObjects:#"row 1", #"row 2", #"row 3", nil];;
}
- (void)viewDidLayoutSubviews {
[self setUpCustomViews];
}
- (void)setUpCustomViews {
self.isFlipped = NO;
self.isTransitioning = NO;
CGRect frame = CGRectMake(0, 0, self.flipContainerView.frame.size.width, self.flipContainerView.frame.size.height);
self.detailFlipView = [[UIView alloc] initWithFrame:frame];
UIView *customView = [[UIView alloc] initWithFrame:CGRectMake(0,0,50,50)];
[self.detailFlipView addSubview:customView];
self.listFlipView = [[UITableView alloc] initWithFrame:frame];
self.listFlipView.delegate = self;
self.listFlipView.dataSource = self;
UIColor *backgroundColour = [UIColor whiteColor];
CGFloat cornerRadius = 15.0f;
CGFloat borderWidth = 1.5f;
UIColor *borderColour = [UIColor colorWithRed:49.0/255.0f green:49.0/255.0f blue:49.0/255.0f alpha:1.0f];
self.detailFlipView.backgroundColor = backgroundColour;
self.listFlipView.backgroundColor = backgroundColour;
self.detailFlipView.layer.cornerRadius = cornerRadius;
self.listFlipView.layer.cornerRadius = cornerRadius;
self.detailFlipView.layer.borderWidth = borderWidth;
self.listFlipView.layer.borderWidth = borderWidth;
self.detailFlipView.layer.borderColor = [borderColour CGColor];
self.listFlipView.layer.borderColor = [borderColour CGColor];
self.detailFlipView.layer.doubleSided = NO;
self.listFlipView.layer.doubleSided = NO;
self.listFlipView.layer.masksToBounds = YES;
self.detailFlipView.layer.masksToBounds = YES;
[self.flipContainerView addSubview:self.detailFlipView];
[self.flipContainerView addSubview:self.listFlipView];
}
- (IBAction)changeViewTapped:(UIControl *)sender {
if (self.isTransitioning) return;
CALayer *top = self.listFlipView.layer;
CALayer *bottom = self.detailFlipView.layer;
if (self.isFlipped) {
top = self.detailFlipView.layer;
bottom = self.listFlipView.layer;
}
CAAnimation *topAnimation = [self flipAnimationWithDuration:0.6f forLayerBeginningOnTop:YES scaleFactor:1.2f];
CAAnimation *bottomAnimation = [self flipAnimationWithDuration:0.6f forLayerBeginningOnTop:NO scaleFactor:1.2f];
CGFloat zDistance = 1000.0f;
CATransform3D perspective = CATransform3DIdentity;
perspective.m34 = -1. / zDistance;
top.transform = perspective;
bottom.transform = perspective;
topAnimation.delegate = self;
[CATransaction begin];
[top addAnimation:topAnimation forKey:#"flip"];
[bottom addAnimation:bottomAnimation forKey:#"flip"];
CABasicAnimation *colorAnimation = [CABasicAnimation animationWithKeyPath:#"backgroundColor"];
colorAnimation.toValue = (id)[UIColor colorWithRed:27.0/255.0f green:47.0/255.0f blue:87.0/255.0f alpha:1.0f].CGColor;
[self.bannerButtonImageView.layer addAnimation:colorAnimation forKey:#"colorAnimation"];
[CATransaction commit];
}
-(CAAnimation *)flipAnimationWithDuration:(NSTimeInterval)aDuration forLayerBeginningOnTop:(BOOL)beginsOnTop scaleFactor:(CGFloat)scaleFactor {
self.isTransitioning = YES;
CABasicAnimation *flipAnimation = [CABasicAnimation animationWithKeyPath:#"transform.rotation.y"];
CGFloat startValue = beginsOnTop ? 0.0f : M_PI;
CGFloat endValue = beginsOnTop ? -M_PI : 0.0f;
flipAnimation.fromValue = [NSNumber numberWithDouble:startValue];
flipAnimation.toValue = [NSNumber numberWithDouble:endValue];
CABasicAnimation *shrinkAnimation = nil;
if (scaleFactor != 1.0f ) {
shrinkAnimation = [CABasicAnimation animationWithKeyPath:#"transform.scale"];
shrinkAnimation.toValue = [NSNumber numberWithFloat:scaleFactor];
shrinkAnimation.duration = aDuration * 0.5;
shrinkAnimation.autoreverses = YES;
}
CAAnimationGroup *animationGroup = [CAAnimationGroup animation];
animationGroup.animations = [NSArray arrayWithObjects:flipAnimation, shrinkAnimation, nil];
animationGroup.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
animationGroup.duration = aDuration;
animationGroup.fillMode = kCAFillModeForwards;
animationGroup.removedOnCompletion = NO;
return animationGroup;
}
-(void)animationDidStop:(CAAnimation *)animation finished:(BOOL)flag {
self.isFlipped = !self.isFlipped;
self.isTransitioning = NO;
}
...USUAL UITABLEVIEW METHODS
- (void)showHelpScreen {
CustomHelp *helpView = [[CustomHelp alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
[self.view addSubview:helpView];
}
#end
CustomHelp.h
#interface CustomHelp : UIView
#end
CustomHelp.m
#implementation CustomHelp
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
UIView *test = [[UIView alloc] initWithFrame:CGRectMake(20, 20, 50, 100)];
test.backgroundColor = [UIColor redColor];
[self addSubview:test];
UITapGestureRecognizer* singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleSingleTap)];
singleTap.numberOfTapsRequired = 1;
singleTap.numberOfTouchesRequired = 1;
[self addGestureRecognizer: singleTap];
}
return self;
}
- (void)handleSingleTap {
[UIView animateWithDuration:0.5
animations:^{ self.alpha = 0.0;}
completion:^(BOOL finished){
[self removeFromSuperview];
}];
}
#end
Adding comment as answer.
My only suggestion would be in the setUpCustomViews function to add in an if(!self.listFlipView) and if(!self.detailFlipView) to the view creation. That function may be being called multiple times and thereby adding multiple views to your window without removing the previous one.

Set Background Color For Part Of Label iOS

Is it possible to set the background color for parts of a label? I'm trying to create something similar to the tags section at the bottom of this post that word wraps and char wraps when necessary. Also, the text blocks can be multiple words. Basically I need something like:
[label setBackgroundColor:UIColor forRange:NSRange];
I need to support iOS 5.0+.
I wasn't able to get it working using NSAttributedString. Here's my solution. It's not super clean, but it works okay. Phrases is an array of NSStrings. Each phrase can be a single word or multiple words.
-(void)addBackgroundsToContainer:(UIView*)container color:(UIColor*)color phrases:(NSArray*)phrases {
CGFloat x = 0.0;
CGFloat y = 0.0;
UIView *lbl;
for(NSString *phrase in phrases) {
NSLog(#"Phrase: '%#'", phrase);
NSArray *words = [phrase componentsSeparatedByString:#" "];
NSString *text = #"";
for(int i = 0; i < words.count; i++) {
NSString *word = [words objectAtIndex:i];
CGSize wordSize = [word sizeWithFont:[self labelFont]];
CGSize textSize = [text sizeWithFont:[self labelFont]];
//if the word appended with the new text fits on one line, concatenate the two
if(textSize.width + wordSize.width + x < container.frame.size.width) {
text = [text isEqualToString:#""] ? word : [NSString stringWithFormat:#"%# %#", text, word];
if(i == words.count -1 ) {//add the label if it's the last word
lbl = [self addLabelWithX:x y:y container:container color:color text:text];
x = lbl.frame.size.width + lbl.frame.origin.x + 1.0;
text = #"";
}
//if the word fits on one line but can't fit on the current line.
} else if(wordSize.width < container.frame.size.width) {
//if it's not the first word, add the text that came before it
if(i != 0) {
lbl = [self addLabelWithX:x width:container.frame.size.width - x y:y container:container color:color text:text];
}
x = 0.0;
y = lbl.frame.size.height + lbl.frame.origin.y + 1.0;
text = word;
//if it's the last word
if(i == words.count - 1) {
lbl = [self addLabelWithX:x y:y container:container color:color text:text];
x = lbl.frame.size.width + lbl.frame.origin.x + 1.0;
text = #"";
}
//if the word doesn't fit on one line and it
} else if(wordSize.width > container.frame.size.width) {
//I don't need to do char wrapping, but this would be where it'd go
}
}
}
}
-(UIView*)addLabelWithX:(CGFloat)x y:(CGFloat)y container:(UIView*)container color:(UIColor*)color text:(NSString*)text {
CGFloat width = [text sizeWithFont:[self labelFont]].width + 4.0;
return [self addLabelWithX:x width:width y:y container:container color:color text:text];
}
-(UIView*)addLabelWithX:(CGFloat)x width:(CGFloat)width y:(CGFloat)y container:(UIView*)container color:(UIColor*)color text:(NSString*)text {
CGFloat lineHeight = [#" " sizeWithFont:[self labelFont]].height;
UILabel *lbl = [[UILabel alloc] initWithFrame:CGRectMake(2.0, 0.0, width, lineHeight)];
[lbl setBackgroundColor:[UIColor clearColor]];
[lbl setTextColor:[UIColor whiteColor]];
[lbl setText:text];
[lbl setFont:[self labelFont]];
UIView *v = [[UIView alloc] initWithFrame:CGRectMake(x, y, width, lbl.frame.size.height)];
[v setBackgroundColor:color];
[v addSubview:lbl];
[container addSubview:v];
return v;
}
-(UIFont*)labelFont {
return [UIFont fontWithName:#"Lato-Regular" size:12.0];
}
EDIT: I went back and made this less terrible
.h
#import <UIKit/UIKit.h>
#protocol WATagCloudDelegate;
#interface WATagCloud : UIView
#property(weak, nonatomic) id<WATagCloudDelegate> delegate;
#property(strong, nonatomic) NSArray *dataTags;
#property(strong, nonatomic) UIColor *tagColor;
#property(strong, nonatomic) UIFont *tagFont;
-(void)expand;
-(void)expandWithAnimation;
-(void)collapse;
-(void)collapseWithAnimation;
#end
#protocol WATagCloudDelegate <NSObject>
#required
-(void)tagCloudExpandDown:(WATagCloud*)tagCloud;
-(void)tagCloudCollapseDown:(WATagCloud*)tagCloud;
#end
.m
#import "WATagCloud.h"
#import "WAControlsUtility.h"
#interface WATagCloud()
#property(strong, nonatomic) UIButton *btnToggleVisibility;
#property(strong, nonatomic) UIView *vExpand;
#property(strong, nonatomic) UILabel *lblExpand;
#end
#implementation WATagCloud
#synthesize dataTags = _dataTags;
#synthesize tagColor = _tagColor;
#synthesize tagFont = _tagFont;
#synthesize btnToggleVisibility;
#synthesize vExpand;
#synthesize lblExpand;
-(void)setTagColor:(UIColor *)color {
_tagColor = color;
[self setColorOfSubviews];
}
-(void)setDataTags:(NSArray *)tags {
_dataTags = tags;
[self addTags];
}
-(UIFont*)tagFont {
if(_tagFont) {
return _tagFont;
} else {
_tagFont = [UIFont fontWithName:#"Lato-Regular" size:14.0];
return _tagFont;
}
}
-(void)setTagFont:(UIFont *)font {
_tagFont = font;
[self addTags];
}
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
[self setClipsToBounds:YES];
self.btnToggleVisibility = [UIButton buttonWithType:UIButtonTypeCustom];
[self.btnToggleVisibility setFrame:CGRectMake(0.0, 0.0, self.frame.size.width, self.frame.size.height)];
[self.btnToggleVisibility addTarget:self action:#selector(onToggleVisibilityDown:) forControlEvents:UIControlEventTouchUpInside];
[self addSubview:self.btnToggleVisibility];
self.vExpand = [[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, 0.0, 0.0)];
[self addSubview:self.vExpand];
self.lblExpand = [[UILabel alloc] initWithFrame:CGRectMake(2.0, 0.0, 0.0, 0.0)];
[self.lblExpand setBackgroundColor:[UIColor clearColor]];
[self.lblExpand setTextColor:[UIColor whiteColor]];
[self.vExpand addSubview:self.lblExpand];
}
return self;
}
//======================================================================
//LAYOUT LABELS
//======================================================================
-(void)addTags {
[self clearTags];
CGFloat x = 0.0;
CGFloat y = 0.0;
UIView *lbl;
for(int j = 0; j < self.dataTags.count; j++) {
NSString *tag = [self.dataTags objectAtIndex:j];
NSArray *words = [tag componentsSeparatedByString:#" "];
NSString *text = #"";
for(int i = 0; i < words.count; i++) {
NSString *word = [words objectAtIndex:i];
CGSize wordSize = [word sizeWithFont:self.tagFont];
CGSize textSize = [text sizeWithFont:self.tagFont];
if(textSize.width + wordSize.width + x < self.frame.size.width) {//if the word appended with the new text fits on one line, concatenate the two
text = [text isEqualToString:#""] ? word : [NSString stringWithFormat:#"%# %#", text, word];
if(i == words.count -1 ) {//add the label if it's the last word
lbl = [self addLabelWithX:x y:y text:text tag:j];
x = lbl.frame.size.width + lbl.frame.origin.x + 1.0;
text = #"";
}
} else if(wordSize.width < self.frame.size.width) {//if the word fits on one line but can't fit on the current line.
//if it's not the first word, add the text that came before it
if(i != 0) {
lbl = [self addLabelWithX:x width:self.frame.size.width - x y:y text:text tag:j];
}
x = 0.0;
y = lbl.frame.size.height + lbl.frame.origin.y + 1.0;
text = word;
//if it's the last word
if(i == words.count - 1) {
lbl = [self addLabelWithX:x y:y text:text tag:j];
x = lbl.frame.size.width + lbl.frame.origin.x + 1.0;
text = #"";
}
} else if(wordSize.width > self.frame.size.width) {//if the word doesn't fit on one line
NSArray *characters = [self getCharacterArrayFromString:word];
}
}
}
//update the frame height
[self setFrame:[WAControlsUtility updateFrame:self.frame withX:nil y:nil width:nil height:[NSNumber numberWithFloat:[WAControlsUtility getHeightOfView:self]]]];
[self.btnToggleVisibility setFrame:CGRectMake(0.0, 0.0, self.frame.size.width, self.frame.size.height)];
}
//======================================================================
//ADD TO CONTAINER
//======================================================================
-(UIView*)addLabelWithX:(CGFloat)x y:(CGFloat)y text:(NSString*)text tag:(int)tag {
CGFloat width = [text sizeWithFont:[self tagFont]].width + 4.0;
return [self addLabelWithX:x width:width y:y text:text tag:tag];
}
-(UIView*)addLabelWithX:(CGFloat)x width:(CGFloat)width y:(CGFloat)y text:(NSString*)text tag:(int)tag {
CGFloat lineHeight = [#" " sizeWithFont:[self tagFont]].height;
UILabel *lbl = [[UILabel alloc] initWithFrame:CGRectMake(2.0, 0.0, width, lineHeight)];
[lbl setBackgroundColor:[UIColor clearColor]];
[lbl setTextColor:[UIColor whiteColor]];
[lbl setText:text];
[lbl setFont:[self tagFont]];
UIView *v = [[UIView alloc] initWithFrame:CGRectMake(x, y, width, lbl.frame.size.height)];
[v setBackgroundColor:self.tagColor];
[v setTag:tag];
[v addSubview:lbl];
[self addSubview:v];
return v;
}
//======================================================================
//UI EVENTS
//======================================================================
-(void)onToggleVisibilityDown:(id)sender {
if(self.delegate ==nil)
return;
if(self.frame.size.height > [#" " sizeWithFont:[self tagFont]].height * 2.0 + 2) {//plus 2 for the spacing between lines
[self.delegate tagCloudCollapseDown:self];
} else {
[self.delegate tagCloudExpandDown:self];
}
}
//======================================================================
//PUBLIC METHODS
//======================================================================
//EXPAND
-(void)expand {
[self modifyViewsForExpanding];
[self setFrame:[WAControlsUtility updateFrame:self.frame withX:nil y:nil width:nil height:[NSNumber numberWithFloat:[WAControlsUtility getHeightOfView:self]]]];
[self.btnToggleVisibility setFrame:CGRectMake(0.0, 0.0, self.frame.size.width, self.frame.size.height)];
[self bringSubviewToFront:self.btnToggleVisibility];
}
-(void)expandWithAnimation {
[UIView animateWithDuration:.4 animations:^{
[self expand];
}];
}
//COLLAPSE
-(void)collapse {
CGFloat height = [#" " sizeWithFont:[self tagFont]].height * 2.0 + 2;//plus 2 for the spacing between lines
[self setFrame:[WAControlsUtility updateFrame:self.frame withX:nil y:nil width:nil height:[NSNumber numberWithFloat:height]]];
[self.btnToggleVisibility setFrame:CGRectMake(0.0, 0.0, self.frame.size.width, self.frame.size.height)];
[self modifyViewsForCollapsing];
[self bringSubviewToFront:self.btnToggleVisibility];
}
-(void)collapseWithAnimation {
[UIView animateWithDuration:.4 animations:^{
[self collapse];
}];
}
//======================================================================
//UTILITY
//======================================================================
-(NSArray*)getCharacterArrayFromString:(NSString*)string {
NSMutableArray *characters = [[NSMutableArray alloc] initWithCapacity:[string length]];
for (int i=0; i < [string length]; i++) {
NSString *ichar = [NSString stringWithFormat:#"%c", [string characterAtIndex:i]];
[characters addObject:ichar];
}
return characters;
}
-(void)setColorOfSubviews {
for(UIView *view in self.subviews) {
if([view isKindOfClass:[UIButton class]] == NO) {
if(view != self.vExpand) {
[view setBackgroundColor:self.tagColor];
} else {
[view setBackgroundColor:[self.tagColor colorWithAlphaComponent:.5]];
}
}
}
}
-(void)clearTags {
[self.subviews makeObjectsPerformSelector:#selector(removeFromSuperview)];
[self addSubview:self.btnToggleVisibility];
[self addSubview:self.vExpand];
}
//EXPAND/COLLAPSE UTILITY
-(NSArray*)getNthRow:(int)nth {//starts at 1 //not zero based
NSMutableArray *rowViews = [[NSMutableArray alloc] initWithCapacity:self.subviews.count];
CGFloat rowOrigin = [#" " sizeWithFont:self.tagFont].height * (nth - 1) + (nth - 1);
for(UIView *view in self.subviews) {
if([view isEqual:self.btnToggleVisibility] || [view isEqual:self.vExpand]) {//ignore the button and expand view
continue;
}
if(view.frame.origin.y == rowOrigin) {
[rowViews addObject:view];
}
}
return rowViews;
}
-(UIView*)getGreatestXOriginViewForNthRow:(int)nthRow {
NSArray *rowViews = [self getNthRow:nthRow];
UIView *greatestXOriginView = nil;
for(UIView *view in rowViews) {
if(greatestXOriginView == nil || view.frame.origin.x > greatestXOriginView.frame.origin.x ) {
greatestXOriginView = view;
}
}
return greatestXOriginView;
}
-(void)modifyViewsForCollapsing {
if([self getNthRow:3].count == 0) {
return;
}
UIView *greatestXOriginView = [self getGreatestXOriginViewForNthRow:2];
//update the label and the container
[self.lblExpand setText:[NSString stringWithFormat:#"+%d", self.dataTags.count - greatestXOriginView.tag]];
[self.lblExpand setFont:self.tagFont];
[self.lblExpand setFrame:[WAControlsUtility updateFrame:self.lblExpand.frame withX:nil y:nil width:[NSNumber numberWithFloat:[self.lblExpand.text sizeWithFont:self.tagFont].width] height:[NSNumber numberWithFloat:greatestXOriginView.frame.size.height]]];
[self resizeLabelContainer];
//figure out where to place the expand and how to size it and the last label on the row
CGFloat viewXValue = (greatestXOriginView.frame.size.width + greatestXOriginView.frame.origin.x);
CGFloat expandXValue = self.frame.size.width - self.vExpand.frame.size.width;
CGFloat xOrigin;
if(viewXValue < expandXValue - 1.0) {//will it all fit without modifying any existing views
xOrigin = viewXValue + 1.0;
} else {//shrink the last view
[greatestXOriginView setFrame:[WAControlsUtility updateFrame:greatestXOriginView.frame withX:nil y:nil width:[NSNumber numberWithFloat:expandXValue - 1 - greatestXOriginView.frame.origin.x] height:nil]];
for(UIView *view in greatestXOriginView.subviews) {//shrink the label
[view setFrame:[WAControlsUtility updateFrame:view.frame withX:nil y:nil width:[NSNumber numberWithFloat:greatestXOriginView.frame.size.width - 4.0] height:nil]];
}
if(greatestXOriginView.frame.size.width < 20.0) {
[greatestXOriginView setAlpha:0.0];//hide the last view if it got shrank down a lot
}
xOrigin = expandXValue;
}
[self.vExpand setFrame:[WAControlsUtility updateFrame:self.vExpand.frame withX:[NSNumber numberWithFloat:xOrigin] y:[NSNumber numberWithFloat:greatestXOriginView.frame.origin.y] width:nil height:nil]];
[self.vExpand setAlpha:1.0];
[self resizeLabelContainer];
}
-(void)modifyViewsForExpanding {
UIView *view = [self getGreatestXOriginViewForNthRow:2];
UILabel *label;
if(view != nil) {
label = (UILabel*)view.subviews[0];
CGSize labelSize = [label.text sizeWithFont:self.tagFont];
[label setFrame:[WAControlsUtility updateFrame:label.frame withX:nil y:nil width:[NSNumber numberWithFloat:labelSize.width] height:nil]];
[view setFrame:[WAControlsUtility updateFrame:view.frame withX:nil y:nil width:[NSNumber numberWithFloat:labelSize.width + 4] height:nil]];
[view setAlpha:1.0];
}
//hide expand
[self.vExpand setAlpha:0.0];
}
-(void)resizeLabelContainer {
[self.vExpand setFrame:[WAControlsUtility updateFrame:self.vExpand.frame withX:nil y:nil width:[NSNumber numberWithFloat:self.lblExpand.frame.size.width + 4.0] height:[NSNumber numberWithFloat:self.lblExpand.frame.size.height]]];
}
#end
You can try to use NSAttributedString with the NSBackgroundColorAttributeName attribute. I haven't tried it though.

Leaks in my UIScrollView helper class

I want to publish tutorial about how to easily create an UIScrollView on http://www.xprogress.com/ and I just want to check with you guys if the code is alright before I publish anything. Any help will be appreciated and I'll put your name / website on the bottom of the article :)
Thanks a lot :)
Ondrej
header file:
///
/// IGUIScrollViewImage.h
///
/// IGUILibrary
///
/// Created by Ondrej Rafaj on 7.4.10.
///
/// Copyright 2010 Home. All rights reserved.
///
/// #todo enable margin and center the image to the middle of the view
/**
<b>Examples:</b>
<i>This is just a short example how to use this class</i>
<pre>
- (NSArray *)getImages {
NSMutableArray *arr = [[[NSMutableArray alloc] init] autorelease];
[arr addObject:[UIImage imageNamed:#"image-1.jpg"]];
[arr addObject:[UIImage imageNamed:#"image-2.png"]];
[arr addObject:[UIImage imageNamed:#"image-3.png"]];
[arr addObject:[UIImage imageNamed:#"image-4.jpg"]];
return (NSArray *)arr;
}
- (void)viewDidLoad {
IGUIScrollViewImage *svimage = [[IGUIScrollViewImage alloc] init];
[svimage setSizeFromScrollView:self.scrView]; // takes size of the scroll view you've already placed on stage via Interface Builder
// or
//[svimage setWidth:320 andHeight:240]; // half screen
[svimage enablePositionMemory]; // enables position (pagination) memory for this scroll view
// or
//[svimage enablePositionMemoryWithIdentifier:#"myIdentifier"]; if you have more instances of this scroll view in your application
[svimage enablePageControlOnBottom];
// or
//[svimage enablePageControlOnTop];
[self.myUIView addSubview:[svimage get]]; // and place it on the stage :)
[super viewDidLoad];
}
</pre>
*/
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#interface IGUIScrollViewImage : NSObject <UIScrollViewDelegate> {
UIScrollView *scrollView;
UIPageControl *pageControl;
CGRect rectScrollView;
CGRect rectPageControl;
int scrollWidth;
int scrollHeight;
NSArray *contentArray;
UIColor *bcgColor;
BOOL pageControlEnabledTop;
BOOL pageControlEnabledBottom;
BOOL rememberPosition;
NSString *positionIdentifier;
}
#property (nonatomic, retain) UIScrollView *scrollView;
- (int)getScrollViewWidth;
- (void)setWidth:(int)width andHeight:(int)height;
- (void)setSizeFromScrollView:(UIScrollView *)scView;
- (void)setBackGroudColor:(UIColor *)color;
- (void)setContentArray:(NSArray *)images;
- (void)enablePageControlOnTop;
- (void)enablePageControlOnBottom;
- (void)enablePositionMemory;
- (void)enablePositionMemoryWithIdentifier:(NSString *)identifier;
- (UIScrollView *)getWithPosition:(int)page;
- (UIScrollView *)getWithPositionMemoryIdentifier:(NSString *)identifier;
- (UIScrollView *)get;
#end
And the implementation file:
//
// IGUIScrollViewImage.m
// IGUILibrary
//
// Created by Ondrej Rafaj on 7.4.10.
// Copyright 2010 Home. All rights reserved.
//
#import "IGUIScrollViewImage.h"
#define kIGUIScrollViewImagePageIdentifier #"kIGUIScrollViewImagePageIdentifier"
#define kIGUIScrollViewImageDefaultPageIdentifier #"Default"
#implementation IGUIScrollViewImage
#synthesize scrollView;
- (int)getScrollViewWidth {
return ([contentArray count] * scrollWidth);
}
- (void)setWidth:(int)width andHeight:(int)height {
scrollWidth = width;
scrollHeight = height;
if (!width || !height) rectScrollView = [[UIScreen mainScreen] applicationFrame];
else rectScrollView = CGRectMake(0, 0, width, height);
}
- (void)setSizeFromScrollView:(UIScrollView *)scView {
scrollWidth = scView.frame.size.width;
scrollHeight = scView.frame.size.height;
rectScrollView = CGRectMake(0, 0, scrollWidth, scrollHeight);
}
- (void)setContentArray:(NSArray *)images {
contentArray = images;
}
- (void)setBackGroudColor:(UIColor *)color {
bcgColor = color;
}
- (void)enablePageControlOnTop {
pageControlEnabledTop = YES;
}
- (void)enablePageControlOnBottom {
pageControlEnabledBottom = YES;
}
- (void)enablePositionMemoryWithIdentifier:(NSString *)identifier {
rememberPosition = YES;
if (!identifier) identifier = kIGUIScrollViewImageDefaultPageIdentifier;
positionIdentifier = identifier;
}
- (void)enablePositionMemory {
[self enablePositionMemoryWithIdentifier:nil];
}
- (UIScrollView *)getWithPosition:(int)page {
if (!contentArray) {
contentArray = [[[NSArray alloc] init] autorelease];
}
if (page > [contentArray count]) page = 0;
if (!scrollWidth || !scrollHeight) {
rectScrollView = [[UIScreen mainScreen] applicationFrame];
scrollWidth = rectScrollView.size.width;
scrollHeight = rectScrollView.size.height;
}
rectScrollView = CGRectMake(0, 0, scrollWidth, scrollHeight);
self.scrollView = [[UIScrollView alloc] initWithFrame:rectScrollView];
self.scrollView.contentSize = CGSizeMake([self getScrollViewWidth], scrollHeight);
if (!bcgColor) bcgColor = [UIColor blackColor];
self.scrollView.backgroundColor = bcgColor;
self.scrollView.alwaysBounceHorizontal = YES;
self.scrollView.contentOffset = CGPointMake(page * scrollWidth, 0);
self.scrollView.pagingEnabled = YES;
UIImageView *imageView;
UIView *main = [[[UIView alloc] initWithFrame:rectScrollView] autorelease];
int i = 0;
for (UIImage *img in contentArray) {
imageView = [[UIImageView alloc] initWithImage:img];
imageView.contentMode = UIViewContentModeScaleAspectFit;
imageView.autoresizingMask = ( UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);
imageView.backgroundColor = [UIColor blackColor];
float ratio = img.size.width/rectScrollView.size.width;
CGRect imageFrame = CGRectMake(i, 0, rectScrollView.size.width, (img.size.height / ratio));
imageView.frame = imageFrame;
[self.scrollView addSubview:imageView];
i += scrollWidth;
}
[imageView release];
[main addSubview:scrollView];
if (pageControlEnabledTop) {
rectPageControl = CGRectMake(0, 5, scrollWidth, 15);
}
else if (pageControlEnabledBottom) {
rectPageControl = CGRectMake(0, (scrollHeight - 25), scrollWidth, 15);
}
if (pageControlEnabledTop || pageControlEnabledBottom) {
pageControl = [[[UIPageControl alloc] initWithFrame:rectPageControl] autorelease];
pageControl.numberOfPages = [contentArray count];
pageControl.currentPage = page;
[main addSubview:pageControl];
}
if (pageControlEnabledTop || pageControlEnabledBottom || rememberPosition) self.scrollView.delegate = self;
//if (margin) [margin release];
return (UIScrollView *)main;
}
- (UIScrollView *)get {
return [self getWithPosition:0];
}
- (UIScrollView *)getWithPositionMemoryIdentifier:(NSString *)identifier {
[self enablePositionMemoryWithIdentifier:identifier];
return [self getWithPosition:[[[NSUserDefaults alloc] objectForKey:[NSString stringWithFormat:#"%#%#", kIGUIScrollViewImagePageIdentifier, positionIdentifier]] intValue]];
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)sv {
int page = sv.contentOffset.x / sv.frame.size.width;
pageControl.currentPage = page;
if (rememberPosition) {
[[NSUserDefaults alloc] setObject:[NSString stringWithFormat:#"%d", page] forKey:[NSString stringWithFormat:#"%#%#", kIGUIScrollViewImagePageIdentifier, positionIdentifier]];
}
}
- (void)dealloc {
[scrollView release];
[super dealloc];
}
#end
Just a quick glance. You alloc UIImageView multiple times in
-(UIScrollView*)getWithPosition:(int)page and release it only once:
for (UIImage *img in contentArray) {
imageView = [[UIImageView alloc] initWithImage:img];
// ...
}
[imageView release];

Resources