Removing badge subview from UIBarButtonItem - iphone

I am adding a badge to a UIBarButtonItem... which works fine. But I cannot remove it. Any help is appreciated.
Thanks.
Code:
MKNumberBadgeView *badge = [[MKNumberBadgeView alloc] initWithFrame:CGRectMake(45, -10, 30,30)];
badge.value = #"!";
badge.layer.cornerRadius = 10;
badge.layer.masksToBounds = YES;
badge.tag = 42;
if ([self.chatCount isEqualToString:#"1"]) {
[chatButton addSubview:badge];
} else {
for (UIView *view in [self.view subviews] ) { if (view.tag == 42 ) { [view removeFromSuperview]; } }
[badge release];
}
UIBarButtonItem *chat = [[UIBarButtonItem alloc] initWithCustomView:chatButton];
self.navigationItem.rightBarButtonItem = chat;
[chat release];

You're adding your badge as a subview to chatButton not self.view. Your for loop is iterating over self.view.subviews and badge is not a subview of self.view but a subview of chatbutton. You will either have to iterate over chatButton.subviews or create a recursive method that iterates over all subviews. Alternatively, you can use viewWithTag which I think searches the entire hierarchy.
I would just hold an instance variable to badge and call [self.badge removeFromSuperview] or self.badge.hidden = YES;

Related

UILongPressGestureRecognizer not removing view

I'm not seeing what's wrong here. When user taps and hold, I add a view, when touch finishes the view gets removed. This does NOT work and I do see the UIGestureRecognizerStateEnded being sent.
However, if I call [tmpView removeFromSuperview]; outside of that state it gets removed without any issues.
Any idea what's causing this?
-(void)longTapped:(UILongPressGestureRecognizer*)recognizer {
UIView *tmpView = [[UIView alloc] init];
tmpView.backgroundColor = [UIColor greenColor];
// Position the menu so it fits properly
tmpView.frame = CGRectMake(0, 100, 320, 250);
// Add the menu to our view and remove when touches have ended
if (recognizer.state == UIGestureRecognizerStateBegan) {
[self.view addSubview:tmpView];
}
else if(recognizer.state == UIGestureRecognizerStateEnded){
[tmpView removeFromSuperview];
}
}
The second time your -longTapped: method is called it is instantiating a new instance of UIView in the tmpView variable, and trying to remove that from its superview. You need to store a reference to your added view on the controller when the long press starts, and when it ends you need to remove that object from its superview.
#interface myVC ()
#property (nonatomic, weak) UIView *tmpView;
#end
-(void)longTapped:(UILongPressGestureRecognizer*)recognizer {
if (recognizer.state == UIGestureRecognizerStateBegan) {
// Add the menu to our view and remove when touches have ended
self.tmpView = [[UIView alloc] init];
self.tmpView.backgroundColor = [UIColor greenColor];
// Position the menu so it fits properly
self.tmpView.frame = CGRectMake(0, 100, 320, 250);
[self.view addSubview:self.tmpView];
}
else if(recognizer.state == UIGestureRecognizerStateEnded){
[self.tmpView removeFromSuperview];
self.tmpView = nil;
}
}

How to fix border in UITableView for the UITableViewStyleGrouped

For a UITableViewStyleGrouped UITableView a small extra line is drawn below the tableview
How do I fix this?
I have tried my best. No luck so far.
Thank's in advance.
My Code
-(void)myTableView
{
// if(mytableView != nil)
// [mytableView release];
if (mytableView == nil) {
mytableView = [[UITableView alloc]initWithFrame:myFrame style:UITableViewStyleGrouped];
}
mytableView.delegate=self;
mytableView.dataSource=self;
mytableView.backgroundView=nil;
mytableView.scrollEnabled = FALSE;
[self.view addSubview:mytableView];
[self myPortraitMode];
}
Background of the table is fixed is an image.
I think what you are referring to is the Bevel color of the table view.
The answer is in this post.
Basically, you need to set the table separatorStyle to UITableViewCellSeparatorStyleNone or to UITableViewCellSeparatorStyleSingleLine.
You need to set a background view:
UIView *backgroundView = [[UIView alloc] init];
backgroundView.backgroundColor = [UIColor yourColor];
tableview.backgroundView = backgroundView;
[backgroundView release];
You don't need to set the properties every time.
-(void)myTableView
{
if (mytableView == nil) {
mytableView = [[UITableView alloc]initWithFrame:myFrame style:UITableViewStyleGrouped];
mytableView.delegate=self;
mytableView.dataSource=self;
mytableView.backgroundView=nil;
mytableView.scrollEnabled = NO;
[self.view addSubview:mytableView];
[self myPortraitMode];
}
}
I don't really see what the problem is though.

need an advice with orientation change iphone

my problem might be simple to some of you but i can't find a solution. I have a method where a create my views automatically (text fields, labels and text views). It's like a registration form. The problem is that when i change the screen to landscape mode, i want to change the views width. To do that i used [self.view removeFromSuperview] and created the views again. The problem is that the views won't get recreated with the landscape width. I can't use IB to autosize the views at orientation change. The views are created in viewDidLoad and removed and recreated in - (void) adjustViewsForOrientation:(UIInterfaceOrientation)orientation {} I don't know why they don't get recreated after being removed. If there was another solution that you could share with me i would appreciate it.
Here's how i create the views:
-(void)createViews:(int)width
{
for(int i = 0; i < numberOfTextfields; i++) {
textfieldPadding = textfieldPadding+40;//set some space between the text fields
labelPadding = labelPadding+40;//set some space between the labels
UITextField *field = [[UITextField alloc] initWithFrame:
CGRectMake(10,i*textfieldHeight+textfieldPadding+firstTextfieldHeight+10,width, textfieldHeight)];
field.autoresizingMask = UIViewAutoresizingFlexibleWidth;
//field.backgroundColor= [UIColor cyanColor];
field.placeholder = [labels objectAtIndex:i];
field.borderStyle=UITextBorderStyleRoundedRect;
field.returnKeyType = UIReturnKeyDone;
[field addTarget:self action:#selector(doneButton:)
forControlEvents:UIControlEventEditingDidEndOnExit];
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(10, i*labelHeight+firstLabelHeight+labelPadding-20, width, labelHeight)];
label.text = [labels objectAtIndex:i];
//label.backgroundColor = [UIColor brownColor];
[scrollView addSubview:field];
[scrollView addSubview:label];
[textfields addObject:field];
[labels addObject:label];
[field release];
[label release];
}
}
Here's where i wanted to remove them and recreate them:
- (void) adjustViewsForOrientation:(UIInterfaceOrientation)orientation
{
if (orientation == UIInterfaceOrientationLandscapeLeft || orientation == UIInterfaceOrientationLandscapeRight)
{
[self.view removeFromSuperview];
[self createViews:landscapeWidth];
}
else if(orientation == UIInterfaceOrientationPortrait || orientation == UIInterfaceOrientationPortraitUpsideDown)
{
[self.view removeFromSuperview];
[self createViews:portraitWidth];
}
}
Thanks in advance!
Instead of removing, resizing and then re-adding as you currently are why not just set the appropriate autoresizingMask (link) when you create the view initially?
UITextField *myTextField = [[UITextField alloc] initWithFrame:someRect];
// the following will automatically resize the width on orientation change
myTextField.autoresizingMask = UIViewAutoresizingFlexibleWidth;
[myView addSubview:myTextField];
[myTextField release];

