how to instantiate a CD entity without being fetched - objective-c

I have a program that fetches from Core Data and then within the program if something is fetches it displays the results in my UITableView.
Now my problem is that sometimes I need the user to add another UITableCell to my UITableView but my tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section counts the elements in my array which holds my ExerciseData entities.
I've tried to create an ExerciseData entity as if it was an object but this doesnt work and crashes the program.
by doing
if ([[_ed objectAtIndex:indexPath.row] weight]) {
NSLog(#"%#",_ed);
cell.weightInput.text = [NSString stringWithFormat:#"%#",[[_ed objectAtIndex:indexPath.row] weight]];
}
it throws the error CoreData: error: Failed to call designated initializer on NSManagedObject class 'ExerciseData' that made me understand that I cant initiate a CD entity like that.
then I've tried to add to the NSArray _ed a NSString and then check for the class and if the class type was a class of NSString it shouldnt try to set cell.weightInput.text
My question are 2:
1) Is there a way to initiate an entity so that I can insert it in the array and then check if is empty so that then i can validate it on a later if statement?
if that is not possible
2) How could i populate the NSArray with something that can then be validated & escalated to multimple items but also work when there is a ExerciseData?
My goal is that the person uses - addSet to create a new UITableCell for as many times the button is pressed then i need to validate whatever is inside so that if is a ExerciseData entity and the property weight is set to populate cell.weightInput.text or otherwise dont populate it
- (void) addNewSet {
ExerciseData * newEd = [[ExerciseData alloc] init];
NSMutableArray* ar = [[NSMutableArray alloc]initWithArray:_ed];
[ar addObject:newEd];
_ed = [[NSArray alloc] initWithArray:ar];
[_mytable reloadData];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
workoutCell * cell = [tableView dequeueReusableCellWithIdentifier:#"cell"];
if (!cell) {
cell = [[workoutCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"cell"];
}
cell.weightInput.text = #"";
if ( indexPath.row < [_ed count] ) {
if (![[[_ed objectAtIndex:indexPath.row] class] isKindOfClass:[NSString class]]) {
NSLog(#"%#",_ed);
cell.weightInput.text = [NSString stringWithFormat:#"%#",[[_ed objectAtIndex:indexPath.row] weight]];
}
}
//...
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if ( [_ed count] == 0 ) {
return 1;
} else {
return [_ed count];
}
}

To create a new CoreData entity you need to:
ExerciseData *data = (ExerciseData*)[NSEntityDescription insertNewObjectForEntityForName:#"ExerciseData" inManagedObjectContext:yourContext];
Make sure to save your context after!

Related

How to get responseObject into cells in UITableView

I'm making an 'Add Friend' function, where it's possible to search on a username. I have a responeObject that contains an array of users. I only want to get the #"name" object for all the users and then list them in the TableView. If I search on "e" i get 3 results:
responseObject: (
{
id = 1;
isUsersAccount = 0;
name = Eshixf;
},
{
id = 3;
isUsersAccount = 0;
name = Neigstal;
},
{
id = 4;
isUsersAccount = 0;
name = Howie;
})
How can I get out all 3 names in 3 different cells?
And why does I get an error when I running the code with this line inside?:
NSDictionary *nameDict = [[friendRow objectAtIndex:0]objectForKey:#"name"];
It gives me this error:
-[__NSCFArray objectForKey:]: unrecognized selector sent to instance 0x7faec35f4d40
Thank you!
you can get all names with simple iteration over response.
NSArray *response = friendRow[0]; // this is result dictionaries in an array. actually it is your responseObject.
//NSMutableArray *names = [NSMutableArray new];
names = [NSMutableArray new];//if declared outside the method, use this array as a dataSource for tableView.
for(NSDictionary *dict in response)
{
[names addObject:dict[#"name"]];
}
NSLog("names %#", names);
//refresh your tableview;
[yourTableView reloadData];
EDIT for TableView:
create names in interface as
NSMutableArray *names;
in delegate method:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
[cell.textLabel setText:names[indexPath.row]];
return cell;
}
with this method, tableview will know how many cells it needs.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return [names count];
}

Populating table with 2 arrays

I'm trying to populate a tableview controller with objects from 2 different arrays but it crashes and gives this error
"Terminating app due to uncaught exception 'NSRangeException', reason: ' -[__NSArrayM objectAtIndex:]: index 1 beyond bounds [0 .. 0]"***
how do i fix this? below is my code:
(void)viewDidAppear:(BOOL)animated{
//[super viewDidAppear:<#animated#>];
NSManagedObjectContext *bookmanagedObjectContext = [self managedObjectContext];
NSFetchRequest *bookfetchRequest = [[NSFetchRequest alloc] initWithEntityName:#"Book"];
NSPredicate *bookpredicate =[NSPredicate predicateWithFormat:#" bookref.toproject contains[cd]%#",self.projectdb];
[bookfetchRequest setPredicate:bookpredicate];
NSSortDescriptor *booksortDescriptor = [[NSSortDescriptor alloc]initWithKey:#"authorSurname" ascending:YES];
NSArray *booksortDescriptors = [[NSArray alloc]initWithObjects:booksortDescriptor, nil];
[bookfetchRequest setSortDescriptors:booksortDescriptors];
self.BookrefArray = [[bookmanagedObjectContext executeFetchRequest:bookfetchRequest error:nil] mutableCopy];
NSManagedObjectContext *journalmanagedObjectContext = [self managedObjectContext];
NSFetchRequest *journalfetchRequest = [[NSFetchRequest alloc] initWithEntityName:#"Journal"];
NSPredicate *journalpredicate =[NSPredicate predicateWithFormat:#" journalref.toproj contains[cd]%#",self.projectdb];
[journalfetchRequest setPredicate:journalpredicate];
NSSortDescriptor *journalsortDescriptor = [[NSSortDescriptor alloc]initWithKey:#"surname" ascending:YES];
NSArray *journalsortDescriptors = [[NSArray alloc]initWithObjects:journalsortDescriptor, nil];
[journalfetchRequest setSortDescriptors:journalsortDescriptors];
self.JournalrefArray = [[journalmanagedObjectContext executeFetchRequest:journalfetchRequest error:nil] mutableCopy];
[self.tableView reloadData];}
(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
#warning Potentially incomplete method implementation.
// Return the number of sections.
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
#warning Incomplete method implementation.
// Return the number of rows in the section.
return (self.BookrefArray.count + self.journalrefArray.count);
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cells";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
Journal *myjournal =[self.journalrefArray objectAtIndex:indexPath.row];
[cell.detailTextLabel setText:[myjournal valueForKey:#"journalname"]];
[cell.textLabel setText:[NSString stringWithFormat:#"%#, %#",[myjournal valueForKey:#"surname"],[myjournal valueForKey:#"firstname"]]];
Book *mybook =[self.BookrefArray objectAtIndex:indexPath.row];
// Configure the cell...
[cell.detailTextLabel setText:[mybook valueForKey:#"bookTitle"]];
[cell.textLabel setText:[NSString stringWithFormat:#"%#, %#",[mybook valueForKey:#"authorSurname"],[mybook valueForKey:#"authorOthernames"]]];
return cell;
}
You have this error because you try to access of an element of your array that is not exist.
In fact you says that your table has "table1.count + table2.count" elements and for each cell you try to get an element in your 2 tables with the current row.
For example, if table1 has 2 items and table2 has 5 items
, your tableView will have 7 rows and "cellForRowAtIndexPath" will be called 7 times. So for index 3 you will obtains this error because your table1 has only 2 items.
To solve the problem, you should get a book OR a journal in function of this row.
For example, you can try anything like this :
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cells";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
if (indexPath.row < self.BookrefArray.count)
{
Book *mybook =[self.BookrefArray objectAtIndex:indexPath.row];
// Configure your cell with a book
}
else
{
Journal *myjournal =[self.journalrefArray objectAtIndex:indexPath.row - self.BookrefArray.count];
// Configure your cell with a journal
}
return cell;
}
You can also change the order to display journals before books.
Answer :
You need to differentiate Book and Journal in -cellForRowAtIndexPath.
Explanation :
Your call for tableview's -cellForRowAtIndexPath will be dependent upon the number you're returning from tableview's -numberOfRowsInSection method.
So, for example, you've 3 objects in BookrefArray and 2 objects in journalrefArray, your tableview's -numberOfRowsInSection method will return 5 which means -cellForRowAtIndexPath will be called for 5 times.
Let's go through this line :
Journal *myjournal =[self.journalrefArray objectAtIndex:indexPath.row];
Here, it'll get indexPath.row = 5 for one case, and your journalrefArray contains only 2 objects. So, you're getting "index .. beyond bounds" error.
Update :
You can simply merge both the arrays into one.
[documentsArray addObjectsFromArray:self.BookrefArray];
[documentsArray addObjectsFromArray:self.journalrefArray];
and then in -cellForRowAtIndexPath, you can do something like this :
id document = [documentsArray objectAtIndex:indexPath.row];
if ([document isKindOfClass:Book])
{
Book *mybook = (Book *)document;
// Do something with mybook.
}
else
{
Journal *myjournal = (Journal *)document;
// Do something with myjournal.
}

Load data into tableview form cells

I have a program where a UITableView contains custom cells loaded from nibs. These cells have textfields and a UIImage. I've been passing the information they contain to a custom class and encoding/decoding the class for data persistence. When I want to load the data, I put the information from the class into the cell. This works fine for 1 cell, but not for more than one. I've checked, and the classes are being written to file correctly.
This is my retrieval method:
//Fills an array if the file exists, otherwise returns nil
- (NSMutableArray*) findFile: (NSString *) add
{
if ([[NSFileManager defaultManager] fileExistsAtPath:[self saveFilePath:add]])
{
NSString *temp = [add stringByAppendingString:#"dat"];
namesIndexer = [[NSMutableArray alloc] initWithContentsOfFile:[self saveFilePath:temp]];
if (namesIndexer == nil) return nil;
NSMutableArray *thing = [NSMutableArray new];
for (NSString *place in namesIndexer)
{
temp = [add stringByAppendingString:place];
PTextHolder *p = [NSKeyedUnarchiver unarchiveObjectWithFile:[self saveFilePath:temp]];
[thing addObject:p];
}
return thing;
}
else
{
return nil;
}
}
Note that this is in a different class, and it calls the method from the holder.
//Returns a cell to be used at a row, populates it from the holder object
- (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *personCellId = #"personID";
UINib *nib = [UINib nibWithNibName:#"PersonCell" bundle:nil];
[tableView registerNib:nib forCellReuseIdentifier:personCellId];
PersonCell *cell = [tableView dequeueReusableCellWithIdentifier:personCellId];
cell.owner = tableView;
if (mineTable == nil) mineTable = tableView;
cell.delegated = formDataStorage;
[formDataStorage putWhatShouldBeInThisCellForThisRowInIt:cell:(int*)indexPath.row];
cell.currentRow = [[NSNumber alloc] initWithInt:indexPath.row];
return cell;
}
Here's the method it calls:
- (void) putWhatShouldBeInThisCellForThisRowInIt: (PersonCell *) someCell: (int *) someRow
{
if ((NSUInteger) someRow >= cake.count)
{
NSLog(#"The cake has been undercooked");
return;
}
PTextHolder *temp = [cake objectAtIndex:(NSUInteger) someRow];
someCell.firstName.text = temp.first;
someCell.lastName.text = temp.last;
someCell.middleName.text = temp.middle;
someCell.suffixName.text = temp.suffix;
someCell.email.text = temp.email;
someCell.theSignature.image = temp.sig;
}
Anything look wrong here/would cause only one cell to be loaded?
I would check first the number of items in the array with
[array count]
, if the number of items is equal to 1, then the problem is as you guessed with the encoding/decoding.
If not, your code is right and the problem is with your code to load the cells.
By the way, why dont you store your array of "cellInfoClass" directly using:
[NSKeyedArchiver archiveRootObject:array toFile:filePath]
and retrieve directly the array.
I guess you already added the encoding/coding code to your class, if not is like that:
/**
* Returns an object initialized from data in a given unarchiver. (required)
*
* #param decoder: An unarchiver object.
*/
- (id)initWithCoder:(NSCoder *)coder {
if (self = [super init]) {
// If parent class also adopts NSCoding, replace [super init]
// with [super initWithCoder:decoder] to properly initialize.
[self setName:[coder decodeObjectForKey:#"name"]];
[self setId:[coder decodeIntForKey:#"id"]];
[self setDomain:[coder decodeObjectForKey:#"domain"]];
}
return self;
}
/**
* Encodes the receiver using a given archiver. (required)
* #param coder: An archiver object.
*/
- (void)encodeWithCoder:(NSCoder *)coder{
// If parent class also adopts NSCoding, include a call to
// [super encodeWithCoder:encoder] as the first statement.
[coder encodeObject:name forKey:#"name"];
[coder encodeInt:id forKey:#"id"];
[coder encodeObject:domain forKey:#"domain"];
}

How to Fix EXC_BAD_ACCESS on NSArray Property?

This is yet another EXC_BAD_ACCESS question. Although I've done my homework and am certain that I am not over-releasing my NSArray.
So here is a snippet of my code:
tableData = [NSDictionary dictionaryWithJSONString:JSONstring error:&error];
//Collect Information from JSON String into Dictionary. Value returns a mutli
dimensional NSDictionary. Eg: { value => { value => "null"}, etc }
NSMutableArray *t_info = [[NSMutableArray alloc] init];
for(id theKey in tableData)
{
NSDictionary *get = [tableData objectForKey:theKey];
[t_info addObject:get];
[get release];
} // converting into an NSArray for use in a UITableView
NSLog(#"%#", t_info);
//This returns an Array with the NSDictionary's as an Object in each row. Returns fine
if (tvc == nil)
{
tvc = [[tableViewController alloc] init]; //Create Table Controller
tableView.delegate = tvc;
tableView.dataSource = tvc;
tvc.tableView = self.tableView;
tvc.tableData = t_info; //pass our data to the tvc class
[tvc.tableView reloadData];
}
...
Now in my TableViewController Class:
#implementation tableViewController
#synthesize tableData, tableView;
- (NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [tableData count]; //Returns X Amount Fine.
}
- (UITableViewCell *)tableView:(UITableView *)the_tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
NSString *MyIdentifier = [NSString stringWithFormat:#"MyIdentifier"];
UITableViewCell *cell = [the_tableView dequeueReusableCellWithIdentifier:MyIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:MyIdentifier] autorelease];
}
NSLog(#"%#", tableData); //** CRASHES!!**
cell.textLabel.text = #"This is a test";
return cell;
}
If I were to comment out that NSLog, it'll work fine and return "this is a test" on each table row.
This one has really got me stumped, all the articles I have around about this problem is generally related to retain/memory issues.
Also, another important point.
If I were to pass through my original (NSDictionary) tableData from my first class code and run the same script in my tableViewController - I can NSLog the object perfectly fine.
The only time you need to release an object is if you have explicitly allocated it by way of new, alloc, or copy.
NSMutableArray *t_info = [[NSMutableArray alloc] init];
for(id theKey in tableData)
{
NSDictionary *get = [tableData objectForKey:theKey];
[t_info addObject:get];
[get release];
}
You shouldn't be releasing get here. By doing this, you're releasing the reference that the tableData dictionary is holding onto, which is bad. My guess is that this is what is causing the problem that you're encountering.
If I'm not mistaken, the reason why [tableData count] returns the expected value is because the array is still holding onto the references that have been released.

UITAbleView Giving Error

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
//NSLog(#"Array: %#",rows);
return [rows count];// AT THIS LINE
}
Program received signal: “EXC_BAD_ACCESS”
THANKS FOR THE REPLY
Actually I have attached it to the WebPage By NSUrl where I have made a PHP array and I have created a NSLOG where I am getting the Values in the array form but When It exceute the line return [rows count];. It gives error when I am writting statically return 2; then it execute. I am explaining to you what I am doing. I am initialising the NIb with
Name tableViewController=[[JsonTestViewController alloc] initWithNibName:#"JsonTestViewController" bundle:nil];
In JsonTestViewController.m
I have this code:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
//NSLog(#"Array: %#",rows);
return [rows count];
}
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
// Configure the cell.
NSDictionary *dict = [rows objectAtIndex: indexPath.row];
NSString *strlb1=[dict objectForKey:#"block"];
NSString *strlb2=[dict objectForKey:#"name"];
strlb1=[strlb1 stringByAppendingString:#" , "];
strlb1=[strlb1 stringByAppendingString:strlb2];
NSString *str1=#"FPS : ";
NSString *str2=[dict objectForKey:#"p_hours"];
NSString *strpinf;
if([str2 isEqualToString:#"FP"])
{
strpinf=#"Free Parking";
}
else if([str2 isEqualToString:#"12"])
{
strpinf=#"2 hours";
}
else if([str2 isEqualToString:#"14"])
{
strpinf=#"4 hours";
}
else if([str2 isEqualToString:#"MP"])
{
strpinf=#"Metered Parking";
}
str1=[str1 stringByAppendingString:strpinf];
cell.textLabel.text =strlb1;
cell.detailTextLabel.text = str1;
return cell;
}
- (void)viewDidLoad {
[super viewDidLoad];
NSURL *url = [NSURL URLWithString:#"SITE URL"];
NSString *jsonreturn = [[NSString alloc] initWithContentsOfURL:url];
NSData *jsonData = [jsonreturn dataUsingEncoding:NSUTF32BigEndianStringEncoding];
NSError *error = nil;
NSDictionary * dict = [[CJSONDeserializer deserializer] deserializeAsDictionary:jsonData error:&error];
if (dict)
{
rows = [dict objectForKey:#"users"];
}
NSLog(#"Array: %#",rows);
[jsonreturn release];
}
- (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 {
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)dealloc {
[super dealloc];
}
#end
can you give more info? This can be anything, but most likely, rows is pointing to memory where a valid array used to be. How did you create the rows array?
For example, your rows array or dictionary not longer pointing to valid memory if you created the rows array as an autoreleased object through a factory method in another method.
Here's another question that's pretty close to what you're describing:
EXC_BAD_ACCESS signal received
EDIT:
So looking at the code you provided, with these lines there are some possibilities:
NSDictionary * dict = [[CJSONDeserializer deserializer] deserializeAsDictionary:jsonData error:&error];
if (dict) { rows = [dict objectForKey:#"users"]; }
the deserializeAsDictionary method can return either an autoreleased dictionary or NULL. so one possibility is that rows = NULL. when you try [rows count], your program will crash. Check and see what's in error, might give you some clues.
This will cause an error even when you explicitly return 2 for numberOfRowsInSection: because in cellForRowAtIndexPath:, you're still trying to access rows, even if it could possibly be NULL.
the other possibility lies in how you've defined rows. I'm guessing it's a property in your class. But where you have rows=[dict objectForKey:#"users"];, rows can point to nothing after the method's finished. Rows will still have the address of where [dict objectForKey:] was, but after the scope of the method, dict may be gone and all the data that comes with it.
NSDictionary * dict = [[CJSONDeserializer deserializer] deserializeAsDictionary:jsonData error:&error];
under the KVC guidelines, you should expect dict to autorelease after the end of method.
and another possibility is, since i don't know the specifics of the JSON class you're using, is that when you release jsonreturn, you're also dealloc'ing all the data associated with it. So in effect, rows is pointing to nothing.
case in point, the error seems to be rooted in how you're setting/retaining/accessing rows.
try using the Build->Build&Analyze in xcode. it might give you some more hints. or throw in a bunch of NSLog(#"%d",[rows count]); all over. also try using the debugger. it'll give you a trace of method calls that lead up to [rows count] faulting.