Memory leak with CIColor spritekit - memory-leaks

I created a class that would generate a hud item, this hud item can animate the resulting texture which is a gradient created using cicolor that is then saved into a uiimage which is in turn used for an sktexture. I've noticed now that i am getting a lot of memory growth in my app and running it through instruments has shown me this, but i can't for the life figure out whats going on:
Here's the error i get
You can't really see the issue so it's giving me 91.4% on this line of code:
animatedGraphic = [[SKSpriteNode alloc]initWithTexture:[[TextureList sharedManager]returnGradientofSize:[[TextureList sharedManager]returnTextureSize:kGMHUDFlowerTarget] topColor:[CIColor colorWithRed:255.0/255.0 green:171.0/255.0 blue:121.0/255.0] bottomColor:[CIColor colorWithRed:225.0/255.0 green:57.0/255.0 blue:86.0/255.0]] color:[UIColor orangeColor] size:CGSizeMake(0, self.frame.size.height)];
animatedGraphic.anchorPoint = CGPointMake(0, 0.5);
animatedGraphic.zPosition = self.zPosition+1;
[self addChild:animatedGraphic];
Heres the code for the sktexture with a gradient:
-(SKTexture*)returnHorizontalGradientofSize:(CGSize)size
leftColor:(CIColor*)leftColor
rightColor:(CIColor*)rightColor{
CIContext *coreImageContext = [CIContext contextWithOptions:nil];
CIFilter *gradientFilter = [CIFilter filterWithName:#"CILinearGradient"];
[gradientFilter setDefaults];
CIVector *startVector = [CIVector vectorWithX:0 Y:size.height/2];
CIVector *endVector = [CIVector vectorWithX:size.width Y:size.height/2];
[gradientFilter setValue:startVector forKey:#"inputPoint0"];
[gradientFilter setValue:endVector forKey:#"inputPoint1"];
[gradientFilter setValue:leftColor forKey:#"inputColor0"];
[gradientFilter setValue:rightColor forKey:#"inputColor1"];
CGImageRef cgimg = [coreImageContext createCGImage:[gradientFilter outputImage]
fromRect:CGRectMake(0, 0, size.width, size.height)];
UIImage *theImage = [UIImage imageWithCGImage:cgimg];
CFRelease(cgimg);
return [SKTexture textureWithImage:theImage];
}
Heres the code for the hud item:
#import "ItemHud.h"
#import "TextureList.h"
#import "UnlockController.h"
#interface ItemHud ()
#property (nonatomic) double scoreIncrement;
#property (nonatomic) double increment;
#property (nonatomic) double barIncrement;
#property (nonatomic) double updateIncrement;
#property (nonatomic) BOOL barAnimating;
#end
#implementation ItemHud
#synthesize theLabel;
#synthesize theLabelTwo;
#synthesize animatedGraphic;
#synthesize iconGraphic;
-(id)initWithImageNamed:(NSString *)ImageName
withLabel:(NSString *)LabelName
withLabelTwo:(NSString *)LabelNameTwo
withIconGraphic:(NSString *)iconGraphicName
withAnimatedGraphic:(BOOL)AnimatedGraphicName{
if (self = [super init]) {
if (ImageName)
{
self.size = [[TextureList sharedManager]returnTextureSize:ImageName];
self.texture = nil;
self.color = [UIColor colorWithRed:0.0/255.0 green:0.0/255.0 blue:0.0/255.0 alpha:0.65];
self.userInteractionEnabled = NO;
_barAnimating = NO;
}
if (AnimatedGraphicName) {
animatedGraphic = [[SKSpriteNode alloc]initWithTexture:[[TextureList sharedManager]returnGradientofSize:[[TextureList sharedManager]returnTextureSize:kGMHUDFlowerTarget] topColor:[CIColor colorWithRed:255.0/255.0 green:171.0/255.0 blue:121.0/255.0] bottomColor:[CIColor colorWithRed:225.0/255.0 green:57.0/255.0 blue:86.0/255.0]] color:[UIColor orangeColor] size:CGSizeMake(0, self.frame.size.height)];
animatedGraphic.anchorPoint = CGPointMake(0, 0.5);
animatedGraphic.zPosition = self.zPosition+1;
[self addChild:animatedGraphic];
}
if (iconGraphicName) {
if ([iconGraphicName isEqualToString:kGMHUDLevelIcon1] || [iconGraphicName isEqualToString:kGMHUDLevelIcon2] || [iconGraphicName isEqualToString:kGMHUDLevelIcon3] || [iconGraphicName isEqualToString:kGMHUDLevelIcon4]|| [iconGraphicName isEqualToString:kGMHUDLevelIcon5] || [iconGraphicName isEqualToString:kGMHUDLevelIcon6] || [iconGraphicName isEqualToString:kGMHUDLevelIcon7] || [iconGraphicName isEqualToString:kGMHUDLevelIcon8] || [iconGraphicName isEqualToString:kGMHUDLevelIcon9]) {
iconGraphic = [[SKSpriteNode alloc]initWithTexture:[SKTexture textureWithImageNamed:iconGraphicName] color:nil size:[[TextureList sharedManager]returnTextureSize:kGMHUDLevelIcon1]];
}
else{
iconGraphic = [[SKSpriteNode alloc]initWithTexture:[SKTexture textureWithImageNamed:iconGraphicName] color:nil size:[[TextureList sharedManager]returnTextureSize:iconGraphicName]];
}
iconGraphic.zPosition = self.zPosition+1;
[self addChild:iconGraphic];
[self setGraphicRight:NO];
}
if (LabelName) {
theLabel = [SKLabelNode labelNodeWithFontNamed:kFontName];
[theLabel setFontColor:[UIColor whiteColor]];
[theLabel setFontName:kFontName];
[theLabel setFontSize:kFontSizeMDMedium];
[theLabel setHorizontalAlignmentMode:SKLabelHorizontalAlignmentModeLeft];
[theLabel setVerticalAlignmentMode:SKLabelVerticalAlignmentModeCenter];
theLabel.text = LabelName;
[self addChild:theLabel];
[self setHudDefaults:YES];
}
if (LabelNameTwo) {
theLabelTwo = [SKLabelNode labelNodeWithFontNamed:kFontName];
[theLabelTwo setFontColor:[UIColor whiteColor]];
[theLabelTwo setFontName:kFontName];
[theLabelTwo setFontSize:kFontSizeMDMedium];
[theLabelTwo setHorizontalAlignmentMode:SKLabelHorizontalAlignmentModeRight];
[theLabelTwo setVerticalAlignmentMode:SKLabelVerticalAlignmentModeCenter];
theLabelTwo.text = LabelNameTwo;
[self addChild:theLabelTwo];
[self setHudDefaults:NO];
}
}
return self;
}
-(void)setBackgroundImage:(SKTexture*)theTexture{
self.texture = theTexture;
}
-(void)setHudDefaults:(BOOL)singleLabel{
theLabelTwo.position = CGPointMake(self.position.x+self.frame.size.width/2,self.position.y);
animatedGraphic.position = CGPointMake(-self.frame.size.width/2,self.position.y);
if (singleLabel) {
[theLabel setHorizontalAlignmentMode:SKLabelHorizontalAlignmentModeCenter];
theLabel.position = CGPointMake(self.position.x,self.position.y);
}
else{
theLabel.position = CGPointMake(theLabelTwo.position.x-theLabelTwo.frame.size.width/2-20,self.position.y);
[theLabel setHorizontalAlignmentMode:SKLabelHorizontalAlignmentModeRight];
}
theLabel.zPosition = self.zPosition+1;
theLabelTwo.zPosition = self.zPosition+1;
}
-(void)setGraphicRight:(BOOL)placeRight{
if (placeRight) {
iconGraphic.position = CGPointMake(self.frame.size.width/2,-self.frame.size.height/4);
iconGraphic.zPosition = animatedGraphic.zPosition+1;
}
else{
iconGraphic.position = CGPointMake(-self.frame.size.width/2,-self.frame.size.height/4);
iconGraphic.zPosition = animatedGraphic.zPosition+1;
}
}
-(void)setBarProgress:(int)flowerTarget currentFlowers:(int)currentFlowers{
double increment = (double)flowerTarget/100;
//NSLog(#"increment is %f",increment);
double barIncrement = (double)self.frame.size.width/100;
//NSLog(#"BAR increment is %f",barIncrement);
double barState = (barIncrement/increment)*currentFlowers;
//NSLog(#"BAR state is %f",barState);
/*if (animatedGraphic.frame.size.width >= self.frame.size.width && !_barAnimating) {
_barAnimating = YES;
[self animateBar:YES];
}
else if (animatedGraphic.frame.size.width < self.frame.size.width && _barAnimating){
_barAnimating = NO;
[self animateBar:NO];
}*/
animatedGraphic.size = CGSizeMake(barState, self.frame.size.height);
}
-(void)setBarValues:(int)startValue increment:(int)increment nextObject:(int)nextObject{
//NSLog(#"0:Totalscore is %i",[[UserDetails sharedManager]userTotalScore]);
//NSLog(#"1:StartValue %i",startValue);
//NSLog(#"2:Increment %i",increment);
//NSLog(#"3:Nextobject %i",nextObject);
_scoreIncrement = (double)startValue/(double)nextObject;
//NSLog(#"increment is %f",increment);
_barIncrement = (double)self.frame.size.width/100;
//NSLog(#"bar increment is %f",barIncrement);
_updateIncrement = ((double)startValue/_scoreIncrement)/100;
//NSLog(#"update increment is %f",updateIncrement);
//NSLog(#"4:Animate %f",_barIncrement/_updateIncrement*increment);
animatedGraphic.size = CGSizeMake(_barIncrement/_updateIncrement*increment, self.frame.size.height);
}
-(void)updateBarProgress:(int)update{
animatedGraphic.size = CGSizeMake(_barIncrement/_updateIncrement*update, self.frame.size.height);
//hudFx.position = CGPointMake(animatedGraphic.frame.size.width-2, animatedGraphic.position.y);
}
-(void)setBarValues:(int)startValue nextObject:(int)nextObject animated:(BOOL)animated{
// start value is difference between unlock score and current value
// next object is score to unlock item
// all unlocks done
if ([[UnlockController sharedManager]allunlocksOpen]) {
theLabel.text = #"ALL ITEMS UNLOCKED";
return;
}
__block int count = 0;
double increment = (double)startValue/(double)nextObject;
//NSLog(#"increment is %f",increment);
double countUp = nextObject-startValue;
//NSLog(#"countup is %f",countUp);
double barIncrement = (double)self.frame.size.width/100;
//NSLog(#"bar increment is %f",barIncrement);
double updateIncrement = ((double)startValue/increment)/100;
//NSLog(#"update increment is %f",updateIncrement);
if (!animated) {
animatedGraphic.size = CGSizeMake(barIncrement/updateIncrement*startValue, self.frame.size.height);
//hudFx.position = CGPointMake(animatedGraphic.frame.size.width-2, animatedGraphic.position.y);
}
else{
SKAction *delay = [SKAction waitForDuration:0.0];
SKAction *animateCount = [SKAction runBlock:^{
count++;
animatedGraphic.size = CGSizeMake(barIncrement*count, self.frame.size.height);
//hudFx.position = CGPointMake(animatedGraphic.frame.size.width-2, animatedGraphic.position.y);
}];
SKAction *animateSequence = [SKAction sequence:#[animateCount,delay]];
SKAction *repeatSequence = [SKAction repeatAction:animateSequence count:(double)countUp/updateIncrement];
[animatedGraphic runAction:repeatSequence completion:^{
}];
}
}
-(void)animateBar:(BOOL)animate{
SKAction *delay = [SKAction waitForDuration:0.15];
SKAction *changeToAnimateBar = [SKAction runBlock:^{
animatedGraphic.texture = [[TextureList sharedManager]returnGradientofSize:[[TextureList sharedManager]returnTextureSize:kGMHUDFlowerTarget] topColor:[CIColor colorWithRed:255.0/255.0 green:244.0/255.0 blue:155.0/255.0] bottomColor:[CIColor colorWithRed:225.0/255.0 green:57.0/255.0 blue:86.0/255.0]];
}];
SKAction *changeToDefaultBar = [SKAction runBlock:^{
animatedGraphic.texture = [[TextureList sharedManager]returnGradientofSize:[[TextureList sharedManager]returnTextureSize:kGMHUDFlowerTarget] topColor:[CIColor colorWithRed:255.0/255.0 green:171.0/255.0 blue:121.0/255.0] bottomColor:[CIColor colorWithRed:225.0/255.0 green:57.0/255.0 blue:86.0/255.0]];
}];
SKAction *animateSequence = [SKAction sequence:#[changeToAnimateBar,delay,changeToDefaultBar,delay]];
SKAction *animatingBarLoop = [SKAction repeatActionForever:animateSequence];
if (animate) {
[self runAction:animatingBarLoop withKey:#"animatingBar"];
}
else{
[self removeActionForKey:#"animatingBar"];
[self runAction:changeToDefaultBar withKey:#"defaultBar"];
}
}

This turned out to be an issue with the AGSpriteButton class which was hogging memory and therefore eventually causing a crash when an advert loaded, you can find a fix here:
SKScene Fails to deallocate memory resulting in bounded memory growth

Related

xcode Sprite Kit Score counts and Coin is removed before Hero touches it

I am a Newbie, and I am making my first game. Everything is working great accept when I added coins.
-(void)spawnCoin {
SKNode* coinNode = [SKNode node];
coinNode.position = CGPointMake(self.frame.size.width + 150 + (arc4random() % 100), 0 );
coinNode.zPosition = -10;
CGFloat y = arc4random() % (NSInteger)( self.frame.size.height / 2 ) + 40;
SKTexture* coinTexture1 = [SKTexture textureWithImageNamed:#"Coins_1"];
coinTexture1.filteringMode = SKTextureFilteringNearest;
SKTexture* coinTexture2 = [SKTexture textureWithImageNamed:#"Coins_2"];
coinTexture2.filteringMode = SKTextureFilteringNearest;
SKTexture* coinTexture3 = [SKTexture textureWithImageNamed:#"Coins_3"];
coinTexture3.filteringMode = SKTextureFilteringNearest;
SKTexture* coinTexture4 = [SKTexture textureWithImageNamed:#"Coins_4"];
coinTexture4.filteringMode = SKTextureFilteringNearest;
SKTexture* coinTexture5 = [SKTexture textureWithImageNamed:#"Coins_5"];
coinTexture5.filteringMode = SKTextureFilteringNearest;
SKTexture* coinTexture6 = [SKTexture textureWithImageNamed:#"Coins_6"];
coinTexture6.filteringMode = SKTextureFilteringNearest;
SKAction* spin = [SKAction repeatActionForever:[SKAction animateWithTextures:#[coinTexture1, coinTexture2, coinTexture3, coinTexture4, coinTexture5, coinTexture6] timePerFrame:0.05]];
_coin = [SKSpriteNode spriteNodeWithTexture:coinTexture6];
[_coin runAction:spin];
[_coin setScale:1.0];
_coin.position = CGPointMake( 0, y );
_coin.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:_coin.size];
_coin.physicsBody.dynamic = NO;
_coin.physicsBody.categoryBitMask = scoreCategory;
_coin.physicsBody.contactTestBitMask = birdCategory;
[coinNode addChild:_coin];
[coinNode runAction:_moveCoinsAndRemove];
[_coins addChild:coinNode];
SKNode* contactNode = [SKNode node];
contactNode.position = CGPointMake(0,y);
contactNode.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:_coin.size];
contactNode.physicsBody.dynamic = NO;
contactNode.physicsBody.categoryBitMask = scoreCategory;
contactNode.physicsBody.contactTestBitMask = birdCategory;
[_coin addChild:contactNode];
}
(void)didBeginContact:(SKPhysicsContact *)contact {
if (_score > _heighscore) {
[[NSUserDefaults standardUserDefaults] setInteger:_score forKey:#"HighScoreSave"];
// Vibrate
AudioServicesPlayAlertSound(kSystemSoundID_Vibrate);
}
if( _moving.speed > 0 ) {
if( ( contact.bodyA.categoryBitMask & scoreCategory ) == scoreCategory || ( contact.bodyB.categoryBitMask & scoreCategory ) == scoreCategory ) {
// contact with score entity
SKNode* coinNode = contact.bodyB.node;
[coinNode removeFromParent];
coinNode.hidden = YES;
_score++;
_scoreLabelNode.text = [NSString stringWithFormat:#"%ld", (long)_score];
Solved this,
coinNode.position = CGPointMake(self.frame.size.width / 1 + _coin.size.width / 1 - 50 + (arc4random() % 50), 0 );
coinNode.zPosition = -10;
CGFloat y = arc4random() % (NSInteger)( self.frame.size.height / 2 ) + 20;
But now I have a NEW problem. When my hero hits the coins they react like obstacles and he is killed instead of just counting and vanishing. It add to to the score for the hit, but also stops the entire game as if the hero has been killed.
Here is my code:
[_coin setScale:1.0];
_coin.position = CGPointMake( 0, y );
_coin.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:_coin.size];
_coin.physicsBody.dynamic = NO;
_coin.physicsBody.usesPreciseCollisionDetection = YES;
_coin.physicsBody.categoryBitMask = coinCategory;
_coin.physicsBody.collisionBitMask = 0;
_coin.physicsBody.contactTestBitMask = birdCategory;
[coinNode addChild:_coin];
SKNode* coinContactNode = [SKNode node];
coinContactNode.position = CGPointMake( _bird.size.width / 0.5, CGRectGetMidY( _coin.frame ) );
coinContactNode.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:CGSizeMake(_coin.size.width, _coin.size.height)];
coinContactNode.physicsBody.dynamic = NO;
coinContactNode.physicsBody.usesPreciseCollisionDetection = YES;
coinContactNode.physicsBody.categoryBitMask = coinCategory;
coinContactNode.physicsBody.collisionBitMask = 0;
coinContactNode.physicsBody.contactTestBitMask = birdCategory;
[_coin addChild:coinContactNode];
[coinNode runAction:_moveCoinsAndRemove];
[_coins addChild:coinNode];
And here:
(void)didBeginContact:(SKPhysicsContact *)contact {
if (_score > _heighscore) {
[[NSUserDefaults standardUserDefaults] setInteger:_score forKey:#"HighScoreSave"];
// Sound effect – Score
[self runAction:[SKAction playSoundFileNamed:#"Tap_It_Real_Good.mp3" waitForCompletion:NO]];
// Vibrate
AudioServicesPlayAlertSound(kSystemSoundID_Vibrate);
}
if( _moving.speed > 0 ) {
if( ( contact.bodyA.categoryBitMask & coinCategory ) == coinCategory || ( contact.bodyB.categoryBitMask & coinCategory ) == coinCategory ) {
_score2++;
_scoreLabelNode2.text = [NSString stringWithFormat:#"%ld", (long)_score2];
// Sound effect – Score
[self runAction:[SKAction playSoundFileNamed:#"Tap_It.mp3" waitForCompletion:NO]];
// Add a little visual feedback for the score increment
[_scoreLabelNode2 runAction:[SKAction sequence:#[[SKAction scaleTo:1.5 duration:0.2], [SKAction scaleTo:1.0 duration:0.2]]]];
}
if( ( contact.bodyA.categoryBitMask & scoreCategory ) == scoreCategory || ( contact.bodyB.categoryBitMask & scoreCategory ) == scoreCategory ) {
// Bird has contact with score entity
_score++;
// Sound effect – Score
[self runAction:[SKAction playSoundFileNamed:#"Tap_It.mp3" waitForCompletion:NO]];
_scoreLabelNode.text = [NSString stringWithFormat:#"%ld", (long)_score];
// Add a little visual feedback for the score increment
[_scoreLabelNode runAction:[SKAction sequence:#[[SKAction scaleTo:1.5 duration:0.2], [SKAction scaleTo:1.0 duration:0.2]]]];
} else {
// Bird has collided with world
_moving.speed = 0;
_bird.physicsBody.collisionBitMask = worldCategory;
_coins.speed = 0;
_bird.speed = 0;
[_bird runAction:[SKAction rotateByAngle:M_PI * _bird.position.y * 0.01 duration:_bird.position.y * 0.003] completion:^{
}];
// Sound effect – Collision
[self runAction:[SKAction playSoundFileNamed:#"Tap_It.mp3" waitForCompletion:NO]];
// Vibrate
AudioServicesPlayAlertSound(kSystemSoundID_Vibrate);
// Flash background if contact is detected
[self removeActionForKey:#"flash"];
[self runAction:[SKAction sequence:#[[SKAction repeatAction:[SKAction sequence:#[[SKAction runBlock:^{
self.backgroundColor = [SKColor redColor];
}], [SKAction waitForDuration:0.05], [SKAction runBlock:^{
self.backgroundColor = _skyColor;
}], [SKAction waitForDuration:0.05]]] count:4], [SKAction runBlock:^{
_canRestart = YES;
}]]] withKey:#"flash"];
}
}
}
Any help. Thanks :)

Xcode :How can I stop video in webview and still using webview

if I use
-(void)viewWillDisappear:(BOOL)animated
{
[subView loadHTMLString:nil baseURL:nil];
}
my Webview can't worked
I try to do this
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
pageControlBeingUsed = NO;
[subView loadHTMLString:nil baseURL:nil];
}
I just want to go next page with paging scrollview and stop video on next page
this my code scrollview paging
book = [[NSMutableArray alloc] initWithObjects:#"page11",#"page12",#"page13",#"page14",#"page15", nil];
for (int i = 0; i < [book count]; i++) {
CGRect frame;
frame.origin.x = self.scrollView.frame.size.height * i;
frame.origin.y = 0;
frame.size = CGSizeMake(1024,768);
subView = [[UIWebView alloc] initWithFrame:frame];
NSURL *url = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:[book objectAtIndex:i] ofType:#"html" inDirectory:#""]];
[subView loadRequest:[NSURLRequest requestWithURL:url]];
subView.scalesPageToFit = YES;
[scrollView setBounces:NO];
[scrollView addSubview:subView];
}
scrollView.contentSize = CGSizeMake(1024 * [book count], 768);
[scrollView setFrame:CGRectMake(0, 0, 1024, 768)];
Can I play video and stop on I next page? //Please advice
sorry my English isn't well
You need to load a blank page into the UIWebView to stop the audio:
[self.webView loadRequest:NSURLRequestFromString(#"about:blank")];
or
[self.webView loadHTMLString:#"" baseURL:nil];
Thank for Advice. I try this is works for me
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
pageControlBeingUsed = NO;
CGFloat pageWidth = self.scrollView.frame.size.width;
int page = floor((self.scrollView.contentOffset.x - pageWidth / 2) / pageWidth) + 1;
for(int i = 0; i < _pageAmount ; i++){
NSIndexPath *indexPath = [NSIndexPath indexPathForItem:i inSection:0];
[_collectionView cellForItemAtIndexPath:indexPath].backgroundColor = [UIColor clearColor];
}
currentPage = page;
if (currentPage > 0 && currentPage < [book count]-1) {
[[self.scrollView.subviews objectAtIndex:currentPage-1]reload];//
[[self.scrollView.subviews objectAtIndex:currentPage+1]reload];
}
if(self.interfaceOrientation == 1 || self.interfaceOrientation == 2){
NSIndexPath *indexPath = [NSIndexPath indexPathForItem:page inSection:0];
[_collectionView cellForItemAtIndexPath:indexPath].backgroundColor = [UIColor redColor];
}
}

Custom MKAnnotaionView, Display title/subtitle Position on Map

1) My annotation shows the title and subtitle of not.
I have already tried a lot, but I can not.
2) If an annotation has been selected, the annotation will be centered in the middle of the window. So the map is moved. Any idea?
3) My Callout button does not work anymore, I've got the # selector (openAnything) but I want to use this function is triggered - (void) mapView: (MKMapView *) mapView annotationView: (MKAnnotationView *) view calloutAccessoryControlTapped: (UIControl *) control {
Enough to ask, here's a video and some source code
http://www.youtube.com/watch?v=Ur1aqeYEFHw&feature=youtube_gdata_player
Thanks
TAPPMapViewControler.m
- (MKAnnotationView *)mapView:(MKMapView *)MapView viewForAnnotation:(id<MKAnnotation>)annotation {
if ([annotation isKindOfClass:[TAPPMapAnnotation class]])
{
static NSString *shopAnnotationIdentifier = #"Filiale";
//pinView = (MKPinAnnotationView *)
TAPPMapAnnotationCustom* pinView = (TAPPMapAnnotationCustom*)[self.myMapView dequeueReusableAnnotationViewWithIdentifier:shopAnnotationIdentifier];
[self.myMapView dequeueReusableAnnotationViewWithIdentifier:shopAnnotationIdentifier];
if (pinView == nil)
{
// if an existing pin view was not available, create one
TAPPMapAnnotationCustom *customPinView = [[TAPPMapAnnotationCustom alloc] initWithAnnotation:annotation reuseIdentifier:shopAnnotationIdentifier];
customPinView.image = [UIImage imageNamed:#"map_pin.png"];
return customPinView;
}
else
{
pinView.annotation = annotation;
}
return pinView;
}
return nil;
}
-(void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control {
TAPPMapAnnotation *theAnnotation = view.annotation;
TAPPMapAnnotationDetail *theController = [self.storyboard instantiateViewControllerWithIdentifier:#"MapAnnotationDetail"];
theController.theAnnotationId = theAnnotation.objectId;
[self.navigationController pushViewController:theController animated:YES];
}
TAPPMapAnnotationCustom.h
#import <MapKit/MapKit.h>
#interface TAPPMapAnnotationCustom : MKAnnotationView
#property (strong, nonatomic) UIImageView *calloutView;
#property (strong, nonatomic) UILabel *title;
#property (strong, nonatomic) UILabel *subTitle;
- (void)setSelected:(BOOL)selected animated:(BOOL)animated;
- (void)animateCalloutAppearance:(BOOL)inAdd;
#end
TAPPMapAnnotationCustom.m
#import "TAPPMapAnnotationCustom.h"
#import "TAPPMapAnnotation.h"
#implementation TAPPMapAnnotationCustom
- (void)setSelected:(BOOL)selected animated:(BOOL)animated{
[super setSelected:selected animated:animated];
if(selected)
{
// Remove Image, because we set a second large one.
self.image = Nil;
UIImage *imageBack = [[UIImage imageNamed:#"map_pin.png"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 35, 0, 6)];
self.calloutView = [[UIImageView alloc]initWithImage:imageBack];
[self.calloutView setFrame:CGRectMake(0,0,0,0)];
[self.calloutView sizeToFit];
[self addSubview:self.calloutView ];
// Callout Button
UIButton* rightButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
[rightButton addTarget:self action:#selector(openAnything) forControlEvents:UIControlEventTouchUpInside];
rightButton.frame = CGRectMake(0
, ((self.calloutView.frame.size.height-6) / 2)-(rightButton.frame.size.height / 2)
, rightButton.frame.size.width
, rightButton.frame.size.height);
self.rightCalloutAccessoryView = rightButton;
self.rightCalloutAccessoryView.hidden = YES;
self.rightCalloutAccessoryView.alpha = 0;
[self addSubview:self.rightCalloutAccessoryView];
// Start Annimation
[self animateCalloutAppearance:YES];
} else {
//Start Annimation and Remove from view
[self animateCalloutAppearance:NO];
}
}
- (void)didAddSubview:(UIView *)subview{
if ([[[subview class] description] isEqualToString:#"UICalloutView"]) {
for (UIView *subsubView in subview.subviews) {
if ([subsubView class] == [UIImageView class]) {
UIImageView *imageView = ((UIImageView *)subsubView);
[imageView removeFromSuperview];
}else if ([subsubView class] == [UILabel class]) {
UILabel *labelView = ((UILabel *)subsubView);
[labelView removeFromSuperview];
}
}
}
}
- (void)animateCalloutAppearance:(BOOL)inAdd {
if (inAdd == YES) {
self.rightCalloutAccessoryView.hidden = NO;
[UIView animateWithDuration:0.4 delay:0 options: UIViewAnimationOptionTransitionNone
animations:^{
self.calloutView.frame = CGRectMake(self.calloutView.frame.origin.x
, self.calloutView.frame.origin.y
, self.calloutView.frame.size.width+150
, self.calloutView.frame.size.height);
self.rightCalloutAccessoryView.alpha = 1;
self.rightCalloutAccessoryView.frame = CGRectMake(self.calloutView.frame.size.width - (self.rightCalloutAccessoryView.frame.size.width)
, self.rightCalloutAccessoryView.frame.origin.y
, self.rightCalloutAccessoryView.frame.size.width
, self.rightCalloutAccessoryView.frame.size.height);
} completion:^(BOOL finished){ }];
} else {
[UIView animateWithDuration:0.4 delay:0 options: UIViewAnimationOptionTransitionNone
animations:^{
self.rightCalloutAccessoryView.alpha = 0;
self.rightCalloutAccessoryView.frame = CGRectMake(0
, self.rightCalloutAccessoryView.frame.origin.y
, self.rightCalloutAccessoryView.frame.size.width
, self.rightCalloutAccessoryView.frame.size.height);
self.calloutView.frame = CGRectMake(self.calloutView.frame.origin.x
, self.calloutView.frame.origin.y
, self.calloutView.frame.size.width-150
, self.calloutView.frame.size.height);
} completion:^(BOOL finished){
self.image = [UIImage imageNamed:#"map_pin.png"];
[self.calloutView removeFromSuperview];
[self.rightCalloutAccessoryView removeFromSuperview];
}];
}
}
#end
Your annotation class needs to have a subtitle attribute, yours has subTitle.
If calloutAccessoryControlTapped is not being called it is usually a sign your MKMapview's delegate has not been set. However you're only setting the accessory button when it gets selected. Do you have a good reason for that? Since the callout window won't be visible until it is selected, I would advise you to set the accessory button in viewForAnnotation and let it appear when the callout window does.
I fix the first one:
TAPPMapAnnotation *theAnnotation = (TAPPMapAnnotation *)self.annotation;
self.title = [[UILabel alloc]init];
self.title.font = [UIFont systemFontOfSize:12.0];
self.title.textColor = [UIColor whiteColor];
self.title.backgroundColor = [UIColor clearColor];
self.title.text = theAnnotation.title;
[...]
[self.theView addSubview:self.title];

cocos2d box2d scale sprite -> removechild (how?)

I am little slow in English, please do understand.
Here is my source code:
- (void)createBall:(CGPoint)touchedAt{
CGSize winSize = [CCDirector sharedDirector].winSize;
ball2 = [CCSprite spriteWithFile:#"Ball.png" rect:CGRectMake(0, 0, 54, 54)];
ball2.position = ccp(touchedAt.x,touchedAt.y);
[self addChild:ball2];
b2BodyDef ballBodyDef2;
ballBodyDef2.type = b2_dynamicBody;
ballBodyDef2.position.Set(touchedAt.x/PTM_RATIO, touchedAt.y/PTM_RATIO);
ballBodyDef2.userData = ball2;
b2Body *body2 = _world->CreateBody(&ballBodyDef2);
b2CircleShape circle;
circle.m_radius = 89.0/PTM_RATIO;//(arc4random()*26.0)/PTM_RATIO;
b2FixtureDef ballShapeDef2;
ballShapeDef2.shape = &circle;
ballShapeDef2.density = 1.0f;
ballShapeDef2.friction = 0.2f;
ballShapeDef2.restitution = 0.8f;
body2->CreateFixture(&ballShapeDef2);
}
-(void)createBall2
{
CGSize winSize = [CCDirector sharedDirector].winSize;
globalSprite = [CCSprite spriteWithFile:#"Ball.png"];
globalSprite.position = ccp(winSize.width/2 + globalSprite.contentSize.width, winSize.height/2);
[self addChild:globalSprite];
b2BodyDef ballBodyDef3;
ballBodyDef3.type = b2_dynamicBody;
ballBodyDef3.position.Set(100/PTM_RATIO, 100/PTM_RATIO);
ballBodyDef3.userData = globalSprite ;
b2Body *body3 = _world->CreateBody(&ballBodyDef3);
b2CircleShape circle;
circle.m_radius = 26.0/PTM_RATIO;//(arc4random()*26.0)/PTM_RATIO;
b2FixtureDef ballShapeDef3;
ballShapeDef3.shape = &circle;
ballShapeDef3.density = 1.0f;
ballShapeDef3.friction = 0.2f;
ballShapeDef3.restitution = 0.8f;
body3->CreateFixture(&ballShapeDef3);
}
// initialize your instance here
-(id) init
{
if( (self=[super init])) {
// enable touch
// enable accelerometer
CGSize winSize = [CCDirector sharedDirector].winSize;
self.isAccelerometerEnabled = YES;
self.isTouchEnabled = YES;
// Create sprite and add it to the layer
// Create a world
b2Vec2 gravity = b2Vec2(0.0f, 0.0f);
bool doSleep = true;
_world = new b2World(gravity, doSleep);
// Create edges around the entire screen
b2BodyDef groundBodyDef;
groundBodyDef.position.Set(0,0);
b2Body *groundBody = _world->CreateBody(&groundBodyDef);
b2PolygonShape groundBox;
b2FixtureDef boxShapeDef;
boxShapeDef.shape = &groundBox;
groundBox.SetAsEdge(b2Vec2(0,0), b2Vec2(winSize.width/PTM_RATIO, 0));
groundBody->CreateFixture(&boxShapeDef);
groundBox.SetAsEdge(b2Vec2(0,0), b2Vec2(0, winSize.height/PTM_RATIO));
groundBody->CreateFixture(&boxShapeDef);
groundBox.SetAsEdge(b2Vec2(0, winSize.height/PTM_RATIO), b2Vec2(winSize.width/PTM_RATIO, winSize.height/PTM_RATIO));
groundBody->CreateFixture(&boxShapeDef);
groundBox.SetAsEdge(b2Vec2(winSize.width/PTM_RATIO, winSize.height/PTM_RATIO), b2Vec2(winSize.width/PTM_RATIO, 0));
groundBody->CreateFixture(&boxShapeDef);
// Create ball body and shape
[self schedule:#selector(tick:)];
//[self schedule:#selector(gameLogic:) interval:1.0];
[self createBall2];
}
return self;
}
- (void)ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
// Choose one of the touches to work with
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInView:[touch view]];
location = [[CCDirector sharedDirector] convertToGL:location];
[self createBall:location];
}
- (void)tick:(ccTime) dt {
_world->Step(dt, 10, 10);
for(b2Body *b = _world->GetBodyList(); b; b=b->GetNext()) {
if (b->GetUserData() != NULL) {
CCSprite *ballData = (CCSprite *)b->GetUserData();
ballData.position = ccp(b->GetPosition().x * PTM_RATIO,
b->GetPosition().y * PTM_RATIO);
ballData.rotation = -1 * CC_RADIANS_TO_DEGREES(b->GetAngle());
}
}
}
I want to
touch -> sprite create(circle) -> sprite scale -> sprite remove
but
- (void)tick:(ccTime) dt <---------- this is simulator turn off!
I want to way
Try this :
world->DestroyBody(sprite);

How to manage UITableView + Dynamic Custom Cell(UIBUtton + UITextField + UIBUtton) Insertion?

I am having problem in managing UITableView. I 'm posting a screenshot here to briefly explain the problem. Image 1 shows the default View when First Time view Appears. When I tap on yellow button(Yellow Button is in a custom table section header view) I open an UIAlertView with table in it like shown in the image 2. Then selecting any option I insert a custom cell with a button,textfield and another button. I have a mutable Array for each section so when I select an option I add that string into the corresponding section array and reloadtable.See image 3. Now when I enter values in UITextfields the values replaced by another cells. See the two images below for understanding the problem. image 4. Also when I delete a cell and insert a new the textfield is preloaded with previous value.
And here is the .m file implementation code for analyze the problem
#import "contactsViewController.h"
#import "textFieldCell.h"
#import "SBTableAlert.h"
#import "PhoneFieldCell.h"
#import "DHValidation.h"
#define kTextFieldTag 222
#define kTitleButtonTag 111
#define MAX_LENGTH 20
#define charecterLimit 13
#define PHONE_NUMBER #"0123456789+-"
#implementation contactsViewController
#synthesize currentTextField;
#synthesize choiceList;
#synthesize labelHeaders;
#synthesize selectedIndexPath;
#synthesize aTable;
#synthesize customText;
#synthesize currentSelectionType;
#synthesize phoneList;
#synthesize emailList;
#synthesize otherDetailsList;
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
[super viewDidLoad];
//Prepare array's for display in table header and in custom alert option table
[self prepareDataForTable];
[self initializeProperties];
//Set selected index to -1 by default
selectedIndex = -1;
}
//prepare array's for table
- (void) prepareDataForTable {
NSArray *temp = [[NSArray alloc] initWithObjects:#"work",#"home",#"mobile",#"custom",nil];
self.choiceList = temp;
[temp release];
NSArray *temp1 = [[NSArray alloc] initWithObjects:#"First Name",#"Last Name",nil];
self.labelHeaders = temp1;
[temp1 release];
}
- (void) initializeProperties {
//Initialize Mutable array's
NSMutableArray *temp = [[NSMutableArray alloc] initWithCapacity:0];
self.phoneList = temp;
[temp release];
NSMutableArray *temp1 = [[NSMutableArray alloc] initWithCapacity:0];
self.emailList = temp1;
[temp1 release];
NSMutableArray *temp2 = [[NSMutableArray alloc] initWithCapacity:0];
self.otherDetailsList = temp2;
[temp2 release];
}
#pragma mark -
- (IBAction) btnCancelTapped:(id) sender {
[self dismissModalViewControllerAnimated:YES];
}
- (IBAction) btnDoneTapped:(id) sender {
[self.currentTextField resignFirstResponder];
//TODO: Fetch all the data from all the cells and notify the delegate.
NSMutableDictionary *allSectionsData = [[[NSMutableDictionary alloc] initWithCapacity:0] autorelease];
NSMutableDictionary *section1Dictionary = [[[NSMutableDictionary alloc] initWithCapacity:0] autorelease];
NSMutableDictionary *phoneSectionDictionary = [[[NSMutableDictionary alloc] initWithCapacity:0] autorelease];
NSMutableDictionary *emailSectionDictionary = [[[NSMutableDictionary alloc] initWithCapacity:0] autorelease];
NSMutableDictionary *otherSectionDictionary = [[[NSMutableDictionary alloc] initWithCapacity:0] autorelease];
//For Section 0
for (unsigned rowIndex = 0; rowIndex < 2; rowIndex++) {
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:rowIndex inSection:0];
UITableViewCell *cell = nil;
cell = (textFieldCell*)[aTable cellForRowAtIndexPath:indexPath];
UITextField *txtf = (UITextField *)[cell viewWithTag:kTextFieldTag];
//TextField validation
DHValidation *validation = [[DHValidation alloc] init];
NSString *str = [txtf.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
NSString *alertMessage = nil;
BOOL isvalid = NO;
if(![validation validateNotEmpty:str])
alertMessage = #"NameField should not be Empty";
else
isvalid = TRUE;
if(!isvalid){
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Error" message:alertMessage delegate:self cancelButtonTitle:#"Ok" otherButtonTitles:nil];
[alert show];
[alert release];
return ;
}
[validation release];
NSString *type = nil;
NSString *value = nil;
if(rowIndex == 0)
type = #"First Name";
else if(rowIndex == 1){
type = #"Last Name";
}
value = txtf.text;
if(!value){
//Do not insert that value in the dictinary
value = #"";
}else {
NSDictionary *dictionary = [NSDictionary dictionaryWithObjectsAndKeys:type,#"type",value,#"value",nil];
[section1Dictionary setObject:dictionary forKey:[NSNumber numberWithInt:rowIndex]];
}
}
if([section1Dictionary count] > 0) {
[allSectionsData setObject:section1Dictionary forKey:#"PersonalDetailsSection"];
}
//For Section 1
for (unsigned rowIndex = 0; rowIndex < [phoneList count]; rowIndex++) {
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:rowIndex inSection:1];
UITableViewCell *cell = nil;
cell = (PhoneFieldCell*)[aTable cellForRowAtIndexPath:indexPath];
UITextField *txtf = (UITextField *)[cell viewWithTag:kTextFieldTag];
UIButton *btnTitle = (UIButton*)[cell viewWithTag:kTitleButtonTag];
NSString *type = nil;
NSString *value = nil;
type = [btnTitle currentTitle];
value = [txtf text];
if(!value || [[value stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] isEqualToString:#""] ){
//Do not insert that value in the dictinary
continue;
}else {
NSDictionary *dictionary = [NSDictionary dictionaryWithObjectsAndKeys:type,#"type",value,#"value",nil];
[phoneSectionDictionary setObject:dictionary forKey:[NSNumber numberWithInt:rowIndex]];
//[phoneSectionDictionary setObject:value forKey:type];
}
}
if([phoneSectionDictionary count] > 0) {
[allSectionsData setObject:phoneSectionDictionary forKey:#"PhoneSection"];
}
//For Section 2
for (unsigned rowIndex = 0; rowIndex < [emailList count]; rowIndex++) {
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:rowIndex inSection:2];
UITableViewCell *cell = nil;
cell = (PhoneFieldCell*)[aTable cellForRowAtIndexPath:indexPath];
UITextField *txtf = (UITextField *)[cell viewWithTag:kTextFieldTag];
UIButton *btnTitle = (UIButton*)[cell viewWithTag:kTitleButtonTag];
NSString *type = nil;
NSString *value = nil;
type = [btnTitle currentTitle];
value = [txtf text];
if(!value || [[value stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] isEqualToString:#""] ){
//Do not insert that value in the dictinary
continue;
}else {
NSDictionary *dictionary = [NSDictionary dictionaryWithObjectsAndKeys:type,#"type",value,#"value",nil];
[emailSectionDictionary setObject:dictionary forKey:[NSNumber numberWithInt:rowIndex]];
}
}
if([emailSectionDictionary count] > 0) {
[allSectionsData setObject:emailSectionDictionary forKey:#"EmailSection"];
}
//for Section 3
for (unsigned rowIndex = 0; rowIndex < [phoneList count]; rowIndex++) {
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:rowIndex inSection:3];
UITableViewCell *cell = nil;
cell = (PhoneFieldCell*)[aTable cellForRowAtIndexPath:indexPath];
UITextField *txtf = (UITextField *)[cell viewWithTag:kTextFieldTag];
UIButton *btnTitle = (UIButton*)[cell viewWithTag:kTitleButtonTag];
NSString *type = nil;
NSString *value = nil;
type = [btnTitle currentTitle];
value = [txtf text];
if(!value || [[value stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] isEqualToString:#""] ){
//Do not insert that value in the dictinary
continue;
}else {
NSDictionary *dictionary = [NSDictionary dictionaryWithObjectsAndKeys:type,#"type",value,#"value",nil];
[otherSectionDictionary setObject:dictionary forKey:[NSNumber numberWithInt:rowIndex]];
//[phoneSectionDictionary setObject:value forKey:type];
}
}
if([otherSectionDictionary count] > 0) {
[allSectionsData setObject:otherSectionDictionary forKey:#"OtherSection"];
}
}
#pragma mark -
#pragma mark UITableView Data Source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 4;
}
// Returns the number of rows in a given section.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSInteger count = 0;
switch (section) {
case 0:
count = 2;
break;
case 1://Phone
count = [phoneList count];
break;
case 2://Email
count = [emailList count];
break;
case 3://Other
count = [otherDetailsList count];
break;
default:
count = 0;
break;
}
return count;
}
// Returns the cell for a given indexPath.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"textFieldCustomCell";
static NSString *PhoneFieldCustomCellIdentifier = #"PhoneFieldCustomCell";
static NSString *EmailFieldCustomCellIdentifier = #"EmailFieldCustomCell";
static NSString *OtherDetailsCustomCellIdentifier = #"OtherDetailsCustomCell";
UITableViewCell *cell = nil;
switch (indexPath.section) {
case 0:{
cell = (textFieldCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"textFieldCell" owner:self options:nil];
for (id currentObject in topLevelObjects){
if ([currentObject isKindOfClass:[textFieldCell class]]){
cell = (textFieldCell *) currentObject;
break;
}
}
}
}
break;
case 1:{
cell = (PhoneFieldCell *)[tableView dequeueReusableCellWithIdentifier:PhoneFieldCustomCellIdentifier];
if (cell == nil) {
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"PhoneFieldCell" owner:self options:nil];
for (id currentObject in topLevelObjects){
if ([currentObject isKindOfClass:[PhoneFieldCell class]]){
cell = (PhoneFieldCell *) currentObject;
((PhoneFieldCell *)cell).enterText.delegate = self;
((PhoneFieldCell *)cell).enterText.text = nil;
break;
}
}
}
}
break;
case 2:{
cell = (EmailFieldCell *)[tableView dequeueReusableCellWithIdentifier:EmailFieldCustomCellIdentifier];
if (cell == nil) {
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"EmailFieldCell" owner:self options:nil];
for (id currentObject in topLevelObjects){
if ([currentObject isKindOfClass:[EmailFieldCell class]]){
cell = (EmailFieldCell *) currentObject;
((EmailFieldCell *)cell).enterText.delegate = self;
((EmailFieldCell *)cell).enterText.text = nil;
break;
}
}
}
}
break;
case 3:{
cell = (OtherDetailsCell *)[tableView dequeueReusableCellWithIdentifier:OtherDetailsCustomCellIdentifier];
if (cell == nil) {
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"OtherDetailsCell" owner:self options:nil];
for (id currentObject in topLevelObjects){
if ([currentObject isKindOfClass:[OtherDetailsCell class]]){
cell = (OtherDetailsCell *) currentObject;
((OtherDetailsCell *)cell).enterText.delegate = self;
((OtherDetailsCell *)cell).enterText.text = nil;
break;
}
}
}
}
break;
default:
break;
}
//Setup cell data
switch (indexPath.section) {
case 0:{
((textFieldCell*)cell).aTextField.delegate = self;
if(indexPath.row == 0){
((textFieldCell*)cell).aTextField.placeholder = #"Enter First Name";
}
if(indexPath.row == 1){
((textFieldCell*)cell).aTextField.placeholder = #"Enter Last Name";
}
((textFieldCell*)cell).aLabel.text = [self.labelHeaders objectAtIndex:indexPath.row];
}
break;
case 1:{
NSString *str = [phoneList objectAtIndex:indexPath.row];
[((PhoneFieldCell *)cell).changeBtn setTitle:str forState:UIControlStateNormal];
[((PhoneFieldCell *)cell).changeBtn addTarget:self action:#selector(changeButtonTapped:) forControlEvents:UIControlEventTouchUpInside];
((PhoneFieldCell *)cell).btnDeleteCell.tag = indexPath.row;
[((PhoneFieldCell *)cell).btnDeleteCell addTarget:self action:#selector(deleteButtonTapped:) forControlEvents:UIControlEventTouchUpInside];
}
break;
case 2:{
NSString *str = [emailList objectAtIndex:indexPath.row];
[((EmailFieldCell *)cell).changeBtn setTitle:str forState:UIControlStateNormal];
[((EmailFieldCell *)cell).changeBtn addTarget:self action:#selector(changeButtonTapped:) forControlEvents:UIControlEventTouchUpInside];
((EmailFieldCell *)cell).btnDeleteCell.tag = indexPath.row;
[((EmailFieldCell *)cell).btnDeleteCell addTarget:self action:#selector(deleteButtonTapped:) forControlEvents:UIControlEventTouchUpInside];
}
break;
case 3:{
NSString *str = [otherDetailsList objectAtIndex:indexPath.row];
[((OtherDetailsCell *)cell).changeBtn setTitle:str forState:UIControlStateNormal];
[((OtherDetailsCell *)cell).changeBtn addTarget:self action:#selector(changeButtonTapped:) forControlEvents:UIControlEventTouchUpInside];
((OtherDetailsCell *)cell).btnDeleteCell.tag = indexPath.row;
[((OtherDetailsCell *)cell).btnDeleteCell addTarget:self action:#selector(deleteButtonTapped:) forControlEvents:UIControlEventTouchUpInside];
}
break;
default:
break;
}
return cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
return 30;
}
- (UIView*) tableView: (UITableView*) tableView viewForHeaderInSection: (NSInteger) section {
if (section == 0) {
return nil;
}
return [self headerViewForSection:section];
}
// Handle row selection
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
}
- (UIView*) headerViewForSection:(NSInteger)section {
CGRect lblTitleFrame = CGRectMake(15, 0, 200, 20);
CGRect btnFrame = CGRectMake(280.0, 0.0, 30.0, 30.0);
CGRect headerViewFrame = CGRectMake(0,0, 40, 30);
NSString *lblTitleText = nil;
switch (section) {
case 1://phone
lblTitleText = #"Phone";
break;
case 2://email
lblTitleText = #"Email";
break;
case 3://other details
lblTitleText = #"Other";
break;
default:
break;
}
//Create a header view with a label and a button
UIView *headerView = [[[UIView alloc] initWithFrame:headerViewFrame] autorelease];
UILabel *titleForTable = [[UILabel alloc]initWithFrame:lblTitleFrame];
titleForTable.text = lblTitleText;
titleForTable.backgroundColor = [UIColor clearColor];
titleForTable.textColor = [UIColor whiteColor];
titleForTable.shadowColor = [UIColor whiteColor];
[headerView addSubview:titleForTable];
[titleForTable release];
UIButton *phoneButton = [[UIButton alloc] initWithFrame:btnFrame];
phoneButton.alpha = 0.7;
phoneButton.tag = section;
[phoneButton setImage:[UIImage imageNamed:#"Yellow.png"] forState: UIControlStateNormal];
[phoneButton addTarget: self action: #selector(headerTapped:) forControlEvents: UIControlEventTouchUpInside];
[headerView addSubview: phoneButton];
[phoneButton release];
return headerView;
}
#pragma mark -
#pragma mark UITextField Delegate
- (void)textFieldDidBeginEditing:(UITextField *)textField {
self.currentTextField = textField;
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
[textField resignFirstResponder];
return YES;
}
//textfield charecters range
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
if (textField.text.length >= MAX_LENGTH && range.length == 0){
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Warning" message:#"You reached maximum limit - 20"
delegate:self
cancelButtonTitle:#"Ok"
otherButtonTitles:nil];
[alert show];
[alert release];
return NO; // return NO to not change text
}
else {
return YES;
}
}
#pragma mark -
- (void)deleteButtonTapped:(id)sender{
if([self.currentTextField isFirstResponder]) {
[self.currentTextField resignFirstResponder];
}
NSLog(#"Button Pressed");
UIButton *btnDelete = (UIButton*)sender;
id cell = [[btnDelete superview] superview];
if([cell isKindOfClass:[PhoneFieldCell class]]) {
cell = (PhoneFieldCell*)cell;
}
if([cell isKindOfClass:[EmailFieldCell class]]) {
cell = (EmailFieldCell*)cell;
}
if([cell isKindOfClass:[OtherDetailsCell class]]) {
cell = (OtherDetailsCell*)cell;
}
NSIndexPath *indexPath = [aTable indexPathForCell:cell];
NSLog(#"Section is %d and row is %d",indexPath.section,indexPath.row);
switch (indexPath.section) {
case 1:
[self.phoneList removeObjectAtIndex:[btnDelete tag]];
[aTable deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationLeft];
break;
case 2:
[self.emailList removeObjectAtIndex:[btnDelete tag]];
[aTable deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationLeft];
break;
case 3:
[self.otherDetailsList removeObjectAtIndex:[btnDelete tag]];
[aTable deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationLeft];
break;
default:
break;
}
[aTable reloadData];
}
- (void)changeButtonTapped:(id)sender{
if([self.currentTextField isFirstResponder]) {
[self.currentTextField resignFirstResponder];
}
UIButton *btnDelete = (UIButton*)sender;
id cell = (PhoneFieldCell*)[[btnDelete superview] superview];
if([cell isKindOfClass:[PhoneFieldCell class]]) {
cell = (PhoneFieldCell*)cell;
}
if([cell isKindOfClass:[EmailFieldCell class]]) {
cell = (EmailFieldCell*)cell;
}
if([cell isKindOfClass:[OtherDetailsCell class]]) {
cell = (OtherDetailsCell*)cell;
}
self.selectedIndexPath = [aTable indexPathForCell:cell];
shouldModify = YES;
NSLog(#"Section is %d and row is %d",self.selectedIndexPath.section,self.selectedIndexPath.row);
SBTableAlert *alert = nil;
alert = [[[SBTableAlert alloc] initWithTitle:#"Options" cancelButtonTitle:#"Cancel" messageFormat:#"Select your option!"] autorelease];
[alert setType:SBTableAlertTypeSingleSelect];
[alert.view addButtonWithTitle:#"OK"];
[alert setDelegate:self];
[alert setDataSource:self];
[alert show];
}
- (void)headerTapped:(id)sender {
if([self.currentTextField isFirstResponder]) {
[self.currentTextField resignFirstResponder];
}
UIButton *tappedButton = (UIButton*)sender;
//set current selection according to section
switch ([tappedButton tag]) {
case 1://Phone
self.currentSelectionType = SELECTIONTYPE_PHONE;
break;
case 2://Email
self.currentSelectionType = SELECTIONTYPE_EMAIL;
break;
case 3://Other details
self.currentSelectionType = SELECTIONTYPE_OTHER;
break;
default:
break;
}
SBTableAlert *alert;
alert = [[[SBTableAlert alloc] initWithTitle:#"Options" cancelButtonTitle:#"Cancel" messageFormat:#"Select your option!"] autorelease];
[alert setType:SBTableAlertTypeSingleSelect];
[alert.view addButtonWithTitle:#"OK"];
[alert setDelegate:self];
[alert setDataSource:self];
[alert show];
}
#pragma mark - SBTableAlertDataSource
- (UITableViewCell *)tableAlert:(SBTableAlert *)tableAlert cellForRow:(NSInteger)row {
UITableViewCell *cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:nil] autorelease];
[cell.textLabel setText:[self.choiceList objectAtIndex:row]];
if(row == selectedIndex)
cell.accessoryType = UITableViewCellAccessoryCheckmark;
else {
cell.accessoryType == UITableViewCellAccessoryNone;
}
return cell;
}
- (NSInteger)numberOfRowsInTableAlert:(SBTableAlert *)tableAlert {
if (tableAlert.type == SBTableAlertTypeSingleSelect)
return [self.choiceList count];
else
return 4;
}
#pragma mark - SBTableAlertDelegate
- (void)tableAlert:(SBTableAlert *)tableAlert didSelectRow:(NSInteger)row {
if (tableAlert.type == SBTableAlertTypeMultipleSelct) {
UITableViewCell *cell = [tableAlert.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:row inSection:0]];
if (cell.accessoryType == UITableViewCellAccessoryNone)
[cell setAccessoryType:UITableViewCellAccessoryCheckmark];
else
[cell setAccessoryType:UITableViewCellAccessoryNone];
[tableAlert.tableView deselectRowAtIndexPath:[NSIndexPath indexPathForRow:row inSection:0] animated:YES];
}
else if (tableAlert.type == SBTableAlertTypeSingleSelect) {
selectedIndex = row;
[tableAlert.tableView reloadData];
[tableAlert.tableView deselectRowAtIndexPath:[NSIndexPath indexPathForRow:row inSection:0] animated:YES];
}
}
- (void)tableAlert:(SBTableAlert *)tableAlert didDismissWithButtonIndex:(NSInteger)buttonIndex {
if(buttonIndex == 1){
if(selectedIndex == -1){
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Select at least one choice" message:nil
delegate:nil
cancelButtonTitle:#"Ok"
otherButtonTitles:nil];
[alert show];
[alert release];
}
else if(cellSelected == FALSE){
if(selectedIndex == 3){
UIAlertView *customAlert = [[UIAlertView alloc] initWithTitle:#"Enter Custom Message" message:#"\n\n"
delegate:self
cancelButtonTitle:#"Cancel"
otherButtonTitles:#"Ok",nil];
customAlert.tag = 99;
CGAffineTransform myTransForm = CGAffineTransformMakeTranslation(0,0);
UITextField *temp = [[UITextField alloc] initWithFrame:CGRectMake(15, 50, 255, 30)];
self.customText = temp;
[temp release];
self.customText.backgroundColor = [UIColor whiteColor];
self.customText.placeholder = #"Enter Custom Text";
self.customText.clearButtonMode = UITextFieldViewModeWhileEditing;
self.customText.layer.cornerRadius = 5;
[customAlert addSubview:self.customText];
[customAlert setTransform:myTransForm];
[customAlert show];
[customAlert release];
}else {
UITableViewCell *cell = [tableAlert.tableView cellForRowAtIndexPath:[ NSIndexPath indexPathForRow:selectedIndex inSection:0]];
NSString *val = cell.textLabel.text;
if(!shouldModify) {
switch (self.currentSelectionType) {
case SELECTIONTYPE_PHONE:
[phoneList addObject:val];
break;
case SELECTIONTYPE_EMAIL:
[emailList addObject:val];
break;
case SELECTIONTYPE_OTHER:
[otherDetailsList addObject:val];
break;
default:
break;
}
}
else {
switch (self.selectedIndexPath.section) {
case 1:
[phoneList replaceObjectAtIndex:self.selectedIndexPath.row withObject:val];
break;
case 2:
[emailList replaceObjectAtIndex:self.selectedIndexPath.row withObject:val];
break;
case 3:
[otherDetailsList replaceObjectAtIndex:self.selectedIndexPath.row withObject:val];
break;
default:
break;
}
shouldModify = NO;
}
}
}
if(self.currentSelectionType != SELECTIONTYPE_UNKNOWN || self.selectedIndexPath.section > 0)
[aTable reloadData];
selectedIndex = -1;
[tableAlert release];
}
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
if(alertView.tag == 99 && buttonIndex == 1){
NSString *val = [self.customText text];
if(!val || [[val stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] isEqualToString:#""]){
//show error alert here and return from here
UIAlertView *errorAlert = [[UIAlertView alloc] initWithTitle:#"Error"
message:#"Please fill a value for custom text"
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[errorAlert show];
[errorAlert release];
return;
}
switch (self.currentSelectionType) {
case SELECTIONTYPE_PHONE:
[phoneList addObject:val];
[aTable reloadData];
break;
case SELECTIONTYPE_EMAIL:
[emailList addObject:val];
[aTable reloadData];
break;
case SELECTIONTYPE_OTHER:
[otherDetailsList addObject:val];
[aTable reloadData];
break;
default:
break;
}
}
}
#pragma mark -
/*
// Override to allow orientations other than the default portrait orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
*/
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
- (void)viewDidUnload {
self.currentTextField = nil;
self.choiceList = nil;
self.labelHeaders = nil;
self.selectedIndexPath = nil;
self.aTable = nil;
self.customText = nil;
self.phoneList = nil;
self.emailList = nil;
self.otherDetailsList = nil;
self.customText = nil;
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)dealloc {
[phoneList release];
[emailList release];
[otherDetailsList release];
[customText release];
[customText release];
[aTable release];
[selectedIndexPath release];
[choiceList release];
[labelHeaders release];
[currentTextField release];
[super dealloc];
}
#end
here is your answer http://www.icodeblog.com/2011/01/04/elctextfieldcell-a-useful-tableviewcell-for-forms/
u can also manually do some customization according to your app need
- (void)tableView:(UITableView *)tableView didEndEditingRowAtIndexPath:(NSIndexPath *)indexPath{
[tableView reloadData];
}

Resources