I'm using the master detail template.
Header file MasterViewController.h:
#import <UIKit/UIKit.h>
//(Imported both MasterViewController.h and DetailViewController.h in implementation file of MasterViewController.m)
#class DetailViewController;
#interface MasterViewController : UITableViewController
#property (strong, nonatomic) DetailViewController *detailViewController;
-(void)createFlowerData;
#end
Implementation file HeaderViewController.m:
#interface MasterViewController () {
NSMutableArray *_objects;
NSArray *_flowerData;
NSArray *_flowerSections;
}
#end
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.navigationItem.leftBarButtonItem = self.editButtonItem;
UIBarButtonItem *addButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:#selector(insertNewObject:)];
self.navigationItem.rightBarButtonItem = addButton;
self.detailViewController = (DetailViewController *)[[self.splitViewController.viewControllers lastObject] topViewController];
//invoking the method I implemented to give data to flowerData array
[self createFlowerData];
}
-(void)createFlowerData{
NSMutableArray *redFlowers;
NSMutableArray *blueFlowers;
redFlowers = [[NSMutableArray alloc] init];
blueFlowers = [[NSMutableArray alloc] init];
//create the 2 sections for the flowerSections array
_flowerSections = #[#"Red Flowers", #"Blue Flowers"];
//add the objects to the mutable array
//red flowers
[redFlowers addObject:#{#"name":#"Poppy",#"picture":#"Poppy.png",#"url":#"http://en.wikiepdia.org/wiki/Poppy"}];
[redFlowers addObject:#{#"name":#"Tulip",#"picture":#"Tulip.png",#"url":#"http://en.wikipedia.org/wiki/Tulip"}];
[redFlowers addObject:#{#"name":#"Gerbera",#"picture":#"Gerbera.png",#"url":#"http://en.wikiepdia.org/wiki/Gerbera"}];
//blue flowers
[blueFlowers addObject:#{#"name":#"Phlox",#"picture":#"Phlox.png",#"url":#"http:en.wikipedia.org/wiki/Gerbera"}];
[blueFlowers addObject:#{#"name":#"Pin Cushion Flower",#"picture":#"Pincushion flower.png",#"url":#"http://en.wikipedia.org/wiki/Scabious"}];
[blueFlowers addObject:#{#"name":#"Iris",#"picture":#"Iris.png",#"url":#"http://en.wikipedia.org/wiki/Iris_(plant)"}];
_flowerData = #[redFlowers, blueFlowers];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return [_flowerSections count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
//find the number of row elements in a given section of the flower Data array
return [_flowerData[section] count];
}
-(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section{
//index 0 is the red flower
//index 1 is the blue flower
return _flowerSections[section];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"flowerCell"];
cell.textLabel.text = _flowerData[indexPath.section][indexPath.row][#"name"];
cell.detailTextLabel.text = _flowerData[indexPath.section][indexPath.row][#"url"];
cell.imageView.image = _flowerData[indexPath.section][indexPath.row][#"picture"];
return cell;
}
I then get the following when I build the application on the ios simulator(iPad):
2013-09-01 23:49:40.015 flowerDetail2[2394:c07] -[__NSCFConstantString _isResizable]: unrecognized selector sent to instance 0x6af4
2013-09-01 23:49:40.017 flowerDetail2[2394:c07] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFConstantString _isResizable]: unrecognized selector sent to instance 0x6af4'
*** First throw call stack:
(0x1c95012 0x10d2e7e 0x1d204bd 0x1c84bbc 0x1c8494e 0x4ca7ab 0x121ae9 0x2c1f 0xd18fb 0xd19cf 0xba1bb 0xcab4b 0x672dd 0x10e66b0 0x2291fc0 0x228633c 0x2291eaf 0x1062bd 0x4eb56 0x4d66f 0x4d589 0x4c7e4 0x4c61e 0x4d3d9 0x502d2 0xfa99c 0x47574 0x4776f 0x47905 0x8dceab6 0x50917 0x1496c 0x1594b 0x26cb5 0x27beb 0x19698 0x1bf0df9 0x1bf0ad0 0x1c0abf5 0x1c0a962 0x1c3bbb6 0x1c3af44 0x1c3ae1b 0x1517a 0x16ffc 0x1bed 0x1b15)
libc++abi.dylib: terminate called throwing an exception
(lldb)
(Please note that I did not include everything, just the parts I thought were important)
This has been driving me crazy the whole day, I've checked multiple times, rewritten the whole thing and still the same result, I can't even get the cells to display. I googled, and I found something like it means that I'm sending a message to a method that doesn't know what to do with it, but I'm sure it's right? Could somebody please help me debug this!
cell.imageView.image = _flowerData[indexPath.section][indexPath.row][#"picture"];
this line cell.imageView.image expect UIImage type
[redFlowers addObject:#{#"name":#"Gerbera",#"picture":#"Gerbera.png",#"url":#"http://en.wikiepdia.org/wiki/Gerbera"}];
but you give it a NSString here, which of cause will make runtime error.
So should be like this
cell.imageView.image = [UIImage imageNamed:_flowerData[indexPath.section][indexPath.row][#"picture"]];
If you are NOT using ARC: You need to retain each of your dictionaries. Like this redFlowers = [[[NSMutableArray alloc] init] retain]; do that for each of your arrays. Also, NSLog(#"%#", redFlowers) before the line of code where your app crashes and post the output. Replace redFlowers with whatever the dictionary being called next is.
From what i am getting, what you need to do is first make NSDictionary objects and than add those objects to NSMutableArray.
NSMutableDictionary *dic = [[NSMutableDictionary alloc] init];
[dic setValue:#"Poppy" forKey:#"name"];
[dic setValue:#"Poppy.png" forKey:#"picture"];
[dic setValue:#"http://en.wikiepdia.org/wiki/Poppy" forKey:#"url"];
[redFlowers addObject:dic];
[dic release]; // Dont use this in case of ARC
Repeat this for all three or number of objects you need to add. Hope this helps.
Related
In one class called LevelSelectViewController, I have this public property
#property (nonatomic, strong, getter=getLevelNumber) NSNumber *levelNumber;
which stores an int value based on a UIButton* touch selection using the method
- (IBAction)buttonPressedSoWhatNumber:(id)sender
{
UIButton *button = (UIButton *)sender;
int row = button.tag;
_levelNumber = [NSNumber numberWithInt:row];
}
When I put a breakpoint at the end of the method to see if my touch interaction triggers the correct result based on what I coded (when I press button 1, really), _levelNumber reads 0 (which it should). I also have a getter method written out for it.
Now, in this second class called GameViewController, I have a method setUpBoards which (should) obtain that value for *levelNumber. It looks like this:
- (void)setUpBoards {
LevelSelectViewController* level = [[LevelSelectViewController alloc] init];
[level getLevelNumber];
[self createLevelModel:(int)level];
}
In that same class, the method createLevelModel:(int)levelIndex uses that value to be passed to 5 initialization methods that access a Levels.plist file to load data for my game.
Basically, that number represents what level button I pressed and uses that number to load the correct level. In another manner, I have verified that those 5 initialization methods work along with loading data from my Levels.plist file.
Now, between the transition from LevelSelectViewController to GameViewController, I receive the NSRangeException error message:
'NSRangeException', reason: '-[__NSCFArray objectAtIndex:]: index (554166800) beyond bounds (1)'
even when pressing the 1 button (which should work considering I only have Item 0 in my plist typed out.......which, again, I verified worked using another manner).
TO ADD ON TO THIS. Here's another important method:
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView
cellForItemAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellIdentifier = #"cvCell";
CVCell *cell = (CVCell *)[collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier forIndexPath:indexPath];
NSMutableArray *data = [self.dataArray objectAtIndex:indexPath.section];
NSString *cellData = [data objectAtIndex:indexPath.row];
[cell.buttonClick setTag:indexPath.row];
[cell.buttonClick addTarget:self action:#selector(buttonPressedSoWhatNumber:)
forControlEvents:UIControlEventTouchUpInside];
[cell addSubview:cell.buttonClick];
return cell;
}
Any insight?
Here's the push controller method from LevelSelectViewController to GameViewController:
-(IBAction)buttonPressed:(id)sender {
GameViewController* obj = [[GameViewController alloc] initWithNibName:#"GameViewController" bundle:nil];
[self.navigationController pushViewController:obj animated:YES];
}
buttonPressed: is another method given to the UIButton*
You need a simple int property in LevelSelectViewController that you can use to store the level that has been selected:
#property int levelSelected;
The store the selected value in your button press handler:
- (IBAction)buttonPressedSoWhatNumber:(UIButton *)sender
{
self.levelSelected = sender.tag;
}
Then you can pass this to a corresponding int property on your GameViewController;
-(IBAction)buttonPressed:(id)sender {
GameViewController* obj = [[GameViewController alloc] initWithNibName:#"GameViewController" bundle:nil];
obj.level = self.selectedLevel
[self.navigationController pushViewController:obj animated:YES];
}
The problem is that you are casting a pointer to an int.
#property (nonatomic, strong, getter=getLevelNumber) NSNumber *levelNumber;
Defines a pointer to an object of type NSNumber.
[self createLevelModel:(int)level];
Is casting that NSNumber * to an int.
You also have another bug in that you are setting level as the view controller and calling getLevelNumber but not actually using the returned value. So here is what I would do. Firstly you don't need to define an NSNumber and don't need a custom getter. Just use this:
#property (nonatomic, assign) int levelNumber;
Then this becomes much simple:
- (void)setUpBoards {
LevelSelectViewController* levelSelectViewController = [[LevelSelectViewController alloc] init];
[self createLevelModel: levelSelectViewController.levelNumber]; // Always going to be zero at this point.
}
I'm following along with the Big Nerd Ranch ios book, chapter 11. It uses a table view in the ItemsViewController to display a list of items and if you click on an item it transfers control to a DetailViewController that shows the details about the individual item. The DetailViewController.xib has outlets for these fields declared in the header file DetailViewController.h
__weak IBOutlet UITextField *nameField;
__weak IBOutlet UITextField *serialNumberField;
__weak IBOutlet UITextField *valueField;
__weak IBOutlet UILabel *dateLabel;
The application worked fine up to a point. If i clicked on an item, the new view would open but the fields were empty. Therefore, the tutorial introduced us to a way to have the fields populated with the values of each item. After introducing this new code to populate the fields, the application crashes with the following errors once I click on an item to view its details
2014-02-12 07:18:30.720 Homepwner[3180:a0b] -[UIView setText:]: unrecognized selector sent to instance 0x89ef8c0
2014-02-12 07:18:30.724 Homepwner[3180:a0b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UIView setText:]: unrecognized selector sent to instance 0x89ef8c0'
Based on the code excerpts below can you explain why the application might be crashing when I click on one of the items in the list to open it in the detail view?
This is the code we are given to populate the fields
DetailViewController.m
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[nameField setText:[item itemName]];
[serialNumberField setText:[item serialNumber]];
[valueField setText:[NSString stringWithFormat:#"%d", [item valueInDollars]]];
// Create a NSDateFormatter that will turn a date into a simple date string
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateStyle:NSDateFormatterMediumStyle];
[dateFormatter setTimeStyle:NSDateFormatterNoStyle];
// Use filtered NSDate object to set dateLabel contents
[dateLabel setText:[dateFormatter stringFromDate:[item dateCreated]]];
// Change the navigation item to display name of item
[[self navigationItem] setTitle:[item itemName]];
}
In ItemViewController.m, we added the middle three lines in this function so that the DetailViewController has its item before viewWillAppear: gets called
- (void)tableView:(UITableView *)aTableView
didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
DetailViewController *detailViewController = [[DetailViewController alloc] init];
NSArray *items = [[BNRItemStore sharedStore] allItems];
BNRItem *selectedItem = [ items objectAtIndex: [indexPath row]];
[detailViewController setItem:selectedItem];
[[self navigationController] pushViewController:detailViewController animated:YES];
}
Since the nameField property is initialized through a NIB/Storyboard, the most likely reason for the problem that you are seeing is an incorrect connection done in the Interface Builder. It appears that the nameField outlet is connected to the parent of UITextEdit, as opposed to the UITextEdit itself.
Removing and re-creating the nameField property should fix the problem. First, remove the property from the code. Then, control-drag from the text field into the DetailViewController's class extension inside DetailViewController.m, and name the property nameField.
In the iOS application, I need to pass an object from one view controller to another and then switch to the new view controller. The goal is to simply relay the information. However, the object becomes NULL and is devoid of any information when the next view showed up. what? could be the reason?
Below is part of my code.
#pragma mark - Table view delegate
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
BIDCourse *course = self.courses[indexPath.row];
NSString *sub = course.subject;
BIDSubjectMainTwoViewController *subjectController=[[BIDSubjectMainTwoViewController alloc] init];
subjectController.title = sub;
subjectController.course=course;
[self.navigationController pushViewController:subjectController animated:YES];
}
BIDCourse *course is my custom subclass to NSObject, which has some NSStrings, and it's not nil, but when I pass it onto the next view controller, it becomes NULL.
I have met a problem like you , when I pass a object to another viewController , it has been released.
I think this is a defect of ARC , ARC think your subjectController may be no use , so it release the subjectController. Make your subjectController as a property , so ARC will not release when you pass it to another viewController.
such as :
#pragma mark - Table view delegate
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
BIDCourse *course = self.courses[indexPath.row];
NSString *sub = course.subject;
_subjectController=[[BIDSubjectMainTwoViewController alloc] init];
_subjectController.title = sub;
_subjectController.course=course;
[self.navigationController pushViewController:_subjectController animated:YES];
}
Could the problem lie in BIDSubjectMainTwoViewController.m?
subjectController.title = sub;
subjectController.course = course;
in your BIDSubjectMainTwoViewController.m file, did you #synthesize your properties?
#synthesize title = _title;
#synthesize course = _course;
You could also pass the variables along with an init function ala:
BIDSubjectMainTwoViewController.h
- (id)initWithTitle:(NSString *)title
andCourse:(BIDCourse *)course;
BIDSubjectMainTwoViewController.m
- (id)initWithTitle:(NSString *)title
andCourse:(BIDCourse *)course
{
self = [super init];
if (self) {
// Custom initialization
_title=title;
_course = course;
}
return self;
}
I encountered this similar behavior. My solution was to make a copy of the object. For your case:
BIDCourse *course = [self.courses[indexPath.row] copy];
And make sure you implement copyWithZone in the BIDCourse .m fike.
-(id)copyWithZone:(NSZone*) zone
Try this:
BIDSubjectMainTwoViewController.h
NSString *strTemp;
#property(nonatomic,retain) NSString *strTemp;
-(void) setValuestrTemp : (NSString *) str;
.m file
#synthesize strTemp;
// Write setter method
-(void) setValuestrTemp : (NSString *) str {
self.strTemp = str;
}
and use strTemp in viewWillAppear.
//Now use it
BIDSubjectMainTwoViewController *subjectController=[[BIDSubjectMainTwoViewController alloc] init];
[subjectController setValuestrTemp:sub];
[self.navigationController pushViewController:_subjectController animated:YES];
Use
NSString *sub = [course.subject copy];
subjectController.course=[course copy];
implement delegate in BIDCourse
-(id)copyWithZone:(NSZone*) zone
I have a text field In that user can enter values from 1-10
at the bottom of the text field i have button.
i need to add the values in text filed to array when user clicks done button
for this i wrote code like this.
- (void)viewDidLoad
{
[super viewDidLoad];
PainlevelsArray = [[NSMutableArray alloc] init]; //PainlevelsArray declared in .h
}
-(IBAction)doneClick:(id)sender
{
[PainlevelsArray addObject:txtField.text ];
// [PainlevelsArray insertObject:rateLabel.text atIndex:0 ];
NSLog(#"PainlevelsArray *** %#",PainlevelsArray);
[self.navigationController popToRootViewControllerAnimated:YES];
}
But every time array displays only the recently added one value only in log when button clicks, like this
Output on Console
========================
2012-05-07 10:11:15.689 ESPT[796:10d03] PainlevelsArray *** (
2
)
2012-05-07 10:11:27.984 ESPT[796:10d03] PainlevelsArray *** (
4
)
My array gets empty every time view loads, and adde a fresh entry when button clicks
But i need like this
2012-05-07 10:11:27.984 ESPT[796:10d03] PainlevelsArray *** (
4,
5,
2,
6,
8,
)
All the velues enters are adde/inserted to the existing array.
Thanks in advance
in ExerciseStartViewController
-(void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
ExerciseResult *result = [[ExerciseResult alloc] init];
[self.navigationController pushViewController:result animated:YES];
[result release];
}
in current/ ExerciseResult viewcontroller
- (void)viewDidLoad
{
[super viewDidLoad];
PainlevelsArray = [[NSMutableArray alloc] init]; //PainlevelsArray declared in .h
}
-(IBAction)doneClick:(id)sender
{
[PainlevelsArray addObject:txtField.text ];
// [PainlevelsArray insertObject:rateLabel.text atIndex:0 ];
NSLog(#"PainlevelsArray *** %#",PainlevelsArray);
[self.navigationController popToRootViewControllerAnimated:YES];
}
You need to use a global array.
Best possible solution is declare an array in AppDelegate.h file and alloc-init this array in applicationdidfinishlaunch method.
AppDelegate *app = (AppDelegate*)[[UIApplication sharedApplication] delegate];
[app.arrMutable addObject:textField.text ];
Use UserDefaults: These are used to save your application data in key-value format. The values/objects stored as userdefaults always remain in application, until you have not removed it from sandbox. You can use following code to store an array in userdefaults.
[[NSUserDefaults standardUserDefaults] setObject:app.arrMutable forKey:#"Global_Array_Key"];
In AppDelegae applicationDidFinishLuanch method you can retrieve this array from userdefaults using:
self.arrMutable = [[NSMutableArray alloc]initWithArray:[[NSUserDefaults standardUserDefaults]objectForKey:#"Global_Array_Key"]];
You need to declare and initialize PainlevelsArray globally, i.e. in AppDelegate or separate class of shared instance, where memory has been assigned once and it won't over write its data even though any number of time you access the said class and so that it will continuously inserts new value into the array and you will get the desired result.
ExerciseResult *result = [[ExerciseResult alloc] init];
[self.navigationController pushViewController:result animated:YES];
[result release];
I think you might be fallow this type of code in you action for coming to this view. Instead of this you have to fallow to take as global ExerciseResult *result
in .h
ExerciseResult *result;
in .m
in viewDidLoad
result = [[ExerciseResult alloc] init];
in you action method you will fallow
[self.navigationController pushViewController:result animated:YES];
you will follow like that
I hope it will helps you
Declare in Delegate.h page
#interface AppDelegate : NSObject <UIApplicationDelegate>
{
NSMutableArray *commString;
}
#property (nonatomic, retain) NSMutableArray *commString;
#end
Delegate.m page
#sythesize commString;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
commString = [[NSMutableArray alloc] init];
// some code.....
}
In your Button view
-(IBAction)doneClick:(id)sender
{
NSMutableArray *mut=[[NSMutableArray alloc] initWithObjects:txtField.text,nil];
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
appDelegate.commString=mut;
// some code....
}
Declare this code where u want your array, you can easily get ur array.
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
NSLog(#"commString=%#",appDelegate.commString);
You use this line of code when you click just write add this line.
[array addobject:textfield.text];
use this only.
[PainlevelsArray addObject:txtField.text]
You should use properties for an array in this situation.
#property (nonatomic, strong) NSMutableArray *painlevelsArray;
Initialize the array
NSMutableArray *array = [[NSMutableArray alloc] init];
self.painlevelsArray = array;
Then add your string to the array after each button click
[self.painlevelsArray addObject:[NSString stringWithFormat:#"%#",self.textField.text]];
I'm implementing a uinavigationcontroller. The first view is a uitableview (imagine the Contacts app) with a list of names.
The second view is the person profile.
So, when I click a person in the uitable, it's suppose to load his profile.
How do I pass the person data to the second view?
In didSelectRowAtIndexPath I do:
ContactView * varContactView = [[ContactView alloc] initWithNibName:nil bundle:nil];
varContactView.title = [[contactsArray objectAtIndex:indexPath.row] name];
[varContactView initWithPerson:[contactsArray objectAtIndex:indexPath.row]];
[navigationController pushViewController:varContactView animated:YES];
In the interface of ContactView I've got:
Person * person;
And then:
#property (nonatomic, retain) Person * person;
-(void) initWithPerson:(Person *)newperson;
And in .m:
#synthesize person
-(void) initWithPerson:(Person *)newperson{
person = [[Person alloc] init];
person = newperson;
}
However, when I try to access person in ContactView, it says always EXC_BAD_ACCESS.
What is wrong here?
Instead of:
[varContactView initWithPerson:[contactsArray objectAtIndex:indexPath.row]];
you can simply use:
varContactView.person = [contactsArray objectAtIndex:indexPath.row];
That will make use of person property setter and assign the given object as varContactView's data. The default implementation of that setter is (in case of retain property):
- (void)setPerson:(Person *)newPerson
{
if (person != newPerson) {
[person release];
person = [newPerson retain];
}
}
That's what you're trying to achieve in -initWithPerson: method. That method is not needed, as its functionality is covered by person property setter. BTW, remember to release person property in -dealloc method of your view controller:
- (void)dealloc
{
[person release];
[super dealloc];
}
The bad access exception might be caused by something else in your code, though...
In .m file, change the code as given below.
-(void) initWithPerson:(Person *)newperson
{
self.person = newperson;
}