How to change the iVar of another class - iphone

This is the code. It is pretty straight forward. I made two classes one is returning the error and hydrate the iVar of another class (TheView) and show it to the User. however I cant figure it out why the View return Null at all time. Thanks is advance guys.
#interface AccountControllerModel : NSObject {
NSString *anError;
}
#property (nonatomic, retain) NSString *anError;
AccountControllerModel.m
#synthesize anError;
- (void)uploadFailed:(ASIHTTPRequest *)theRequest{
RegistrationViewController *regoVC = [[RegistrationViewController alloc] init];
[regoVC manageTheError:#"THIS IS AN ERROR"];
[regoVC release]; regoVC = nil;
}
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#interface RegistrationViewController : UIViewController {
NSMutableString *test;
}
#property (nonatomic, assign) NSMutableString *test;
#synthesize test;
-(void)viewDidLoad {
test = [[NSMutableString alloc] init];
}
-(void)manageTheError:(NSString *)theError{
self.test = [NSMutableString stringWithFormat:#"%#",theError];
resultOfRegistration.text = [NSString stringWithFormat:#"%#",self.test];
NSLog(#"test is %#",self.resultOfRegistration.text); //It comes back Null
}

Alex is right, some clarification on what's not working would help but by looking through I may have found your error. [[NSNotificationCenter defaultCenter] postNotificationName:#"Blah" object:self], you have object set to nil which could be your issue with the notification.

There are a number of problems with your code.
#property (nonatomic, assign) NSMutableString *test;
Two things here, one, exposing a NSMutable* object in a property is never a good idea, two you should 'copy' value objects, especially because this is how you're treating it in your code. Make this #property (nonatomic, copy) NSString *test;
regoVC.test = [NSMutableString stringWithString:self.anError];
You're assigning an autoreleased object to an assign property, this is a leak, the change above will fix that.
NSLog(#"test is %#",test); // It is perfect as you expect
test isn't in scope here, but I'd assume that was supposed to be regoVC.test, these other changes should remedy the situation.

Related

NSManagedObject exception “this class is not key value coding-compliant” and crashes the app in ios 6 but works for ios 5

I having an issue where my application crashes with the following exception:
ABC[1936:c07] * Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<_NSObjectID_48_0 0xb63e310> valueForUndefinedKey:]: this class is not key value coding-compliant for the key id.'
The strange issue with this exception is that it does not occur when using iOS5. Please see the code where the exception takes place below:
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
if ((self.sectionInfoArray == nil) ||
([self.sectionInfoArray count] != [self numberOfSectionsInTableView:self.tableView]))
{
NSMutableArray *infoArray = [[NSMutableArray alloc] init];
for (Tour *tour in self.tours)
{
SectionInfo *sectionInfo = [[SectionInfo alloc] init];
sectionInfo.tour = tour;
sectionInfo.open = NO;
NSLog(#"Tour Details Count %#", [[tour tourDetails] objectAtIndex:0]);
NSNumber *defaultRowHeight = [NSNumber numberWithInteger:DEFAULT_ROW_HEIGHT];
NSInteger countOfQuotations = [[sectionInfo.tour tourDetails] count];
for (NSInteger i = 0; i < countOfQuotations; i++)
{
[sectionInfo insertObject:defaultRowHeight inRowHeightsAtIndex:i];
}
[infoArray addObject:sectionInfo];
}
self.sectionInfoArray = infoArray;
}
}
Would this exception be being caused because due to me having a Fetched Property defined within the class Tour that gets an array of TourDetail classes. Please see the implementation code for both classes below:
#import "Tour.h"
#import "TourDetail.h"
#implementation Tour
#dynamic background_url;
#dynamic id;
#dynamic summary;
#dynamic title;
#dynamic tour_tourdetail;
#dynamic tourDetails;
#end
#import "TourDetail.h"
#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>
#class TourDetail;
#interface Tour : NSManagedObject
#property (nonatomic, retain) NSString * background_url;
#property (nonatomic, retain) NSNumber * id;
#property (nonatomic, retain) NSString * summary;
#property (nonatomic, retain) NSString * title;
#property (nonatomic, retain) TourDetail *tour_tourdetail;
#property (nonatomic, retain) NSArray *tourDetails;
#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>
#interface TourDetail : NSManagedObject
#property (nonatomic, retain) NSString * audiofile;
#property (nonatomic, retain) NSString * detail;
#property (nonatomic, retain) NSNumber * id;
#property (nonatomic, retain) NSNumber * lattitude;
#property (nonatomic, retain) NSNumber * longitude;
#property (nonatomic, retain) NSString * title;
#property (nonatomic, retain) NSNumber * tour_id;
#property (nonatomic, retain) NSManagedObject *tourdetail_tour;
#end
#implementation TourDetail
#dynamic audiofile;
#dynamic detail;
#dynamic id;
#dynamic lattitude;
#dynamic longitude;
#dynamic title;
#dynamic tour_id;
#dynamic tourdetail_tour;
#end
Any help with this issue would be greatly appreciated. As I am at a loss as to how I can fix this.
Thanks,
Michael
UPDATE:
When I remove the Fetched Property the exception does not occur with iOS6. Please see the predicate I have configured below:
Fetched Property tourDetails Predicate tour_id == $FETCH_SOURCE.id
Can you see anything I doing wrong with the setup of this predicate ? My goal is to use this so as I can return an Array of TourDetail objects for each tour_id that mathces the id column inside the Tour table.
UPDATE:
I have been able to diagnose that the exception is being thrown because of the Predicate as when I call both tables separately there is no exception raised. Can you see any issue with the predicate that I have created ?
Please see code below showing how I am retrieving the objects from the Core Data DB:
- (void)viewDidLoad
{
[super viewDidLoad];
[DrivingToursContent setupStaticData];
self.tableView.sectionHeaderHeight = HEADER_HEIGHT;
_openSectionIndex = NSNotFound;
self.tableView.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:#"custombackground.ptoung"]];
self.managedObjectContext = [[BaseCoreDataController sharedInstance] newManagedObjectContext];
[self loadRecordsFromCoreData];
[self loadRecordsFromCoreDataForTourDetail];
NSLog(#"Tour Detail array count: %d", [self.toursTest count]);
// Do any additional setup after loading the view.
}
- (void)loadRecordsFromCoreData {
[self.managedObjectContext performBlockAndWait:^{
[self.managedObjectContext reset];
NSError *error = nil;
NSFetchRequest *request = [[NSFetchRequest alloc] initWithEntityName:NSStringFromClass([Tour class])];
[request setSortDescriptors:[NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:#"id" ascending:YES]]];
self.tours = [self.managedObjectContext executeFetchRequest:request error:&error];
}];
}
UPDATE:
The root of the problem is definitely coming from the Predicate I have defined for the Fetched property but can you advise how I should write the predicate to link between the 2 tables. As when I write the predicate tour_id == 0 and directly reference an id I know exists the fetched property works correctly. But when I use $FETCH_SOURCE.id the key value coding exception is thrown. What property do you use to reference the the table you wish to link to ?
Really appreciate all your help with this.
Thanks,
Michael
without seeing your code, you are calling a method on a class that was deprecated in iOS6, hence the crash.
There's nothing in the code you've posted for viewWillAppear that touches Core Data in any obvious way at all, which makes it kind of hard to guess what's going on. Some of those objects might be managed objects, but who knows which ones or how you created them?
However the error message does provide a huge clue:
[<_NSObjectID_48_0 0xb63e310> valueForUndefinedKey:]: this class is not key value coding-compliant for the key id.
The fact that this mentions _NSObjectID_48_0 indicates that at some point you're using NSManagedObjectID instances when you're expecting NSManagedObject instances. NSManagedObjectID does not have a property named id, no matter what the entity looks like, so asking one for its id will produce a "not key value coding compliant" error.
As for why this would be happening, it's still impossible to say, since you haven't posted any code that gives any clues about how you are using Core Data.
It might be something to do with the predicate:
tour_id == $FETCH_SOURCE.id
If you constructed a fetch so that $FETCH_SOURCE is an NSManagedObjectID, this would be a problem. Maybe (and I can only guess) you're using it while asking for a result type of NSManagedObjectIDResultType.
#property (nonatomic, retain) NSNumber * id;
Isn't id a reserved word in Objective-C? Have you tried renaming this property to something else, to see if that is causing any conflicts?
Without digging into your code, NSFetchRequest can set the returned result type,
e.g., NSManagedObjectIDResultType or NSManagedObjectResultType.
NSManagedObjectResultType is wanted, but NSManagedObjectIDResultType is returned.
I have the same issue when I use MagicalRecord, but have no issue when use Xcode generate CoreData source code.

iPhone - Error setting up block that takes an array

I am writing as a follow up to this question I asked yesterday, but I have not heard back from the original responder. I would be happy to wait, but I have a small time limit. He helped me tremendously with my NSURLConnection code, and I understand perfectly how this is working, but I can't seem to get the syntax correct.
I can't get handler:^ to be recognized and this line:
[self loadImageArray:urlArray handler:^(NSMutableArray *)imageArray
and it needs to take an array (imageArray from loadImageArray) that is populated with images.
- (void)loadImageArray:(NSArray *)urls handler:(void(^)( handler)
This should populate an array (imageArray) asynchronously from the server.
How do I setup the block calls correctly? I have read about blocks on a few sites, but none of the suggestions have helped.
Again, I have asked the original responder, but have not heard back.
I hope that edit helps. Thank you!
Here is my .h
#interface OBNSURLViewController : UIViewController
{
NSArray *jsonArray;
NSMutableData *theJsonData;
IBOutlet UIView *mainView;
__weak IBOutlet UIImageView *mainImage;
__weak IBOutlet UILabel *mainLabel;
}
#property (nonatomic, strong) NSData *serverData;
#property (strong, nonatomic) IBOutlet UIScrollView *mainScroll;
#property (nonatomic, retain) NSMutableArray *imageArray;
#property (nonatomic, retain) NSMutableArray *urlArray;
#property (nonatomic, retain) UIImage *imageData;
#end
Here is the relavent code I am stuck on:
- (void)parseJSONAndGetImages:(NSData *)data
{
//initialize urlArray
urlArray = [[NSMutableArray alloc]init];
//parse JSON and load into jsonArray
jsonArray = [NSJSONSerialization JSONObjectWithData:theJsonData options:nil error:nil];
//assertion?
assert([jsonArray isKindOfClass:[NSArray class]]);
//Make into one liner with KVC.... Find out what KVC is
//Code to load url's into array goes here....
//load the images into scrollview after fetching from server
[self loadImageArray:urlArray handler:^(NSMutableArray *)imageArray //Here is a big problem area
{
//work goes here....
}];
}
- (void)loadImageArray:(NSArray *)urls handler:(void(^)( handler)//This does not want to work either. I am stuck on handler???
{ dispatch_async(0, ^{
//imageArray = [NSMutableArray array];
for (int y = 0; y < urlArray.count; y++)
{
//stuff goes here.....a
});
dispatch_async(dispath_get_main_queue(),^{
handler(imageArray);
});
}
As I'm reading this, the method syntax should look like the following. If the handler block takes an argument, you need to declare that it does.
- (void)loadImageArray:(NSArray *)urls handler:(void (^)(NSMutableArray *imageArray))handler
{
NSMutableArray *imageArray = [NSMutableArray array];
// Do something with the urls array to fill in entries in imageArray...
handler(imageArray);
}
You would call the method like this:
NSArray *urls = // filled in somewhere else...
[myObject loadImageArray:urls handler:^(NSArray *imageArray) {
NSLog(#"%#", imageArray);
}];

objective-c beginner: getter setter prob and EXC_BAD_ACCESS error

Iam getting an EXC_BAD_ACCESS all the time and I cannot figure out why...
Simple task:
The Parser Class pases XML with touchXML in an NSMutableArray called listArray.
In the Method grabCountry I can access the listArray and listArray.count works well.
Now I need the listArray.count in another Class the MasterViewController.
But Im getting an EXC_BAD_ACCESS error all the time.
Please help!
Here is the code snipplet:
Parser.h
#import <Foundation/Foundation.h>
#interface Parser : NSObject
#property (strong, retain) NSMutableArray *listArray;
#property (strong, retain) NSURL *url;
-(void) grabCountry:(NSString *)xmlPath;
#end
Parser.m
#import "Parser.h"
#import "TouchXML.h"
#implementation Parser
#synthesize listArray;
#synthesize url;
-(void) grabCountry:(NSString *)xmlPath {
// Initialize the List MutableArray that we declared in the header
listArray = [[NSMutableArray alloc] init];
// Convert the supplied URL string into a usable URL object
url = [NSURL URLWithString: xmlPath];
//XML stuff deleted
// Add the blogItem to the global blogEntries Array so that the view can access it.
[listArray addObject:[xmlItem copy]];
//works fine
NSLog(#"Amount: %i",listArray.count);
}
#end
MasterViewController.h
#import <UIKit/UIKit.h>
#import "AppDelegate.h"
#import "TouchXML.h"
#import "Parser.h"
#class Parser;
#interface MasterViewController : UITableViewController{
Parser *theParser;
}
#end
MasterViewControlelr.m
- (void)viewDidLoad
{
NSString *xmlPath = #"http://url/to/xml.xml";
theParser = [[Parser alloc] init];
//Starts the parser
[theParser grabCountry:xmlPath];
//Here I want to access the Array count, but getting an BAD ACCESS error
NSLog(#"Amount %#",[theParser.listArray count]);
[super viewDidLoad];
}
Can anyone explain me what the problem here is?
Thanks!
Internally, each #property has a corresponding instance variable.
In your -grabCountry method, you are directly accessing the instance variable in the statement listArray = [[NSMutableArray alloc] init]; (same with url = [NSURL URLWithString: xmlPath];), instead of the #property's setter method, causing the NSMutableArray that you alloc-init'd to not be retained by the property. To invoke the #property's setter method, you should call
NSMutableArray *temp = [[NSMutableArray alloc] init];
self.listArray = temp; // or [self setListArray:temp];
[temp release];
If you want to have Xcode show an error when you are directly accessing the instance variable of an #property, you can have #synthesize listArray = _listArray, which changes the name of the instance variable to _listArray.
Generally, if there is an alloc-init, there must be a corresponding release (except if using Automatic Reference Counting).
Also, in the [listArray addObject:[xmlItem copy]]; statement, the call to copy is not needed, as NSArrays retain every object that is added to them. Calling copy also increases the retain count, which is another leak. Instead, you should just have [self.listArray addObject:xmlItem];
You are getting EXC_BAD_ACCESS because in NSLog(#"Amount %#",[theParser.listArray count]);, you are using %# format specifier, which is for NSStrings. You want to print the array's count, an integer, so you should be using %d or %i.

NSString "invalid summary"

Ok, I have read a lot of posts and resources about this but I am STILL having the same issue. I have a few NSString variables that I need to be class-wide variables used in multiple places throughout the class. I have tried many combinations of settings. First of all, I do have the strings declared in the interface like so:
#interface iCodeViewController : UIViewController <NSXMLParserDelegate> {
NSString *myString;
}
I have also added the property as follows (I have tried with and without the property and synthesizing)
#property (readwrite, retain) NSString *myString;
I have also tried, (nonatomic, retain), (nonatomic, copy), (readwrite, copy).
Then in the .m file:
#synthesize myString;
I have tried:
self.myString = #"whatever";
myString = #"whatever";
I have also tried with and without allocating memory to it by:
myString = [[NSString alloc] init];
What am I missing??
After I have 'supposedly' set the string variable in one method, I try to check it in another with if ([myString isEqualToString:#"blah blah"]) and when I put in a breakpoint and hover over myString it is always showing 'invalid summary.
Thanks!
use below
#property (nonatomic, retain) NSString *myString;
self.myString = [NSString stringWithString:#"whatever"];
for more read the SO post
Invalid Summary in NSString assignment
Can you place the class code here? The way you are handling your myString is perfectly fine.
One possibility I can think of is that you are forgetting to return self from the init method.
There could be other possible memory related mess some where in your code.
I was able to reproduce the invalid summary by initializing an NSMutableString to size 100 and only appending to it. I found the problem went away when I called
[mutableString setString:#""];
prior to
[mutableString appendString:string];

Need to store array of an array of class objects in View Controller

An iPhone question for you guys! I have an NSURLConnection that downloads XML from a server and processes it into an array which is a part of another array. I have no way of knowing how many objects I will need, so I cannot allocate an NSArray beforehand. My question is:
Would it be better to create the parent array as an NSArray at the class level and allocate it after I store the data in a temporary NSMutableArray or just make the NSMutableArray at class level? It is worth noting that I do not need to modify the array other than to release it at the end of the program run.
I don't think it really matters.
I'm reading the Beginning iPhone 3 Development book at the moment, and usually loading the data is done like this:
You'd have an NSArray property :
#interface
{
...
NSArray *listOfObjects;
...
}
#property (nonatomic, retain) NSArray *listObObjects;
...
Then you create an NSMutableArray, load your data and set the property:
NSMutableArray *array = [[NSMutableArray alloc] init]; // ?
// load the XML into array here
...
self.listOfObjects = array;
[array release];
listOfObjects would then be treated as an NSArray (immutable) although it actually would be an NSMutableArray.
I think what you probably want to do is create some Classes that match what you are representing in your xml. For example if you xml looks something like this:
<peopleList>
<person>
<name>Joe</name>
<possession>Shovel</possession>
</person>
<person>
<name>Sam</name>
<possession>Shovel</possession>
<possession>Fork</possession>
<possession>Backpack</possession>
</person>
</peopleList>
You should have a PeopleList Class and a Person Class. An object instantiated from the PeopleList Class has your first array that contains one or more Person objects. The Person objects, in turn, also have arrays to hold the possesions (which in this case are strings - although if needed they could be Possesion objects) In this case, to help the example the Person Class also has another property: 'name' which is also a String.
For example:
#interface PeopleList {
NSMutableArray *persons; // An array to store the Person objects
}
#property (nonatomic, retain) NSMutableArray *persons;
#end
#interface Person {
NSString *name;
NSMutableArray *possesions; //An array to store this Person's possesion strings
}
#property (nonatomic, retain) NSString *name;
#property (nonatomic, retain) NSMutableArray *possesions;
#end
In the init method's of these objects you will have to alloc/init the arrays so they will be ready to receive objects. And because I alloc'd them, my class is responsible for the release.
#implementation PeopleList
-(id) init {
if (self = [super init]) {
persons = [[NSMutableArray alloc] init];
}
}
-(void) dealloc {
[persons release];
[super dealloc];
}
#end
#implementation PeopleList
-(id) init {
if (self = [super init]) {
possesions = [[NSMutableArray alloc] init];
}
}
-(void) dealloc {
[possesions release];
[super dealloc];
}
#end
Now that this is done, you can set up your data structure of cascading array's.
As you are parsing the XML when you come across a PeopleList Tag do a:
currentPeopleList = [[PeopleList alloc] init];
and when you come across a Person tage do a:
currentPerson = [[Person alloc] init];
[peopleList.persons addObject: person];
a possesion:
[currentPerson.possesion addObject: contentsOfCurrentElement];
or name:
currentPerson.name = contentsOfCurrentElement;
But to answer your more specific question, I not store the data in a temporary NSArray and then copy that into a NSMutableArray. There is almost no performance gain by doing so, and you will burn cpu cycles and memory doing the copy.