Custom UITableViewCell won't redraw on setNeedsDisplay

I created a custom UITableViewCell class with a UIButton, a UIImage, and two UILabels. The button and the image are overlayed on top of each other, and only one is displayed at a time. The expected behavior is you touch on the button, the button disappears, and it displays the image. The UITableViewCells are set to be reused. Here's my code:
Constructor:
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
unheartButton = [[UIButton buttonWithType:UIButtonTypeCustom] retain];
unheartButton.backgroundColor = [UIColor clearColor];
unheartButton.frame = CGRectMake(10, 13, 20, 18);
[unheartButton addTarget:self action:#selector(onButtonClick:) forControlEvents:UIControlEventTouchUpInside];
[unheartButton setBackgroundImage:[UIImage imageNamed:#"redheart.png"] forState:UIControlStateNormal];
imageView = [[UIImageView alloc] init];
imageView.frame = CGRectMake(12, 13, 16, 16);
NSMutableArray *array = [[NSMutableArray alloc] init];
for (int ndx = 1; ndx < 13; ndx++) {
[array addObject:[UIImage imageNamed:[NSString stringWithFormat:#"icon-loading-%d (dragged).tiff", ndx]]];
}
imageView.animationImages = array;
imageView.animationDuration = 1;
[array release];
[self.contentView addSubview:imageView];
[self.contentView addSubview:unheartButton];
return self;
}
}
- (void) setModel:(MyModel *)myModel {
model = myModel;
if (model.hideImage) {
imageView.hidden = YES;
unheartButton.hidden = NO;
else {
imageView.hidden = NO;
unheartButton.hidden = YES;
}
}
Button click:
- (IBAction) onButtonClick: (id) sender {
model.hideImage = NO;
unheartButton.hidden = YES;
imageView.hidden = NO;
[imageView startAnimating];
[self setNeedsDisplay];
[self.contentView setNeedsDisplay];
[self.unheartButton setNeedsDisplay];
[self.imageView setNeedsDisplay];
}
I'm calling setNeedsDisplay on everything, but nothing seems to happen. If I scroll off the screen and back up, the button is hidden and now the loading icon is shown, but this only happens after a scroll. I'm not sure what I need to do to get the cell to repaint.
The UITableView does some fancy caching to support scrolling and the like; I've had similar issues with refreshing a specific cell when I use custom views.
You can use reloadRowsAtIndexPaths:withRowAnimation: to make the table reload just that row. See this post for more information: Why won't my UITableViewCell deselect and update its text?

How to change image and disable UIBarButtonItem

I have a NavigationBar app with two views: a parent and a sub view. In the sub view I'm adding a button to the right corner as follows:
- (void)viewDidLoad {
UIBarButtonItem *tempButton = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:#"lock-unlocked.png"] style:UIBarButtonItemStylePlain target:self action:#selector(lockScreen)];
self.navigationItem.rightBarButtonItem = tempButton;
[tempButton release];
}
When that button is clicked I want to change the image of this rightBarButtonItem and disable the leftBarButtonItem (which was added automatically by the controller). Basically have two states of a button, locked and unlocked.
Question 1:
The only way I can find how to change the image is to create a new UIButtonItem with a new image and replace rightBarButtonItem with that new one. But I'm wondering if there's a way to just change the image without creating a new UIBarButtonItem. Am I creating a memory leak if I keep creating new UIBarButtonItem?
Question 2:
How can I get a hold of self.navigationItem.leftBarButtonItem and disable/enable it? I don't create that one manually, it's created automatically for me by the controller. I don't see any method/property on UIBarButtonItem to enable/disable user interaction with it.
Question 1: Declare UIBarButtonItem *tempButton in the interface
#interface MyAppDelegate : NSObject <UIApplicationDelegate> {
UIBarButtonItem *tempButton;
}
#property (nonatomic, retain) UIBarButtonItem *tempButton;
and synthesize it in the implementation.
#synthesize tempButton;
Create the object in viewDidLoad similiar to how you are now.
- (void)viewDidLoad {
tempButtom = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:#"lock-unlocked.png"] style:UIBarButtonItemStylePlain target:self action:#selector(lockScreen)];
self.navigationItem.rightBarButtonItem = tempButton;
}
But don't release it here, release it in the dealloc method normally found at the bottom.
Then when lockScreen is called do
tempButton.image = [UIImage imageNamed:#"myImage.png"]
I don't have an answer for question 2, im afraid!
In regard to question 2, use the 'enabled' property:
self.navigationItem.leftBarButtonItem.enabled = NO;
I can't understand if you have a navigationController, but in this case to disable the back button you need to call:
self.navigationItem.hidesBackButton = YES;
Shouldn't the above have release the UILabel *l after the [self.window addSubView:l] call? That way it gets retained +1 when added to the Subview, but released -1 in the same branch. Otherwise, you must call disableLeftBarButtonItemOnNavbar:NO to release it. And while, you'll end up in the same place in the end, you aren't leaking, I think the static analysis tools they've built into XCode wouldn't like that being in a separate branch. Small detail :-)
- (void) disableLeftBarButtonItemOnNavbar:(BOOL)disable
{
static UILabel *l = nil;
if (disable) {
if (l != nil)
return;
l = [[UILabel alloc] initWithFrame:CGRectMake(0, 20, 160, 44)];
l.backgroundColor = [UIColor clearColor];
l.userInteractionEnabled = YES;
[self.window addSubview:l];
[l release];
}
else {
if (l == nil)
return;
[l removeFromSuperview];
l = nil;
}
}
I was not able to disable/grey out a NavBar button with:
self.navigationItem.leftBarButtonItem.enabled = NO;
...but hiding the back button works well!
self.navigationItem.hidesBackButton = YES;
Thanks Dzamir!
Using "hidesBackButton=YES" is really not an elegant solution, cause it HIDES the button which is not what we want. An acceptable work-around would be adding a UILabel to the window just over the back button at least disabling the touches on the button.
Add this method to your AppDelegate class:
- (void) disableLeftBarButtonItemOnNavbar:(BOOL)disable
{
static UILabel *l = nil;
if (disable) {
if (l != nil)
return;
l = [[UILabel alloc] initWithFrame:CGRectMake(0, 20, 160, 44)];
l.backgroundColor = [UIColor clearColor];
l.userInteractionEnabled = YES;
[self.window addSubview:l];
}
else {
if (l == nil)
return;
[l removeFromSuperview];
[l release];
l = nil;
}
}
You can call it like this from any view controller to disable:
MyAppDelegate *appDeleg = (MyAppDelegate *) [[UIApplication sharedApplication] delegate];
[appDeleg disableLeftBarButtonItemOnNavbar:YES];
To enable:
MyAppDelegate *appDeleg = (MyAppDelegate *) [[UIApplication sharedApplication] delegate];
[appDeleg disableLeftBarButtonItemOnNavbar:NO];
I think this code helps you,
UIButton *m_objbtnFlip= [[UIButton alloc] initWithFrame:CGRectMake(0,0,89, 37)];
[m_objbtnFlip setBackgroundImage:[UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"btn_purchased"
ofType:IMAGETYPE]]
forState:UIControlStateNormal];
[m_objbtnFlip setBackgroundImage:[UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"btn_allavailable"
ofType:IMAGETYPE]]
forState:UIControlStateSelected];
[m_objbtnFlip addTarget:self action:#selector(flipViews) forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem *objBarButtonItemRight = [[UIBarButtonItem alloc] initWithCustomView:m_objbtnFlip];
self.navigationItem.rightBarButtonItem=objBarButtonItemRight;
[objBarButtonItemRight release];
objBarButtonItemRight = nil;
And write action here,
-(void)flipViews {
// put action code here
}