UI issues in UITabBarController - objective-c

here is the source code
problem: TabbarController is not working properly...
please help me
NSArray *actionButtonItems = #[searchItem, refreshItem];
self.navigationItem.rightBarButtonItems = actionButtonItems;
NSMutableArray *items = [[NSMutableArray alloc] init];
[items addObject:[[UITabBarItem alloc]
initWithTabBarSystemItem:UITabBarSystemItemHistory tag:1]];
[items addObject:[[UITabBarItem
alloc]initWithTabBarSystemItem:UITabBarSystemItemContacts tag:2]];
tabBar.items = items;
tabBar.delegate = self;
addFriends = [[AddFriendsViewController alloc] initWithNibName:#"AddFriendsViewController" bundle:nil];
[self.tabView addSubview:addFriends.view];
//[self.tabsetSelectedIndex = 0];
_tabBarController.selectedIndex = 0;
[self.view addSubview:_tabBarController.view];

Before you call
[self.tabView addSubview:addFriends.view];
you should call
[self.tabView setViewControllers:[NSArray arrayWithObjects: addFriends, nil]];

Set selectedViewController property of UITabBarController:
self.myTabBarController.selectedViewController = myViewController;
Use as below
self.myTabBarController.selectedViewController
= [self.myTabBarController.viewControllers objectAtIndex:0];

Related

Pushing UITableViewControllers and filtering/reloading the data

I think this is probably a simple problem that I am not understanding but I have spent a lot of time on it and it is holding up my work.
I have a UITableViewController that displays 4 rows of "topics". When you touch one, it creates an instance of my UITableViewController class, set's the data source array to the array of "subtopics" and pushes the controller onto the nav stack. When I go to my "All" topics page with say 10 rows, I have a segmented control for filtering the results. I am able to successfully filter the array but when I assign it to my self.topicsDataSource and call [self.tableView reloadData], nothing happens. The delegate methods numberOfSections and numberOfRowsInSection, but cellForRowAtIndexPath is not. When I press the navigation back button it goes back to and the previous table is now the filtered results I wanted in the top table.
So here's what I think is happening.
1. I am actually altering the data source of the previous table, and self.tableView.reloadData is being called on that table.
2. cellForRowAtIndexPath is not called because the tableview being reloaded is not visible at that time.
Here is where I am instantiating an pushing the table views. This class is called TopicsViewController
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSNumber *idtopic = [[self.topicsDataSource objectAtIndex:indexPath.row] idtopic];
NSArray *subtopics = [DataManager getSubtopicsForTopic:idtopic];
if ([subtopics count] > 0) {
TopicsViewController *topicsVC = [[TopicsViewController alloc ] init];
topicsVC.tableView.rowHeight = 106;
topicsVC.parentTopicId = idtopic;
topicsVC.topicsDataSource = [NSMutableArray arrayWithArray:subtopics];
topicsVC.diseaseStateId = self.diseaseStateId;
topicsVC.title = [[self.topicsDataSource objectAtIndex:indexPath.row] topic];
[self.navigationController pushViewController:topicsVC animated:YES];
}
else if (![[self.topicsDataSource objectAtIndex:indexPath.row] topic]) {
//all topics was selected
TopicsViewController *topicsVC = [[TopicsViewController alloc] initWithNibName:nil bundle:nil];
topicsVC.tableView.rowHeight = 106;
NSMutableArray *mArray = [[NSMutableArray alloc] initWithArray:[DataManager getTopicsAtEndOfTree]];
topicsVC.allTopics = mArray;
topicsVC.topicsDataSource = topicsVC.allTopics;
topicsVC.diseaseStateId = self.diseaseStateId;
topicsVC.parentTopicId = [NSNumber numberWithInt:100];
UISegmentedControl *segControl = [[UISegmentedControl alloc] initWithItems:[[NSArray alloc] initWithObjects:#"All", #"Speaker Direct", #"Live Meeting", nil]];
[segControl addTarget:self action:#selector(segControlChanged:) forControlEvents:UIControlEventValueChanged];
[segControl setSegmentedControlStyle:UISegmentedControlStyleBar];
[segControl setSelectedSegmentIndex:0];
topicsVC.navigationItem.titleView = segControl;
topicsVC.tableView.dataSource = topicsVC;
[self.navigationController pushViewController:topicsVC animated:YES];
}....
and here is where I am filtering the data and reloading the tableView:
- (void)segControlChanged:(UISegmentedControl *)sender
{
self.allTopics = [NSMutableArray arrayWithArray:[DataManager getTopicsAtEndOfTree]];
if (sender.selectedSegmentIndex == 1) {
NSPredicate *pred = [NSPredicate predicateWithFormat:#"type == 2"];
NSMutableArray *mArr = [[NSMutableArray alloc] initWithArray:[self.allTopics filteredArrayUsingPredicate:pred]];
self.topicsDataSource = mArr;
}
else if (sender.selectedSegmentIndex == 2) {
NSPredicate *pred = [NSPredicate predicateWithFormat:#"type == 1"];
NSMutableArray *mArr = [[NSMutableArray alloc] initWithArray:[self.allTopics filteredArrayUsingPredicate:pred]];
self.topicsDataSource = mArr;
}
else {
NSMutableArray *mArr = [[NSMutableArray alloc] initWithArray:[DataManager getTopicsAtEndOfTree]];
self.topicsDataSource = mArr;
}
[self.tableView reloadData];
}
Any help would be appreciated. Thanks!
- (void)segControlChanged:(UISegmentedControl *)sender
{
self.allTopics = [NSMutableArray arrayWithArray:[DataManager getTopicsAtEndOfTree]];
if (sender.selectedSegmentIndex == 1) {
NSPredicate *pred = [NSPredicate predicateWithFormat:#"type == 2"];
NSMutableArray *mArr = [[NSMutableArray alloc] initWithArray:[self.allTopics filteredArrayUsingPredicate:pred]];
self.topicsDataSource = mArr;
}
else if (sender.selectedSegmentIndex == 2) {
NSPredicate *pred = [NSPredicate predicateWithFormat:#"type == 1"];
NSMutableArray *mArr = [[NSMutableArray alloc] initWithArray:[self.allTopics filteredArrayUsingPredicate:pred]];
self.topicsDataSource = mArr;
}
else {
NSMutableArray *mArr = [[NSMutableArray alloc] initWithArray:[DataManager getTopicsAtEndOfTree]];
self.topicsDataSource = mArr;
}
[tableView reloadData]; //
}
It's very difficult to tell what your question is and what is happening - I'd suggest next time asking a question with much less random code, more explanation, and a more obvious question (also better formatting). Anyway.
As best as I can tell, self is still referring to the original view controller. I'm not sure what classes your code is coming from but if you want this to work you need to
Write a custom class for TopicsViewController
Push it/etc
Inside the custom class, define datasource, reloading, etc
Call the change datasource method inside of the custom class
Call the reloadData method on the tableView of the custom class.
The point is, make sure that all of your work happens inside of the class for your custom table view data controller.

I want grab 1 random item out of 4 different arrays and display the result

I have an app that uses 3 arrays. The interface is basically 3 picker wheels that one can use to select from a plethora of choices to form a 3 part answer.
But, I need to randomize these not unlike what urban spoon does short of the graphical aspect.
I just need to implement a button that will reach into the arrays and give me a random selection from each array.
Here is a snippet of my code as it sits now...
Any help would be appreciated...
import "DoubleComponentPickerViewController.h"
#implementation DoubleComponentPickerViewController
#synthesize doublePicker;
#synthesize firstTypes;
#synthesize middleTypes;
#synthesize lastTypes;
-(IBAction)buttonPressed
{
NSInteger firstRow = [doublePicker selectedRowInComponent:kfirstComponent];
NSInteger middleRow = [doublePicker selectedRowInComponent:kmiddleComponent];
NSInteger lastRow = [doublePicker selectedRowInComponent:klastComponent];
NSString *first = [firstTypes objectAtIndex:firstRow];
NSString *middle = [middleTypes objectAtIndex:middleRow];
NSString *last = [lastTypes objectAtIndex:lastRow];
NSString *message = [[NSString alloc] initWithFormat:#"%# %# %# test.",first, middle, last];
UIAlertView *alert = [[ UIAlertView alloc] initWithTitle:#"Description:"
message:message
delegate:nil
cancelButtonTitle:#"Cancel"
otherButtonTitles:nil];
[alert show];
[alert release];
[message release];
}
- (void)viewDidLoad
{
NSArray *firstArray = [[NSArray alloc] initWithObjects:
#"a",#"b",#"c",#"d",nil];
self.firstTypes = firstArray;
[firstArray release];
NSArray *middleArray = [[NSArray alloc] initWithObjects:
#"A",#"B",#"C",#"D",nil];
self.middleTypes = middleArray;
[middleArray release];
NSArray *lastArray = [[NSArray alloc] initWithObjects:
#"1",#"2",#"3",#"4",nil];
self.lastTypes = lastArray;
[lastArray release];
You can pick a random element of firstTypes like this:
NSObject *randomFirst = [self.firstTypes objectAtIndex:arc4random_uniform(self.firstTypes.count)];

Application crashes when searching ONE word

I'm making my UISearchBar working and i've noticed that if i type a word, just ONE, contained in more controllers (for example "a") and i select a row, i get an unexpected crash. If i search for more than a word it works, even if contained in more than 1 controller.
i'm getting a NSRangeException:
Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[NSArray objectAtIndex:]: index 9 beyond bounds [0 .. 8]'
at line
cellValue = [array objectAtIndex:indexPath.row];
of my code (i have 3 sections)
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
//Get the nib
NSString *cellValue = nil;
if(searching)
cellValue = [copyListOfItems objectAtIndex:indexPath.row];
else {
NSDictionary *dictionary =[listaOggetti objectAtIndex:indexPath.row];
NSArray *array = [dictionary objectForKey:#"Elementi"];
cellValue = [array objectAtIndex:indexPath.row];
}
NSDictionary *dict = [listaOggetti objectAtIndex:indexPath.section];
NSArray *array = [dict objectForKey:#"Elementi"];
cellValue = [array objectAtIndex:indexPath.row] ; //here's the error
if (indexPath.section == 0)
{
if ([cellValue isEqual: #"FirstNib"]){
FIrstViewController *firstController = [[FirstViewController alloc] initWithNibName:#"FirstViewController" bundle:nil];
[self.navigationController pushViewController:appsController animated:YES];
[firstController release];
if ([cellValue isEqual: #"SecondNib"]){
secondViewController *secondController = [[SecondViewController alloc] initWithNibName:#"secondViewController" bundle:nil];
[self.navigationController pushViewController:secondController animated:YES];
[secondController release];
}
//and so on
}
if (indexPath.section == 1){
if ([cellValue isEqual: #"ThirdNib"]){
ThirdViewController *firstController = [[ThirdViewController alloc] initWithNibName:#"ThirdViewController" bundle:nil];
[self.navigationController pushViewController:ThirdController animated:YES];
[ThirdController release];
}
//and so on
}
if (indexPath.section == 2) {
if ([cellValue isEqual #"FourthNib"]){
FourthViewController *firstController = [[FourthViewController alloc] initWithNibName:#"FourthViewController" bundle:nil];
[self.navigationController pushViewController:FourthController animated:YES];
[FourthController release];
}
}
(the line is not the one in the IF state)
Now. I know that it goes over the array, trying to access to the 10th element.
Passing the mouse over the line "array" here
cellValue = [array objectAtIndex:indexPath.row] ;
It tells me there are 9 objects on it, while there should be 45, as i declared them here, for the key #"Elementi":
- (void)viewDidLoad {
[super viewDidLoad];
listaOggetti = [[NSMutableArray alloc] init];
NSArray *arrayDesk = [NSArray arrayWithObjects: #"First",#"Second",#"Third"..#"9th", nil];
NSArray *sortedDesk = [arrayDesk sortedArrayUsingSelector:#selector(localizedCaseInsensitiveCompare:)];
NSDictionary *dictDesk = [NSDictionary dictionaryWithObject:sortedDesk forKey:#"Elementi"];
NSArray *arrayLion = [NSArray arrayWithObjects:#"First1",#"Second1" ... #"30th", nil];
NSArray *sortedLion = [arrayLion sortedArrayUsingSelector:#selector(localizedCaseInsensitiveCompare:)];
NSDictionary *dictLion = [NSDictionary dictionaryWithObject:sortedLion forKey:#"Elementi"];
NSArray *arrayRestore = [NSArray arrayWithObjects:#"First2",#"Second2" ... #"6th", nil];
NSArray *sortedRestore = [arrayRestore sortedArrayUsingSelector:#selector(localizedCaseInsensitiveCompare:)];
NSDictionary *dictRest = [NSDictionary dictionaryWithObject:sortedRestore forKey:#"Elementi"];
[listaOggetti addObject:dictDesk];
[listaOggetti addObject:dictLion];
[listaOggetti addObject:dictRest];
copyListOfItems = [[NSMutableArray alloc] init];
self.navigationItem.title = NSLocalizedString(#"TIPS", #"Tips");
self.view.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:#"window.png"]];
//Add the search bar
self.tableView.tableHeaderView = searchBar;
searchBar.autocorrectionType = UITextAutocorrectionTypeNo;
searching = NO;
letUserSelectRow = YES;
CGRect bounds = self.tableView.bounds;
bounds.origin.y = bounds.origin.y + searchBar.bounds.size.height;
self.tableView.bounds = bounds;
}
Shouldn't it see all the object for the key #"Elementi"? I'm on it from days, i can't understand how to solve, though.
Any help appreciated
*EDIT *
I noticed that
NSDictionary *dict = [listaOggetti objectAtIndex:indexPath.section];
has only 9 elements, as well as in the first array, but i have 3 dictionaries: dictDesk, dictLion, dictRest.
How can i do to select all the 45 elements in the NSDictionary?
*EDIT 2 *
Thanks to pengOne, i finally filled a global array with my 45 elements,this way
NSMutableArray *allObjects = [[NSMutableArray alloc] init];
[allObjects addObjectsFromArray:[[listaOggetti objectAtIndex:0] objectForKey:#"Elementi"]];
[allObjects addObjectsFromArray:[[listaOggetti objectAtIndex:1] objectForKey:#"Elementi"]];
[allObjects addObjectsFromArray:[[listaOggetti objectAtIndex:2] objectForKey:#"Elementi"]];
Now all i need to do it's to adapt something like this
NSDictionary *dictionary =[listaOggetti objectAtIndex:indexPath.row];
NSArray *array = [dictionary objectForKey:#"Elementi"];
cellValue = [array objectAtIndex:indexPath.row];
to the global array i've done, so it can let me search and select contents, either from tableView and SearchView.
The error tells you that you are sending this message:
[array objectAtIndex:9];
when array has 9 object, and it only responds to
[array objectAtIndex:0];
...
[array objectAtIndex:8];
The lines you need to investigate are:
NSArray *array = [dictionary objectForKey:#"Elementi"];
selectedRow = [array objectAtIndex:indexPath.row];
Check [dictionary objectForKey:#"Elementi"]. It appears to be an NSArray with 9 objects, when it needs to be an NSArray with at least 10 objects in order to access the object at index 10.
For your viewDidLoad method, it looks to me like listaOggetti is an NSMutableArray with 3 objects: dictDesk has 9 elements, dictLion has 30 elements, and dictRest has 6 elements.
To fix this error, you will need to change the number of rows in section 0 to be 9, the number of rows in section 1 to be 30 and the number of rows in section 2 to be 6.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSString* cellValue=#"";
if (searching)
cellValue = [copyListOfItems objectAtIndex:indexPath.row];
else{
NSDictionary *dictionary = [listaOggetti objectAtIndex:indexPath.section];
NSArray *array = [dictionary objectForKey:#"Elementi"];
cellValue = [array objectAtIndex:indexPath.row];
}
if ([cellValue isEqual: #"Apps on specific Desks"] || [cellValue isEqual: #"Applicazioni su piĆ¹ Scrivanie"]){
AppsViewController *appsController = [[AppsViewController alloc] initWithNibName:#"AppsViewController" bundle:nil];
[self.navigationController pushViewController:appsController animated:YES];
[appsController release];
}
}

NSMutableArray won't add NSDictionary

I updated to cocos2d from 0.99.4 to 0.99.5. While it was on the older version I had the high score list working and I was able to add the NSDictionary to NSMutableArray with no problems.
Now that I've updated it won't add the NSDictionary variable scoreDetails to my NSMutableArray scoreList. Here's my code:
StatsManager.h
#interface StatsManager : NSObject {
NSMutableArray *scoreList;
NSUserDefaults *saveHighScore;
NSMutableArray *printableScoreList;
//NSMutableArray *scoreListTestOne;
float highScoreHelloWorld;
}
StatsManager.m
-(void)setHighScore:(float)highScore nameStrings:(NSString*)nameString {
NSNumber *newHighScore = [NSNumber numberWithFloat:highScore];
NSLog(#"%# highScore", newHighScore);
NSDictionary *scoreDetails = [NSDictionary dictionaryWithObjectsAndKeys:nameString, #"name", newHighScore, #"score", nil];
NSLog(#"%#", scoreDetails);
//NSMutableArray *testTwo = [[NSMutableArray alloc] init];
[scoreList addObject:scoreDetails];
NSLog(#"scoreList %#", scoreList);
//[scoreListTestOne addObject:scoreDetails];
//NSLog(#"scoreListTestOne %#", scoreListTestOne);
//sort
NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:#"score" ascending:NO];
[scoreList sortUsingDescriptors:[NSArray arrayWithObject:sort]];
printableScoreList = scoreList;
NSLog(#"printableScoreList %#", printableScoreList);
//NSLog(#"scoreListTestOne %#", scoreListTestOne);
}
The line in question is
[scoreList addObject:scoreDetails];
I created a local NSMutableArray variable in the setHighScore function and tried adding the scoreDetails to that and it worked. but why doesn't it work like I've coded it above anymore?
I alloc init my scoreList here:
#implementation StatsManager
static StatsManager *_sharedStatsManager = nil;
-(id)init {
scoreList = [[NSMutableArray alloc] init];
//playerNames = [[NSMutableArray alloc] init];
//playerScores = [[NSMutableArray alloc] init];
printableScoreList = [[NSMutableArray alloc] init];
//listOfScoresTest = [[NSMutableDictionary alloc] initWithCapacity:5];
/*if ([scoreList count] == 0) {
for (int i = 0; i < 5; i++) {
[scoreList addObject:[NSNumber numberWithFloat:0.00]];
}
}*/
return [super init];
}
I should also mention that I created a new projectB and transferred my files/images from my old projectA to the new one because the old one wouldn't compile anymore because of some duplicate error. But i "cleaned all targets" again and it worked but that also has the same problem as my new projectB
Do you initialize scoreList ivar in init or so forth?
- (id)init
{
/* snip */
scoreList = [[NSMutableArray alloc] init];
return self;
}
- (void)dealloc
{
[scoreList release];
[super dealloc];
}
Ok Georg I reconsidered your suggestion about overwriting it later.
and it had something to do with my NSUserdefaults. I commented them out and now it add's the objects to my NSMutableArray. I'm pretty new to NSUserdefaults so I don't know exactly how to use it atm lol
-(void)save
{
//make another array to save the scores.
saveHighScore = [NSUserDefaults standardUserDefaults];
//[saveHighScore setObject:scoreListNew forKey:#"DodgerAppBeta"];
[saveHighScore synchronize];
//[[NSUserDefaults standardUserDefaults] setObject:scoreListTestOne forKey:#"DodgerBeta"];
//[[NSUserDefaults standardUserDefaults] synchronize];
}
-(void)load
{
saveHighScore = [NSUserDefaults standardUserDefaults];
//scoreListNew = [[saveHighScore objectForKey:#"DodgerAppBeta"] mutableCopy];
printableScoreList = [[saveHighScore objectForKey:#"DodgerAppBeta"] mutableCopy];
//NSLog(#"scoreListTestOne %#", scoreListTestOne);
//[printableScoreList addObject:[[NSUserDefaults standardUserDefaults] objectForKey:#"Dodger"]];
NSLog(#"PSL %#", printableScoreList);
}

Populating an NSArray/NSMutableArray, the right way

This is a general question about memory management and best practices when using Cocoa arrays.
Which of the following is "better":
NSArray *pageControllers = [[NSArray alloc] initWithObjects:
[[Page1 alloc] initWithNibName:#"Page1" bundle:nil],
[[Page2 alloc] initWithNibName:#"Page2" bundle:nil],
[[Page3 alloc] initWithNibName:#"Page3" bundle:nil],
nil];
...then release NSArray later when not needed anymore...
Or
NSMutableArray *pageControllers = [[NSMutableArray alloc] init];
UIViewController *page1 = [[Page1 alloc] initWithNibName:#"Page1" bundle:nil];
[pageControllers addObject:page1];
[page1 release];
UIViewController *page2 = [[Page2 alloc] initWithNibName:#"Page2" bundle:nil];
[pageControllers addObject:page2];
[page2 release];
UIViewController *page3 = [[Page3 alloc] initWithNibName:#"Page3" bundle:nil];
[pageControllers addObject:page3];
[page3 release];
...then release NSMutableArray later when not needed anymore...
Or is there something else that's even better?
Either way works fine, but keep in mind that you'll be leaking all your page objects in the first example.