Sorting items In NSDictionary - nsdictionary

I am reading the items from plist into dictionary, i am using keys of dictionary to set title and value as tag to the buttons. now i have to sort the items in the dictionary, i don't want to put sorted items into array, as i am using dictionary to set title and tag for the button. I checked the links but most of them are putting sorted items into array. How can i do it with out using array , and instead use same dictionary.
here is code snippet.
while (key = [keyEnumerator nextObject])
{
UIButton *btnWith = [UIButton buttonWithType:UIButtonTypeRoundedRect];
btnWith.tag = [[topics objectForKey:key] integerValue] ;
[btnWith setTitle:key forState:UIControlStateNormal];
btnWith.titleLabel.font = [UIFont fontWithName:#"Aller-Light" size:15];
[btnWith setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
btnWith.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
[btnWith setBackgroundImage:[UIImage imageNamed:#"unchecked.png"] forState:UIControlStateNormal];
[btnWith addTarget:self action:#selector(CheckboxClicked:) forControlEvents:UIControlEventTouchUpInside];
[self.scrollview setContentSize: CGSizeMake(320, topics.count *50)];
}

The order of a dictionary's entries is not defined. You have to sort the keys (e.g. with any of the sortXXX methods) and save them in a collection which is ordered (e.g. an array).
Then use this collection to access the dictionary entries in your desired order.

Related

Creating UIButtons dynamically - Logic Error

I have a NSMutableArray, and i have saving some string values in it. The size of the NSMutableArray could vary from 2-5 (Meaning it might have 2 -5 string values stored in it).
Depending on the count of the NSMutableArray i need to initialize UIBUttons and then set the value of the String stored init to the buttons title.
int numberOfButtonsToBeInitialize= [mutableArr count];// we are finding the number of buttons to be initialize and we assign it to a variable.
Now i need to create buttons (what ever the number returned by numberOfButtonsToBeInitialize)
How can i do this ?
for(int i=0;i<numberOfButtonsToBeInitialize;i++){
//init the button
UIButton *bout = [UIButton buttonWithType:UIButtonTypeRoundedRect];
//set the title
[bout setTitle:[mutableArr objectAtIndex:i] forState:UIControlStateNormal];
[bout addTarget:self action:#selector(event:) forControlEvents: UIControlEventTouchUpInside];
[self.view addSubview:bout ];
//then you can set the position of your button
[bout setFrame:CGRectMake(70,3, 40,40)];}
Try this:
NSMutableArray *myButtonsArray = [[NSMutableArray alloc] initWithCapacity:0];
UIButton *tmpButton;
for (NSString *bTitle in mutableArr)
{
tmpButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[tmpButton setTitle:bTitle forState:UIControlStateNormal];
// Any additional setup goes here
[myButtonsArray addObject:tmpButton];
}
Now you have an array with all the buttons. You can just iterate this array and add any button as a subview in your main view.
You need a for loop. For example:
float buttonWidth=50;
float margin=5;
for (int index=0; index<numberOfButtonsToBeInitialize;index++)
{
UIButton* button=[UIButton buttonWithType:UIButtonTypeRoundedRect];
NSString* buttonTitle=[mutablearr objectAtIndex:index];
[button setTitle:buttonTitle forState:UIControlStateNormal];
[button setFrame:CGRectMake(0+(buttonWidth+margin)*index, 0, buttonWidth, 30)];
[button setTag:100+index];
[button addTarget:self action:#selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:button];
}
In this case we layout buttons in a row(horizontally). Adjust to your own preferences

Create toolbar for quiz app

This is related to a question i posted earlier.I am still stuck on it.Heres a description.I am creating a quiz app.It has a toolbar whose buttons are to be created dynamicaly each time the user clicks a button.I did it using a method which adds three buttons into an arrray, then uses a for loop to check the number of choices the question has and then create and add a button to the array for each choice.Later i use
[toolbar setitems:tempArray];
to add the buttons
But while doing this i am running into memory leaks.The app crashes after 200 questions.I found using instruments that the leaks were in button creation area.But after doing many experiments im at a loss about what to do.
I also have another question
Is there a way to find out the retain count of objects created by built in methods in iphone sdk.Specificaly,
1)Does NSMutableArray's addobject method increase the retain count of the added object
2)Is [[toolbar items] release] likely to cause trouble if i am intending to release the customBarButtonItem objects stored in it?
because wile playing with these options , the app either crashes immediately or the changes have no effect on the reported leaks
heres the code.Its got a lot of comment lines which are options i tried
- (void)CreateButtons{
UIToolbar *tempToolBar=[[UIToolbar alloc] ]
numberOfChoices=0;//set number of choice buttons at present to 0
NSMutableArray *tempItems=[[NSMutableArray alloc] init];//Array for holding the buttons
Question *question=[currentQuestion question];
NSString *answer=[question answerOptions];
int numericAnswer=0;
numericAnswer=[answer characterAtIndex:0];
//see if its a number or a character
if (numericAnswer > 96) { // its a character
int choice;
for (choice=97; choice <=numericAnswer ; choice ++) {
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button setBackgroundImage:[UIImage imageNamed:#"gembtnblu.png"] forState:UIControlStateNormal];
button.frame = CGRectMake(0, 0, TOOLBAR_BUTTON_WIDTH , TOOLBAR_BUTTON_HEIGHT);
[button setTitle:[NSString stringWithFormat:#"%c",(char)choice] forState:UIControlStateNormal];
[button setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
[button addTarget:self action:#selector(ChoiceButtonTouched:) forControlEvents:UIControlEventTouchUpInside];
[button setTag:choice];
UIBarButtonItem *customBarItem = [[UIBarButtonItem alloc] initWithCustomView:button];
if (isReviewing == TRUE) {
customBarItem.customView.userInteractionEnabled=FALSE;
}
//Add button to the array
[tempItems addObject:customBarItem];
//release buttons
[customBarItem release];
numberOfChoices++;
}
}
else {
int choice;
for (choice=49; choice<=numericAnswer; choice ++) {
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button setBackgroundImage:[UIImage imageNamed:#"gembtnblu.png"] forState:UIControlStateNormal];
button.frame = CGRectMake(0, 0, TOOLBAR_BUTTON_WIDTH , TOOLBAR_BUTTON_HEIGHT);
[button setTitle:[NSString stringWithFormat:#"%c",choice] forState:UIControlStateNormal];
[button setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
[button addTarget:self action:#selector(ChoiceButtonTouched:) forControlEvents:UIControlEventTouchUpInside];
[button setTag:choice];
UIBarButtonItem *customBarItem = [[UIBarButtonItem alloc] initWithCustomView:button];
//Add button to the array
[tempItems addObject:customBarItem];
if (isReviewing == TRUE) {
customBarItem.customView.userInteractionEnabled=FALSE;
}
//release buttons
[customBarItem release];
numberOfChoices++;
}
}
//load the image
UIButton *previousButton = [UIButton buttonWithType:UIButtonTypeCustom];
[previousButton setBackgroundImage:[UIImage imageNamed:#"prev.png"] forState:UIControlStateNormal];
[previousButton addTarget:self action:#selector(PreviousClicked:) forControlEvents:UIControlEventTouchUpInside];
previousButton.frame = CGRectMake(0, 0, TOOLBAR_BUTTON_WIDTH , TOOLBAR_BUTTON_HEIGHT);
UIBarButtonItem *customBarItem6 = [[UIBarButtonItem alloc] initWithCustomView:previousButton];
//[previousButton release];
self.prevButton=customBarItem6;
UIButton *nextButton= [UIButton buttonWithType:UIButtonTypeCustom];
[nextButton setBackgroundImage:[UIImage imageNamed:#"nex.png"] forState:UIControlStateNormal];
[nextButton addTarget:self action:#selector(nextClicked:) forControlEvents:UIControlEventTouchUpInside];
nextButton.frame = CGRectMake(0, 0, TOOLBAR_BUTTON_WIDTH, TOOLBAR_BUTTON_HEIGHT);
UIBarButtonItem *customBarItem7 = [[UIBarButtonItem alloc] initWithCustomView:nextButton];
//[nextButton release];
//Use this to put space in between your toolbox buttons
UIBarButtonItem *flexItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
[tempItems addObject:flexItem];
[tempItems addObject:customBarItem6];
[tempItems addObject:customBarItem7];
//release buttons
[customBarItem6 release];
[customBarItem7 release];
[flexItem release];
//NSArray *items=[[NSArray alloc] initWithArray:(NSArray *)tempItems];
//[tempItems release];
//add array of buttons to toolbar
//if([[toolbar items] count]>0)
// {
// [[toolbar items] release];
// }
[toolbar setItems:tempItems animated:YES];
//[items release];
//[self.view addSubview:toolbar];
if(isReviewing == FALSE && isPractice == FALSE) {
prevButton.enabled=FALSE;
}
//[toolbar bringSubviewToFront:customBarItem6.customView];
}
toolbar is created via ib
Yeah its a lot of code but it just creates buttons based on number of choices for a question.The two for loops are similar exept one puts a,b,c,d on the buttons while the other one puts 1,2,3,4.....In addition three buttons are created.One for next, previous and a flex item .This method is is called each time the user clicks teh next button.
I can see a few things which are not very efficient memory-wise:
You use lots of convenience initializers: buttonWithType and 'imageNamed`. These will autorelease themselves at some point in the future but not within your method.
The item tempToolbar is allocated but never released. This will leak.
Your mutable array tempItems also does not appear to be released: this will kill you completely since all your buttons are added to it...
Based on this I would suggest:
Use of alloc/init methods instead of convenience constructors
Alternatively: create an NSAutoReleasePool at the start of your method and drain it at the end: this will release all autoreleased entities.
Good luck
Difficult to follow all that code, but an easy part-answer to 1) is that, yes, [NSMutableArray addObject:] increase retain +1.

Can I add OBject of button to NSMutableArray?

I am trying to create number of buttons on view programatically and for that I need array, so can I add button object in NSMutableArray?
Yes you can do that see the following code
// Create buttons for the sliding menu. For simplicity I create 5 standard buttons.
NSMutableArray *buttonArray = [[NSMutableArray alloc] init];
for(NSInteger i = 0; i < [self.slideMenuArray count]; i++)
{
// Rounded rect is nice
UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
NSString *title=[slideMenuArray objectAtIndex:i];
[btn setFrame:CGRectMake(0.0f, 4.0f, 90.0f, 20.0f)];
[btn setTitle:[NSString stringWithString:title] forState:UIControlStateNormal];
[btn setBackgroundColor:[UIColor clearColor]];
[btn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
[[btn titleLabel] setFont:[UIFont systemFontOfSize:12]];
[btn addTarget:self action:#selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside];
UIImage *backgroundView;
if(i==0)
backgroundView= [UIImage imageNamed:#"btnclk.png"];
else
backgroundView= [UIImage imageNamed:#"btn.png"];
[btn setBackgroundImage:backgroundView forState:UIControlStateNormal];
[buttonArray addObject:btn];
}
You can retrieve the added button objects like this-
for(int i = 0; i < [buttonArray count]; i++)
{
UIButton *btn = [buttonArray objectAtIndex:i];
// Move the buttons position in the x-demension (horizontal).
CGRect btnRect = btn.frame;
btnRect.origin.x = totalButtonWidth;
[btn setFrame:btnRect];
}
sure you can, and remember that when you do, every button or other object will be retained bu the array and released when you remove it from the array...
Yes, NSMutableArray can hold any objects

section header in uitableview - reusidentifier?

I have a table with customized headers for the sections. In addition to that, I implemented a collapsing feature, so that when a header is touched, all non-adressed sections are reduced, and the adressed section is expanded.
I realized that by using UIButtons as background views. Furthermore, the buttons have different colors and text, depending on their state (expanded vs not expanded).
I have a problem, similar to that reusidentifier problem, i.e. if u dont reuse cells already allocated in a table, certain fragments appear, if u start to scroll. Here it only happens to my first section, nevertheless it appears fragmented and duplicated....
Is there anything similar to reusing headerviews already allocated once like the method reusIdentifier for UITableViewCells?
Or is there a better approach?
Allocating the Buttons in advance to store them in array didnt do the trick for me...
Here's some code:
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, self.tableView.frame.size.width, 40)];
[button setShowsTouchWhenHighlighted:NO];
[button setTitleShadowColor:[UIColor clearColor] forState:UIControlStateNormal];
[button addTarget:self action:#selector(collapse:) forControlEvents:UIControlEventTouchUpInside];
button.tag = section;
[button setAdjustsImageWhenHighlighted:NO];
button.backgroundColor = [UIColor colorWithRed:63.0f/255.0f green:154/255.0f blue:201/255.0f alpha:1.0f];
[button.titleLabel setFont:[UIFont fontWithName:#"Helvetica" size:14.0]];
[button setContentHorizontalAlignment:UIControlContentHorizontalAlignmentLeft];
[button setContentVerticalAlignment:UIControlContentVerticalAlignmentCenter];
if (section == 0) {
// [button setBackgroundImage:[UIImage imageNamed:#""] forState:UIControlStateNormal];
[button setTitle:#" Newsroom" forState:UIControlStateNormal];
} else {
[button setTitle:[NSString stringWithFormat:#" Sektion %d", section] forState:UIControlStateNormal];
}
if (section == mySection) {
[button setBackgroundImage:[UIImage imageNamed:#"sectionHeader_active.png"] forState:UIControlStateNormal];
[button setBackgroundImage:[UIImage imageNamed:#"sectionHeader_active.png"] forState:UIControlEventTouchUpInside];
[button.titleLabel setTextColor:[UIColor whiteColor]];
} else {
[button setBackgroundImage:[UIImage imageNamed:#"sectionHeader_inactive.png"] forState:UIControlStateNormal];
[button setBackgroundImage:[UIImage imageNamed:#"sectionHeader_inactive.png"] forState:UIControlEventTouchUpInside];
[button.titleLabel setTextColor:[UIColor colorWithRed:96.0f/255.0f green:96/255.0f blue:97/255.0f alpha:1.0f]];
}
return [button autorelease];
}
I also implemented a collapsing section table using UIButton header views. What I found was that it was folly trying to cache and resuse the views, because you don't know when the UITableView is done with them (I got crashes).
I recommend implementing your state change by: updating your data model; performing all the row insert/deletes to perform the collapses/expand; then doing a [tableView reloadData], which will call viewForHeaderInSection, where you use the state of your data model to return the appropriately formatted uibutton view.

how to add a ui button that calls a number from an array and displays the phone number as the button title

anotherViewController.myLabel = [NSString stringWithFormat:#"Telephone %#",
anotherViewController.title];
this is the declaration for a previus label however im not sure how to do this for a button...
the data array is located made in this format
phoneNumbers = [[NSArray alloc] initWithObjects:#"6940313388", #"4045434218", nil ];
self.phoneNumbers =phoneNumbers;
and then the labels are simply added by
theLabel.text = myLabel;
where mylabel is an NSString
please help ive been trying to solve this for a very long time ...
this is the code i use to make buttons. then you add the button to a view !
edit: you would change the setTitle: part of this to whatever string you wanted the button to display as its title.
//create the button
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
//sets its size
[button setFrame:CGRectMake(10, 10, 300, 50)];
//set title, font size and font color
[button setTitle:#"Sign Up" forState:UIControlStateNormal];
[button setFont:[button.font fontWithSize:22]];
[button setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
[button setBackgroundImage:[UIImage imageNamed:#"green_btn_bg.png"] forState:UIControlStateNormal];
//set action of the button
[button addTarget:self action:#selector(signUp:)
forControlEvents:UIControlEventTouchUpInside];