Background:
Im building a game "kinda" like connect 4.
I have most of it working, the only part I'm stuck at now is determining if there are 5 of the same colors in a row (left,right,up,down & diagonal)
Question:
How can I get the code to loop and see if there are 5 pieces in a row with the same color in any direction.
Note - Each turn is played by moving one piece on the board to a new position and than 3 new pieces come into play.
That means that it would have to check for a match of 5 after the turn and also after the 3 new pieces get randomly placed onto the board.
Thank you!
My code for the game so far is..
ViewController(.m)
#import "ViewController.h"
#import "BoardCell.h"
#import <QuartzCore/QuartzCore.h>
#interface ViewController ()
#property (strong,nonatomic) NSArray *imageNames;
#property (strong,nonatomic) NSMutableArray *board;
#property NSInteger lastMove;
#define BOARDWIDTH 9
#define BOARDHEIGHT 9
#end
static int moves[]={-BOARDWIDTH,-1,1,BOARDWIDTH};
bool preSelect;
BoardCell *startCell;
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
preSelect = NO;
self.imageNames = #[#"marble_red",#"marble_blue",#"marble_purple",#"marble_orange",#"marble_green"];
self.board = [NSMutableArray new];
for (int y=0; y < BOARDWIDTH; y++) {
for (int x = 0; x < BOARDHEIGHT; x++) {
UIButton * button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
button.frame = CGRectMake(5+ 35 * x, 100 + 35 * y, 30, 30);
button.tag = y*BOARDWIDTH+x;
//[button setTitle:[NSString stringWithFormat:#"%ld", button.tag] forState:UIControlStateNormal];
button.selected = NO;
[button.layer setCornerRadius:15];
[button setBackgroundColor:[UIColor colorWithWhite:.7 alpha:.5]];
[button addTarget:self action:#selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview: button];
[self.board addObject:[[BoardCell alloc] initWithButton:button]];
}
}
self.lastMove=arc4random_uniform(BOARDWIDTH*BOARDHEIGHT);
UIButton *button=(UIButton *)[self.view viewWithTag:self.lastMove];
[button setBackgroundImage:[UIImage imageNamed:#"greensquare"] forState:UIControlStateNormal];
[self addRandoms:3];
}
-(void) addRandoms:(NSInteger)randomCount {
for (int i = 0; i < randomCount; i++) {
int space = arc4random_uniform(BOARDWIDTH*BOARDHEIGHT);
BoardCell *cell=self.board[space];
if (!cell.occupied) {
int pic = arc4random_uniform((u_int32_t)self.imageNames.count);
NSString *string = [self.imageNames objectAtIndex:pic];
NSString *highlighted = [NSString stringWithFormat:#"%#_highlighted",string];
NSLog(#"HIGHLIGHTED = %#",highlighted);
[cell.button setBackgroundImage:[UIImage imageNamed:string] forState:UIControlStateNormal];
[cell.button setTitleColor:[UIColor lightGrayColor] forState:UIControlStateNormal];
[cell.button setTitleColor:[UIColor blackColor] forState:UIControlStateSelected];
cell.button.selected = NO;
cell.occupied=YES;
}
else {
i--;
}
}
}
-(void)buttonPressed:(UIButton *)button
{
NSInteger buttonId=button.tag;
BoardCell *cell=self.board[buttonId];
if (!preSelect) {
if (cell.occupied) {
//cell.button.selected = YES;
[[cell.button layer] setBorderWidth:3.5f];
[cell.button.layer setBorderColor:[[UIColor colorWithWhite:.85 alpha:.7]CGColor]];
cell.button.highlighted = YES;
preSelect = YES;
self.lastMove = buttonId;
startCell = cell;
}else{
cell.button.selected = NO;
cell.button.highlighted = NO;
[cell.button.layer setBorderColor:[[UIColor clearColor]CGColor]];
}
}else{
NSLog(#"SECOND STEP");
if (!cell.occupied) {
BoardCell *startCell=self.board[self.lastMove];
startCell.occupied=NO;
if ([self validMoveFromSquare:self.lastMove toDestination:buttonId]) {
[cell.button setBackgroundImage:[startCell.button backgroundImageForState:UIControlStateNormal]
forState:UIControlStateNormal];
[startCell.button setBackgroundImage:[UIImage imageNamed:#""] forState:UIControlStateNormal];
NSLog(#"FROM %ld, TO %ld",(long)self.lastMove,(long)buttonId);
cell.button.selected = NO;
cell.button.highlighted = NO;
startCell.button.selected = NO;
startCell.button.highlighted = NO;
self.lastMove=buttonId;
cell.occupied=YES;
preSelect = NO;
[self addRandoms:3];
}else{
startCell.occupied=YES;
preSelect = NO;
cell.button.selected = NO;
cell.button.highlighted = NO;
startCell.button.selected = NO;
startCell.button.highlighted = NO;
NSLog(#" INVALID FROM %ld, TO %ld",(long)self.lastMove,(long)buttonId);
}
}
preSelect = NO;
cell.button.selected = NO;
cell.button.highlighted = NO;
startCell.button.selected = NO;
startCell.button.highlighted = NO;
[cell.button.layer setBorderColor:[[UIColor clearColor]CGColor]];
[startCell.button.layer setBorderColor:[[UIColor clearColor]CGColor]];
}
}
-(BOOL) validMoveFromSquare:(NSInteger)startSquare toDestination:(NSInteger)destination {
for (int limit=1;limit<10;limit++ ) {
NSMutableIndexSet *visitList=[NSMutableIndexSet new];
if ([self DFSFromStart:startSquare toGoal:destination withLimit:limit andVisitList:visitList]) {
return YES;
}
}
return NO;
}
-(BOOL) DFSFromStart:(NSInteger)start toGoal:(NSInteger)goal withLimit:(NSInteger)limit andVisitList:(NSMutableIndexSet *)visitList {
if (limit >=0) {
if (((BoardCell *)self.board[start]).occupied) {
NSLog(#"Self Board = %#",self.board[start]);
return NO;
}
[visitList addIndex:start];
for (int i=0;i<4;i++) {
NSInteger nextPosition=start+moves[i];
NSLog(#"Next spot = %ld",(long)nextPosition);
if (nextPosition == goal) {
return YES;
}
if (nextPosition >=0 && nextPosition < BOARDWIDTH*BOARDHEIGHT) {
if (![visitList containsIndex:nextPosition]) {
if ([self DFSFromStart:nextPosition toGoal:goal withLimit:limit-1 andVisitList:visitList]) {
return YES;
}
}
}
}
}
return NO;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
BoardCell.m
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#interface BoardCell : NSObject
#property (weak,nonatomic,readonly) UIButton *button;
#property BOOL occupied;
-(id) initWithButton:(UIButton *)button;
#end
Thank you again!
You can use a recursive algorithm to work in each of the eight directions until you hit a boundary or a different color -
-(void) clearRunsOfColor:(Colors)color fromPoint:(NSInteger)startPoint {
NSInteger left=[self runFromStart:startPoint-1 ofColor:color inDirection:-1];
NSInteger right=[self runFromStart:startPoint+1 ofColor:color inDirection:1];
BOOL cleared=NO;
if (left+right+1 >4) {
[self clearBoardFromStart:startPoint-1 inDirection:-1 forLength:left];
[self clearBoardFromStart:startPoint+1 inDirection:1 forLength:right];
cleared=YES;
}
NSInteger up=[self runFromStart:startPoint-BOARDWIDTH ofColor:color inDirection:-BOARDWIDTH];
NSInteger down=[self runFromStart:startPoint+BOARDWIDTH ofColor:color inDirection:BOARDWIDTH];
if (up+down+1 > 4) {
[self clearBoardFromStart:startPoint-BOARDWIDTH inDirection:-BOARDWIDTH forLength:up];
[self clearBoardFromStart:startPoint+BOARDWIDTH inDirection:BOARDWIDTH forLength:down];
cleared=YES;
}
NSInteger NW=[self runFromStart:startPoint-BOARDWIDTH-1 ofColor:color inDirection:-BOARDWIDTH-1];
NSInteger SE=[self runFromStart:startPoint+BOARDWIDTH+1 ofColor:color inDirection:+BOARDWIDTH+1];
if (NW+SE+1 > 4) {
[self clearBoardFromStart:startPoint-BOARDWIDTH-1 inDirection:-BOARDWIDTH-1 forLength:NW];
[self clearBoardFromStart:startPoint+BOARDWIDTH+1 inDirection:BOARDWIDTH+1 forLength:SE];
cleared=YES;
}
NSInteger NE=[self runFromStart:startPoint-BOARDWIDTH+1 ofColor:color inDirection:-BOARDWIDTH+1];
NSInteger SW=[self runFromStart:startPoint+BOARDWIDTH-1 ofColor:color inDirection:+BOARDWIDTH-1];
if (NE+SW+1 > 4) {
[self clearBoardFromStart:startPoint-BOARDWIDTH+1 inDirection:-BOARDWIDTH+1 forLength:NE];
[self clearBoardFromStart:startPoint+BOARDWIDTH-1 inDirection:BOARDWIDTH-1 forLength:SW];
cleared=YES;
}
if (cleared) {
[self occupyCell:startPoint withPiece:nil];
}
}
-(void) clearBoardFromStart:(NSInteger)start inDirection:(NSInteger)direction forLength:(NSInteger) length {
NSInteger pos=start;
for (int i=0;i<length;i++) {
[self occupyCell:pos withPiece:nil];
pos+=direction;
}
}
-(NSInteger) runFromStart:(NSInteger)start ofColor:(Colors)color inDirection:(NSInteger)direction {
if ([self inBounds:start]) {
BoardCell *thisCell=self.board[start];
if (thisCell.gamepiece != nil && thisCell.gamepiece.color == color) {
if ([self validDestination:start+direction withMove:(int)direction fromSquare:start]) {
return ([self runFromStart:start+direction ofColor:color inDirection:direction]+1);
}
else {
return 1;
}
}
}
return 0;
}
-(BOOL) inBounds:(NSInteger) position {
if (position >=0 && position < BOARDHEIGHT*BOARDWIDTH) {
return YES;
}
else {
return NO;
}
}
None of the code below is tested for correctness.
You could update your BoardCell class like so:
typedef enum {
TopLeft, Top, TopRight,
Left, Right,
BottomLeft, Bottom, BottomRight,
NumberOfDirections
} BoardCellAdjacentDirection;
#interface BoardCell
- (void)addAdjacentCell:(BoardCell *)cell forDirection:(BoardCellAdjacentDirection)direction;
- (NSInteger)occupiedCellsInDirection:(BoardCellAdjacentDirection)direction;
#end
#implementation BoardCell {
NSMutableArray *adjacentCells;
}
- (instancetype)init {
if (self = [super init]) {
adjacentCells = [[NSMutableArray alloc] init];
for (NSInteger i = 0; i < (NSInteger)NumberOfDirections; i++) {
[adjacentCells addObject:[NSNull null]];
}
}
return self;
}
- (void)addAdjacentCell:(BoardCell *)cell forDirection:(BoardCellAdjacentDirection)direction {
[adjacentCells setObject:cell atIndex:(NSInteger)direction];
}
- (NSInteger)occupiedCellsInDirection:(BoardCellAdjacentDirection)direction {
if (!self.occupied) return 0;
if (adjacentCells[direction] == [NSNull null]) return 1;
return [adjacentCells[direction] occupiedCellsInDirection:direction]+1;
}
#end
Wherever you create your BoardCell objects, you'll need to add the appropriate adjacent cells. You'll also probably want to put in some sanity checks to make sure that cell adjacency is a two-way relationship (i.e. cell A is left-adjacent to B and B is right-adjacent to A).
Edit You'll probably also want to add a method to determine if you've injected a cell into the centre of a line.
typedef enum {
BackSlash,
ForwardSlash,
Vertical,
Horizontal
} BoardCellAxis;
...
- (NSInteger)occupiedCellsOnAxis:(BoardCellAxis)axis {
switch (axis) {
case BackSlash:
return MAX(0, [self occupiedCellsInDirection:TopLeft]
+ [self occupiedCellsInDirection:BottomRight]
- 1); // Don't count yourself twice.
case ForwardSlash:
return MAX(0, [self occupiedCellsInDirection:TopRight]
+ [self occupiedCellsInDirection:BottomLeft]
- 1); // Don't count yourself twice.
case Vertical:
return MAX(0, [self occupiedCellsInDirection:Top]
+ [self occupiedCellsInDirection:Bottom]
- 1); // Don't count yourself twice.
case Horizontal:
return MAX(0, [self occupiedCellsInDirection:Left]
+ [self occupiedCellsInDirection:Right]
- 1); // Don't count yourself twice.
}
}
Related
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.
How to get the black blocks disappear?
And after the rotation, the black blocks disappear.
AppDelegate Source File:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
UIStoryboard *mainStoryBoard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
UIViewController *viewController = [mainStoryBoard instantiateViewControllerWithIdentifier:#"ViewController"];
self.window.rootViewController = viewController;
bar = [KodUserCenterBar instance];
[self.window makeKeyAndVisible];
return YES;
}
Header File:
#interface KodUserCenterBar : UIWindow
/**获取单例
*/
+ (instancetype)instance;
/**显示工具栏
*/
+ (void)show;
/**隐藏工具栏
*/
+ (void)hide;
/**显示功能视图
*/
+ (void)showFunctionView;
/**隐藏功能视图
*/
+ (void)hideFunctionView;
#end
Source File:
#define WIDTH self.frame.size.width
#define HEIGHT self.frame.size.height
#define kScreenWidth [UIScreen mainScreen].bounds.size.width
#define kScreenHeight [UIScreen mainScreen].bounds.size.height
#define kBarWidth 200
#define kBarImageViewTag 100
#define kBarItemGap 5
#define degreesToRadian(x) (M_PI * (x) / 180.0)
#interface KodUserCenterBarFunctionItemObject : NSObject
#property (nonatomic, copy) NSString *title;
#property (nonatomic, assign) NSUInteger indexOfTabBar;
#property (nonatomic, copy) NSString *imageName;
+ (instancetype)objectWithTitle:(NSString *)title indexOfTabBar:(NSUInteger)index imageName:(NSString *)imageName;
#end
#implementation KodUserCenterBarFunctionItemObject
+ (instancetype)objectWithTitle:(NSString *)title indexOfTabBar:(NSUInteger)index imageName:(NSString *)imageName
{
KodUserCenterBarFunctionItemObject *obj = [KodUserCenterBarFunctionItemObject new];
if (obj) {
obj.title = title;
obj.indexOfTabBar = index;
obj.imageName = imageName;
}
return obj;
}
#end
#interface KodUserCenterBar()
{
UIPanGestureRecognizer *pan;
UIViewController *_rootVC;
}
#property (nonatomic, copy) NSArray *itemsOfBar;
#property (nonatomic, assign) CGFloat initWidth;
#property (atomic, strong) UIButton *button;
#end
static KodUserCenterBar *static_instance = nil;
static BOOL isShowMenu = NO;
#implementation KodUserCenterBar
+ (instancetype)instance
{
if (static_instance == nil) {
static_instance = [KodUserCenterBar new];
[static_instance addTopButton];
}
return static_instance;
}
+ (void)show
{
[KodUserCenterBar instance].hidden = NO;
}
+ (void)hide
{
[KodUserCenterBar instance].hidden = YES;
}
+ (void)showFunctionView
{
if (!isShowMenu) {
[[KodUserCenterBar instance] clickBar:nil];
}
}
+ (void)hideFunctionView
{
if (isShowMenu) {
[[KodUserCenterBar instance] clickBar:nil];
}
}
- (instancetype)init
{
if (self = [super init]) {
self.backgroundColor = [UIColor clearColor];
self.windowLevel = UIWindowLevelAlert;
self.userInteractionEnabled = YES;
[self makeKeyAndVisible];
self.sd_x = 0;
self.sd_center_y = [UIScreen mainScreen].bounds.size.height / 2;
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(onDeviceOrientationChange) name:UIDeviceOrientationDidChangeNotification object:nil];
}
return self;
}
- (NSArray *)itemsOfBar
{
if (_itemsOfBar == nil) {
KodUserCenterBarFunctionItemObject *item1 = [KodUserCenterBarFunctionItemObject objectWithTitle:#"个人中心" indexOfTabBar:0 imageName:#"tb3_toolbaruser"];
KodUserCenterBarFunctionItemObject *item2 = [KodUserCenterBarFunctionItemObject objectWithTitle:#"游戏礼包" indexOfTabBar:1 imageName:#"tb3_toolbargame"];
KodUserCenterBarFunctionItemObject *item3 = [KodUserCenterBarFunctionItemObject objectWithTitle:#"系统公告" indexOfTabBar:2 imageName:#"tb3_toolbarmsg"];
KodUserCenterBarFunctionItemObject *item4 = [KodUserCenterBarFunctionItemObject objectWithTitle:#"游戏论坛" indexOfTabBar:3 imageName:#"tb3_toolbarbbs"];
NSArray *data = #[item1, item2, item3, item4];
_itemsOfBar = [NSArray arrayWithArray:data];
}
return _itemsOfBar;
}
- (void)onDeviceOrientationChange
{
UIDeviceOrientation orientation = [UIDevice currentDevice].orientation;
if (orientation == UIDeviceOrientationPortrait || orientation == UIDeviceOrientationPortraitUpsideDown) {
NSLog(#"is portrait");
NSLog(#"width = %f, height = %f", kScreenWidth, kScreenHeight);
[self adjustWindowPosition];
self.sd_center_y = kScreenHeight / 2;
}
else if (orientation == UIDeviceOrientationLandscapeLeft || orientation == UIDeviceOrientationLandscapeRight) {
NSLog(#"is landscape");
NSLog(#"width = %f, height = %f", kScreenWidth, kScreenHeight);
[self adjustWindowPosition];
self.sd_center_y = kScreenHeight / 2;
}
}
- (void)addTopButton
{
pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(dragBar:)];
pan.delaysTouchesBegan = NO;
[self addGestureRecognizer:pan];
UIViewController *vc = [[KodBasicViewController alloc] init];
vc.view.backgroundColor = [UIColor clearColor];
self.rootViewController = vc;
CGSize size = [UIImage imageNamed:#"tb3_assi_nor"].size;
self.sd_width = size.width;
self.sd_height = size.height;
self.initWidth = size.width;
_button = [[UIButton alloc] init];
[_button setBackgroundImage:[UIImage imageNamed:#"tb3_assi_nor"] forState:UIControlStateNormal];
[_button setBackgroundImage:[UIImage imageNamed:#"tb3_assi_pre"] forState:UIControlStateHighlighted];
[_button setBackgroundImage:[UIImage imageNamed:#"tb3_assi_pre"] forState:UIControlStateSelected];
_button.frame = CGRectMake(0, 0, self.frame.size.width, self.frame.size.height);
[_button addTarget:self action:#selector(clickBar:) forControlEvents:UIControlEventTouchUpInside];
_button.userInteractionEnabled = YES;
_button.selected = NO;
[_button becomeFirstResponder];
[vc.view addSubview:_button];
}
- (void)clickBar:(id)button
{
NSTimeInterval interval = 0.2;
__weak typeof(_button) weakButton = _button;
isShowMenu = !isShowMenu;
pan.enabled = !isShowMenu;
if (self.sd_center_x > kScreenWidth / 2) {
[UIView animateWithDuration:interval animations:^{
self.sd_x = kScreenWidth;
} completion:^(BOOL finished) {
if (isShowMenu) {
self.sd_width = kBarWidth + self.initWidth;
_button.sd_right_x = self.sd_width;
UIImage *image = [UIImage imageNamed:#"tb3_assi_bor_right"];
image = [image resizableImageWithCapInsets:UIEdgeInsetsMake(1, 30, 1, 0)];
UIImageView *rightImageView = [[UIImageView alloc] initWithImage:image];
rightImageView.image = image;
rightImageView.sd_width = kBarWidth;
rightImageView.sd_right_x = _button.sd_x;
rightImageView.sd_center_y = _button.sd_center_y;
rightImageView.tag = kBarImageViewTag;
rightImageView.userInteractionEnabled = YES;
[self.rootViewController.view addSubview:rightImageView];
self.sd_x = kScreenWidth;
[weakButton setBackgroundImage:[UIImage imageNamed:#"tb3_assi_act_right"] forState:UIControlStateNormal];
[weakButton setBackgroundImage:[UIImage imageNamed:#"tb3_assi_act_pre_right"] forState:UIControlStateSelected];
[weakButton setBackgroundImage:[UIImage imageNamed:#"tb3_assi_act_pre_right"] forState:UIControlStateHighlighted];
[self addFunctionItems:NO];
}
else {
self.sd_width = self.initWidth;
_button.sd_right_x = self.sd_width;
UIView *contentView = [self.rootViewController.view viewWithTag:kBarImageViewTag];
[contentView removeFromSuperview];
[weakButton setBackgroundImage:[UIImage imageNamed:#"tb3_assi_nor"] forState:UIControlStateNormal];
[weakButton setBackgroundImage:[UIImage imageNamed:#"tb3_assi_pre"] forState:UIControlStateSelected];
[weakButton setBackgroundImage:[UIImage imageNamed:#"tb3_assi_pre"] forState:UIControlStateHighlighted];
}
[UIView animateWithDuration:interval animations:^{
self.sd_right_x = kScreenWidth;
}];
}];
}
else {
[UIView animateWithDuration:interval animations:^{
self.sd_right_x = 0;
} completion:^(BOOL finished) {
if (isShowMenu) {
self.sd_width = kBarWidth + self.initWidth;
UIImage *image = [UIImage imageNamed:#"tb3_assi_bor_left"];
image = [image resizableImageWithCapInsets:UIEdgeInsetsMake(1, 0, 1, 30)];
UIImageView *leftImageView = [[UIImageView alloc] initWithImage:image];
leftImageView.image = image;
leftImageView.sd_width = kBarWidth;
leftImageView.sd_x = _button.sd_right_x;
leftImageView.sd_center_y = _button.sd_center_y;
leftImageView.tag = kBarImageViewTag;
leftImageView.userInteractionEnabled = YES;
[self.rootViewController.view addSubview:leftImageView];
self.sd_right_x = 0;
[weakButton setBackgroundImage:[UIImage imageNamed:#"tb3_assi_act_left"] forState:UIControlStateNormal];
[weakButton setBackgroundImage:[UIImage imageNamed:#"tb3_assi_act_pre_left"] forState:UIControlStateSelected];
[weakButton setBackgroundImage:[UIImage imageNamed:#"tb3_assi_act_pre_left"] forState:UIControlStateHighlighted];
[self addFunctionItems:YES];
}
else {
self.sd_width = self.initWidth;
UIView *contentView = [self.rootViewController.view viewWithTag:kBarImageViewTag];
[contentView removeFromSuperview];
[weakButton setBackgroundImage:[UIImage imageNamed:#"tb3_assi_nor"] forState:UIControlStateNormal];
[weakButton setBackgroundImage:[UIImage imageNamed:#"tb3_assi_pre"] forState:UIControlStateSelected];
[weakButton setBackgroundImage:[UIImage imageNamed:#"tb3_assi_pre"] forState:UIControlStateHighlighted];
}
[UIView animateWithDuration:interval animations:^{
self.sd_x = 0;
}];
}];
}
}
- (void)addFunctionItems:(BOOL)isLeft
{
UIView *bgView = [self.rootViewController.view viewWithTag:kBarImageViewTag];
if (bgView) {
[self.itemsOfBar enumerateObjectsUsingBlock:^(KodUserCenterBarFunctionItemObject *obj, NSUInteger idx, BOOL * _Nonnull stop) {
if ([bgView viewWithTag:idx] == nil) {
KodFrameTabBarItem *item = [[KodFrameTabBarItem alloc] init];
item.tag = idx;
item.title = obj.title;
item.imageName = obj.imageName;
item.sd_width = (bgView.sd_width - _itemsOfBar.count * kBarItemGap - 10) / _itemsOfBar.count;
item.sd_height = bgView.sd_height;
item.sd_center_y = bgView.sd_height / 2;
item.sd_center_x = kBarItemGap + idx * (item.sd_width + kBarItemGap) + item.sd_width / 2;
item.sd_center_x += isLeft ? 0 : item.sd_width / 4;
[item addTarget:self action:#selector(clickItem:) forControlEvents:UIControlEventTouchUpInside];
[bgView addSubview:item];
}
}];
}
}
- (void)clickItem:(id)sender
{
[KodNavigationView showWithIndex:0];
[[UIApplication sharedApplication].keyWindow addSubview:[KodNavigationView instance]];
}
- (void)adjustWindowPosition
{
if (self.sd_center_x < kScreenWidth / 2) {
self.sd_x = 0;
}
else {
self.sd_right_x = kScreenWidth;
}
}
- (void)dragBar:(UIPanGestureRecognizer *)p
{
CGPoint panPoint = [p locationInView:[[UIApplication sharedApplication] keyWindow]];
if (p.state == UIGestureRecognizerStateBegan) {
if (_button) {
_button.selected = YES;
}
}
else if(p.state == UIGestureRecognizerStateChanged) {
self.center = CGPointMake(panPoint.x, panPoint.y);
if (panPoint.x < WIDTH / 2) {
self.sd_x = 0;
}
else if (panPoint.x > kScreenWidth - WIDTH / 2) {
self.sd_right_x = kScreenWidth;
}
if (panPoint.y < HEIGHT / 2) {
self.sd_y = 0;
}
else if (panPoint.y > kScreenHeight - HEIGHT / 2) {
self.sd_bottom_y = kScreenHeight;
}
}
else if(p.state == UIGestureRecognizerStateEnded) {
if(panPoint.x <= kScreenWidth / 2) {
[UIView animateWithDuration:0.2 animations:^{
self.sd_x = 0;
} completion:nil];
}
else {
[UIView animateWithDuration:0.2 animations:^{
self.sd_right_x = kScreenWidth;
} completion:nil];
}
if (_button) {
_button.selected = NO;
}
}
}
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
#end
Root ViewController
Source File Of Root ViewController:
#interface KodBasicViewController ()
#end
#implementation KodBasicViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (UIInterfaceOrientationMask)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskAll;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return UIInterfaceOrientationPortrait;
}
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
UIWindow *window = self.view.window;
[window bringSubviewToFront:window.rootViewController.view];
}
- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator
{
UIWindow *window = self.view.window;
[window bringSubviewToFront:window.rootViewController.view];
}
#end
Here is my solution to this problem:
window.layer.masksToBounds = true
It's the default background colour of UIWindow instance, and while your root view is doing rotation, those uncovered parts will be shown as black block as you said.
You can just set your desired background colour for your window (or make your root view's frame big enough to cover whole window while doing rotation, not recommended):
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
...
[self.window setBackgroundColor:[UIColor lightGrayColor]];
[self.window makeKeyAndVisible];
return YES;
}
I have 3 page - A ViewController, B ViewController and C ViewController.
And A PageViewController control there horizontal scroll.
PagesViewController.m
- (void)viewDidLoad {
[super viewDidLoad];
self.aVC = [self.storyboard
instantiateViewControllerWithIdentifier:#"AViewController"];
self.bVC = [self.storyboard
instantiateViewControllerWithIdentifier:#"BViewController"];
self.cVC = [self.storyboard
instantiateViewControllerWithIdentifier:#"CViewController"];
self.delegate = self;
self.dataSource = self;
self.allViewControllers = #[self.aVC,self.bVC
,self.cVC];
[self setViewControllers:#[self.aVC]
direction:UIPageViewControllerNavigationDirectionForward
animated:NO completion:nil];
_pageControl = [UIPageControl appearance];
}
I want to change the _pageControl color when I scroll to A VC , B VC and C VC.
So I put the code in
-(NSInteger)presentationIndexForPageViewController:
(UIPageViewController *)pageViewController
{
NSLog(#"%#",pageViewController.viewControllers[0]);
for( int i = 0 ; i< self.allViewControllers.count ; i++ )
{
if( pageViewController.viewControllers[0] == self.allViewControllers[i])
{
if( i ==0 )
{
_pageControl.backgroundColor = [UIColor greenColor];
}
else if( i ==1)
{
_pageControl.backgroundColor = [UIColor redColor];
}
else
{
_pageControl.backgroundColor = [UIColor clearColor];
}
NSLog(#"return index:%d", i);
return i;
}
}
return 0;
}
But the page control was not change the color.
I try to put below the code in the viewDidLoad, it will change color at all the view controller.
_pageControl.backgroundColor = [UIColor redColor];
But now I want to change the pageControl color when I scroll to different UIViewController.
How can I do? or How can I refresh the pageControl color?
Because now the color always black.
I offer others delegate method about the PageViewController:
-(UIViewController*) pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController
{
NSUInteger currentIndex = [self.allViewControllers indexOfObject:viewController];
if( currentIndex == 0 )
{
return nil;
}
currentIndex--;
return [self.allViewControllers objectAtIndex:currentIndex];
}
-(UIViewController *) pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController
{
NSUInteger currentIndex = [self.allViewControllers indexOfObject:viewController];
NSLog(#"after currentIndex:%ld",currentIndex);
currentIndex++;
if( currentIndex == [self.allViewControllers count])
{
return nil;
}
return [self.allViewControllers objectAtIndex:currentIndex];
}
-(NSInteger)presentationCountForPageViewController:
(UIPageViewController *)pageViewController
{
return self.allViewControllers.count;
}
In your viewDidLoad: method,
instead of:
_pageControl = [UIPageControl appearance];
use:
NSArray *subviews = self.view.subviews;
_pageControl = nil;
for (int i=0; i<[subviews count]; i++) {
if ([[subviews objectAtIndex:i] isKindOfClass:[UIPageControl class]]) {
_pageControl = (UIPageControl *)[subviews objectAtIndex:i];
}
}
=====
EDIT:
For your specific project, you're not getting the _pageControl (it's returning nil) because the Storyboard has not completed instantiating your view controller in the viewDidLoad. I thought it would need to go in viewDidAppear:animated, but that didn't work either, so I cheated by delaying requesting it for 0.2 milliseconds.
In your viewDidLoad, put this:
[self performSelector:#selector(findPageControl) withObject:nil afterDelay:0.2f];
Then, add this method:
- (void) findPageControl {
NSArray *subviews = self.view.subviews;
_pageControl = nil;
for (int i=0; i<[subviews count]; i++) {
if ([[subviews objectAtIndex:i] isKindOfClass:[UIPageControl class]]) {
_pageControl = (UIPageControl *)[subviews objectAtIndex:i];
}
}
[self changePage:0];
}
In your viewControllerAfterViewController method, I added this right after the NSUInteger currentIndex = line:
[self changePage:currentIndex];
That seems to have made it work. Now, you could add an animation in your changePage method to make the transition seem a little smoother.
Also, when debugging, this is what I did:
I added a breakpoint on the _pageControl = line, so I could check and see what was happening. When I saw it was nil, that told me that it wasn't being set properly. Look in the debug area, and you can see what I printed out ("po") to see what values existed -- and why there was no UIPageControl. If you do the same after the changes I list above, you'll see that this is now found and set.
Here's an example, just with a pageControl in a UIViewController:
#import "ViewController.h"
#interface ViewController () {
UIPageControl *pageControl;
}
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor lightGrayColor];
pageControl = [[UIPageControl alloc] initWithFrame:CGRectMake(10, 10, 100, 40)];
pageControl.numberOfPages = 6;
[pageControl addTarget:self action:#selector(changePage:) forControlEvents:UIControlEventValueChanged];
[self.view addSubview:pageControl];
}
- (void) changePage:(UIPageControl *)page {
NSInteger currentPage = page.currentPage;
switch (currentPage) {
case 0:
pageControl.backgroundColor = [UIColor redColor];
break;
case 1:
pageControl.backgroundColor = [UIColor greenColor];
break;
case 2:
pageControl.backgroundColor = [UIColor blueColor];
break;
default:
break;
}
}
#end
In my app I've to create a custom alert view like the following:
So I followed this tutorial to create a custom alert view. I finished it but I'm getting issue in the following method:
- (void)addOrRemoveButtonWithTag:(int)tag andActionToPerform:(BOOL)shouldRemove {
NSMutableArray *items = [[NSMutableArray alloc]init];
[items addObject:self.buttonOk];
[items addObject:self.buttonClose];
int buttonIndex = (tag == 1);
if (shouldRemove) {
[items removeObjectAtIndex:buttonIndex];
} else {
if (tag == 1) {
[items insertObject:self.buttonOk atIndex:buttonIndex];
} else {
[items insertObject:self.buttonClose atIndex:buttonIndex];
}
}
}
I edited it than the tutorial because I don't need a UIToolBar for buttons. When I run the app it says me that I can't insert a nil object in an NSMutableArray, but I don't understand what's wrong, I hope you can help me to fix this issue.
UPDATE
Here's all the class code I developed:
#import "CustomAlertViewController.h"
#define ANIMATION_DURATION 0.25
#interface CustomAlertViewController ()
- (IBAction)buttonOk:(UIButton *)sender;
- (IBAction)buttonCancel:(UIButton *)sender;
#property (weak, nonatomic) IBOutlet UIButton *buttonClose;
#property (weak, nonatomic) IBOutlet UIButton *buttonOk;
#property (strong, nonatomic) IBOutlet UIView *viewAlert;
-(void)addOrRemoveButtonWithTag:(int)tag andActionToPerform:(BOOL)shouldRemove;
#end
#implementation CustomAlertViewController
- (id)init
{
self = [super init];
if (self) {
[self.viewAlert setFrame:CGRectMake(self.labelAlertView.frame.origin.x,
self.labelAlertView.frame.origin.y,
self.labelAlertView.frame.size.width,
self.viewAlert.frame.size.height)];
[self.buttonOk setTag:1];
[self.buttonClose setTag:0];
}
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)showCustomAlertInView:(UIView *)targetView withMessage:(NSString *)message {
CGFloat statusBarOffset;
if (![[UIApplication sharedApplication] isStatusBarHidden]) {
CGSize statusBarSize = [[UIApplication sharedApplication] statusBarFrame].size;
if (statusBarSize.width < statusBarSize.height) {
statusBarOffset = statusBarSize.width;
} else {
statusBarOffset = statusBarSize.height;
}
} else {
statusBarOffset = 0.0;
}
CGFloat width, height, offsetX, offsetY;
if ([[UIApplication sharedApplication] statusBarOrientation] == UIInterfaceOrientationLandscapeLeft ||
[[UIApplication sharedApplication] statusBarOrientation] == UIInterfaceOrientationLandscapeRight) {
width = targetView.frame.size.width;
height = targetView.frame.size.height;
offsetX = 0.0;
offsetY = -statusBarOffset;
}
[self.view setFrame:CGRectMake(targetView.frame.origin.x, targetView.frame.origin.y, width, height)];
[self.view setFrame:CGRectOffset(self.view.frame, offsetX, offsetY)];
[targetView addSubview:self.view];
[self.viewAlert setFrame:CGRectMake(0.0, -self.viewAlert.frame.size.height, self.viewAlert.frame.size.width, self.viewAlert.frame.size.height)];
[UIView beginAnimations:#"" context:nil];
[UIView setAnimationDuration:ANIMATION_DURATION];
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
[self.viewAlert setFrame:CGRectMake(0.0, 0.0, self.viewAlert.frame.size.width, self.viewAlert.frame.size.height)];
[UIView commitAnimations];
[self.labelAlertView setText:#"CIAO"];
}
- (void)removeCustomAlertFromView {
[UIView beginAnimations:#"" context:nil];
[UIView setAnimationDuration:ANIMATION_DURATION];
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
[self.viewAlert setFrame:CGRectMake(0.0, -self.viewAlert.frame.size.height, self.viewAlert.frame.size.width, self.viewAlert.frame.size.height)];
[UIView commitAnimations];
[self.view performSelector:#selector(removeFromSuperview) withObject:nil afterDelay:ANIMATION_DURATION];
}
- (void)removeCustomAlertFromViewInstantly {
[self.view removeFromSuperview];
}
- (BOOL)isOkayButtonRemoved {
if (self.buttonOk == nil) {
return YES;
} else {
return NO;
}
}
- (BOOL)isCancelButtonRemoved {
if (self.buttonClose == nil) {
return YES;
} else {
return NO;
}
}
- (void)removeOkayButton:(BOOL)shouldRemove {
if ([self isOkayButtonRemoved] != shouldRemove) {
[self addOrRemoveButtonWithTag:1 andActionToPerform:shouldRemove];
}
}
- (void)removeCancelButton:(BOOL)shouldRemove {
if ([self isCancelButtonRemoved] != shouldRemove) {
[self addOrRemoveButtonWithTag:0 andActionToPerform:shouldRemove];
}
}
- (void)addOrRemoveButtonWithTag:(int)tag andActionToPerform:(BOOL)shouldRemove {
NSMutableArray *items = [[NSMutableArray alloc]init];
[items addObject:self.buttonOk];
[items addObject:self.buttonClose];
int buttonIndex = (tag == 1);
if (shouldRemove) {
[items removeObjectAtIndex:buttonIndex];
} else {
if (tag == 1) {
[items insertObject:self.buttonOk atIndex:buttonIndex];
} else {
[items insertObject:self.buttonClose atIndex:buttonIndex];
}
}
}
- (IBAction)buttonOk:(UIButton *)sender {
[self.delegate customAlertOk];
}
- (IBAction)buttonCancel:(UIButton *)sender {
[self.delegate customAlertCancel];
}
#end
UPDATE 2
Code in which I use the CustomAlertView:
#import "PromotionsViewController.h"
#import "CustomAlertViewController.h"
#interface PromotionsViewController () <CustomAlertViewControllerDelegate> {
BOOL isDeletingItem;
}
#property(nonatomic,strong) CustomAlertViewController *customAlert;
- (IBAction)buttonBack:(UIButton *)sender;
#property (weak, nonatomic) IBOutlet UIButton *buttonAlert;
- (IBAction)buttonAlert:(UIButton *)sender;
#end
#implementation PromotionsViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
[self.buttonAlert setTitle:self.promotionSelected forState:UIControlStateNormal];
[self.customAlert setDelegate:self];
isDeletingItem = NO;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)buttonBack:(UIButton *)sender {
[self dismissViewControllerAnimated:YES completion:nil];
}
- (IBAction)buttonAlert:(UIButton *)sender {
self.customAlert = [[CustomAlertViewController alloc]init];
[self.customAlert removeOkayButton:NO];
[self.customAlert removeCancelButton:NO];
NSString *message = [NSString stringWithFormat:#"La tua offerta %# del 20%% è stata convertita in punti IoSi x10", self.promotionSelected];
[self.customAlert showCustomAlertInView:self.view withMessage:message];
isDeletingItem = YES;
}
- (void)customAlertOk {
if (isDeletingItem) {
[self.customAlert removeCustomAlertFromViewInstantly];
} else {
[self.customAlert removeCustomAlertFromView];
}
}
- (void)customAlertCancel {
[self.customAlert removeCustomAlertFromView];
if (isDeletingItem) {
isDeletingItem = NO;
}
}
#end
Maybe you're calling addOrRemoveButtonWithTag:andActionToPerform: at a time where your UI is not fully created, since UI elements are created asynchronously. So if you call this method, right after custom alert view instanciation, you'll get your crash because the buttons in the view are not created.
To solve this issue, you need to call addOrRemoveButtonWithTag:andActionToPerform: only once your custom alert has been added to the view hierarchy.
EDIT :
With the example code you gave in edit 2, you call these lines :
- (IBAction)buttonAlert:(UIButton *)sender {
self.customAlert = [[CustomAlertViewController alloc]init];
[self.customAlert removeOkayButton:NO];
[self.customAlert removeCancelButton:NO];
}
but when you have just instantiated CustomAlertViewController, its 2 buttons are not yet created, so I suggest you add 2 properties hasOkButton and hasCancelButton and a new constructor to your custom class like this one :
- (instancetype) initWithOk:(BOOL)OkButton AndCancel:(BOOL) CancelButton
{
if(self = [super init])
{
hasOkButton = OkButton;
hasCancelButton = CancelButton;
}
}
-(void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
// At this time, the custom UI buttons will be created in the UI view hierarchy
[self removeOkayButton: hasOkButton];
[self removeOkayButton: hasCancelButton];
}
And in the caller you can use the following to display a custom alert View:
- (IBAction)buttonAlert:(UIButton *)sender {
self.customAlert = [[CustomAlertViewController alloc] initWithOk:NO AndCancel:NO];
// ...
}
EDIT #2
I tried your solution in a real project, I made it work by using these lines int the caller :
- (IBAction)buttonAlert:(UIButton *)sender {
self.customAlert = [self.storyboard instantiateViewControllerWithIdentifier:#"customAlertView"];
self.customAlert.hasOK = NO;
self.customAlert.hasCancel = YES;
NSString *message = [NSString stringWithFormat:#"La tua offerta %# del 20%% è stata convertita in punti IoSi x10", self.promotionSelected];
[self.customAlert showCustomAlertInView:self.view withMessage:message];
isDeletingItem = YES;
}
In the CustomAlertViewController declare 2 visible properties hasOK and hasCancel in.h.
And modify your .m by adding method :
-(void)viewWillAppear:(BOOL)animated
{
[self removeOkayButton:self.hasOK];
[self removeCancelButton:self.hasCancel];
}
Be sure to modify your storyboard (if eligible) to have the "customAlertView" defined this way :
Don't forget also to bind your UIButton to the controller this can be a mistake too in your implementation :
Hope this will help you :)
I found on the web a tutorial to create custom alert view by using code, if you are interested you can go to this tutorial. I used it for my issue and it worked great! You have to fix a few things, because it uses deprecated command but it's easy to fix it.
If you are interested just take a look about this tutorial. I think you can integrate it in your app and after you can easily use for other stuff if it's necessary. I hope that my answer will help someone.
I have 10 UIImages. When I click the UIButton it displaying under UIScrollView. But I need to implement theUIButtonlike **Next**, ifUIButtonis clicked first time, it displays the firstUIImage`, then after that, on click it displays next image. If I click the back button, the previous image should be displayed.
int currentIndex = 0;
int MAX_COUNT;
NSMutableArray *imageName = [[NSMutableArray alloc] initWithObjects:
#"spices.jpg",
#"spice_powder.jpg",
#"turmeric.jpg",
#"whynani_img3.jpg",
#"spice_blends.jpg",
#"products1.png", nil];
currentIndex = currentIndex + 1;
if(currentIndex > MAX_COUNT) {
currentIndex = MAX_COUNT;
}
for (int i = 0; i<[imageName count]; i++ ) {
UIImageView *mmageView =
[[UIImageView alloc] initWithFrame:CGRectMake(200,200,350,350)];
[mmageView setImage:[UIImage imageNamed:[imageName objectAtIndex:i]]];
[self.view addSubview:mmageView];
}
Declare a global imageView and an int in interface file
UIImageView *imgView;
int index;
In viewDidLoad:
index = 0;
imgView = [[UIImageView alloc] initWithFrame:CGRectMake(200,200,350,350)];
[imgView setImage:[UIImage imageNamed:[imageName objectAtIndex:index]]];
[self.view addSubView:imgView];
In Next Button Action
-(void)nextButtonAction
{
++index;
[previousBtn setEnabled:YES];
if (index > [imageName count])
{
index = [imageName count] - 1;
[nextBtn setEnabled:NO];
}
[imgView setImage:[UIImage imageNamed:[imageName objectAtIndex:index]]];
}
In Previous Button Action
-(void)previousButtonAction
{
--index;
[nextBtn setEnabled:YES];
if (index < 0)
{
index = 0;
[previousBtn setEnabled:NO];
}
[imgView setImage:[UIImage imageNamed:[imageName objectAtIndex:index]]];
}
You can do the same using a UIViewController having 2 UIButtons with custom images depicting forward and back along with UIImageView. On selecting the next / back button load the appropriate image. The image name has to be stored in an NSArray.
Hope this helps.
Edit: sample code as given below,
In .h file
#property(nonatomic, weak) UIImageView *imageView;
#property(nonatomic, weak) UIButton *nextButton;
#property(nonatomic, weak) UIButton *backButton;
(IBAction)btnNextBtn:(id)sender;
(IBAction)btnBackBtn:(id)sender;
In .m file
(void)viewDidLoad {
currentIndex = 0;
NSMutableArray *imageName = [[NSMutableArray alloc] initWithObjects:#"Myprofile.png",
#"great_ideas_wordle2.png", #"Review.png",
#"collaborate.png", nil];
imageView = [[UIImageView alloc] initWithFrame:CGRectMake(200,200,350,350)];
[imageView setImage:[UIImage imageNamed:[imageName objectAtIndex:currentIndex]]];
[self.view addSubView:imageView];
}
(IBAction)btnNextBtn:(id)sender {
currentIndex = currentIndex + 1;
if(currentIndex > MAX_COUNT) {
currentIndex = MAX_COUNT;
}
// load the image view with the currentIndex from the array.
[imageView setImage:[UIImage imageNamed:[imageName objectAtIndex:currentIndex]]];
}
(IBAction)btnBackBtn:(id)sender {
currentIndex = currentIndex - 1;
if (currentIndex < 0) {
currentIndex = 0;
}
// load the image view with the currentIndex from the array.
[imageView setImage:[UIImage imageNamed:[imageName objectAtIndex:currentIndex]]];
}
write this in .h file
#property (nonatomic,retain)IBOutlet UIImageView *imageview1;
#property (nonatomic,retain)IBOutlet UIButton *pre,*next;
#property (nonatomic,retain) NSArray *images;
#property (nonatomic) int currentindex;
-(IBAction)prebtn:(id)sender;
-(IBAction)nextbtn:(id)sender;
write this code in .m file
#implementation ViewController
#synthesize images;
#synthesize currentindex;
#synthesize pre,next;
#synthesize imageview1;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.currentindex = 0;
self.images = [[NSArray alloc] initWithObjects:#"images-2.jpeg",#"images- 3.jpeg",#"images.jpeg", nil];
imageview1.image = [UIImage imageNamed:#"images-2.jpeg"];
[pre setEnabled:NO];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(IBAction)nextbtn:(id)sender{
currentindex = currentindex + 1;
[pre setEnabled:YES];
if (currentindex >= [images count])
{
currentindex = currentindex - 1;
[next setEnabled:NO];
}
imageview1.image = [UIImage imageNamed:[images objectAtIndex:currentindex]];
}
-(IBAction)prebtn:(id)sender{
currentindex = currentindex - 1;
[next setEnabled:YES];
if(currentindex < 0)
{
currentindex = 0;
[pre setEnabled:NO];
}
imageview1.image = [UIImage imageNamed:[images objectAtIndex:currentindex]];
}
#end
Try with this code
.h file
#property(nonatomic, strong) UIImageView *imageView;
#property(nonatomic, strong) UIButton *nextButton;
#property(nonatomic, strong) UIButton *previousButton;
#property(nonatomic, strong) NSMutableArray *imagesArrayName;
#property(nonatomic) int currentIndex;
-(IBAction)btnNextImage:(id)sender;
-(IBAction)btnPreviousImage:(id)sender;
.m file
- (void)viewDidLoad {
[super viewDidLoad];
self.currentIndex = 0;
NSMutableArray *imagesArrayName = [[NSMutableArray alloc] initWithObjects:
#"spices.jpg",
#"spice_powder.jpg",
#"turmeric.jpg",
#"whynani_img3.jpg",
#"spice_blends.jpg",
#"products1.png", nil];
[self.nextButton addTarget:self action:#selector(btnNextImage:) forControlEvents:UIControlEventTouchUpInside];
[self.previousButton addTarget:self action:#selector(btnPreviousImage:) forControlEvents:UIControlEventTouchUpInside];
[self.imageView setImage[UIImage imageNamed:(NSString*)[imagesArrayName objectAtIndex:currenIndex]]];
[self.previousButton setEnabled:FALSE];
}
-(IBAction)btnNextImage:(id)sender {
self.currentIndex = self.currentIndex + 1;
[self.imageView setImage[UIImage imageNamed:(NSString*)[imagesArrayName objectAtIndex:currenIndex]]];
if (self.currentIndex == [self.imagesArrayName count] - 1) {
[self.nextButton setEnabled:FALSE];
}
[self.previousButton setEnabled:TRUE];
}
-(IBAction)btnPreviousImage:(id)sender{
self.currentIndex = self.currentIndex - 1;
[self.imageView setImage[UIImage imageNamed:(NSString*)[imagesArrayName objectAtIndex:currenIndex]]];
if (self.currentIndex == 0) {
[self.previousButton setEnabled:FALSE];
}
[self.nextButton setEnabled:TRUE];
}