initWithDictionary - cocoa

I have the problem that I can't get the Data from one of my classes to the other...
To do this I created this method in the class I am initializing (angebotPage):
- (id) initWithDictionary:(NSDictionary *)dictionary
{
self = [super init];
if (self) {
dict = [dictionary retain];
}
return self;
}
The call from the other class looks like this:
angebotPage *page;
angebotPDF = [[PDFDocument alloc] init];
page = [[angebotPage alloc] initWithDictionary:dictionary];
The Error I get is EXC_BAD_ACCESS in the line where I do:
dict = [dictionary retain];
But why? I need to retain it cause I will use it for the next program steps.. But without retaining I can't use it (EXC_BAD_ACCESS comes elsewhere...)

I recommend that you use a property for dict instead.
#property (retain) NSDictionary *dict;
And then assign the dictionary with self.dict = dictionary. This is assuming all the objects in dictionary are correctly retained in the first place. Try with an empty dictionary if in doubt.

Related

NSMutableDictionary entry corrupted after departing from the method where entry was added

I use setObject:forKey: to add an object of type Rresource to a NSMutableDictionary named: resourceLib.
Then I immediately look at what's actually in the dictionary and it's OK.
When I try to look at it again in another object's method, the proper key is present but a reference to a string property "url" cases a list of error messages including:
2016-09-28 11:32:42.636 testa[760:16697] -[__NSCFString url]: unrecognized selector sent to instance 0x600000456350
Rresource object is defined as:
#interface Rresource : NSObject
#property (nonatomic,strong) NSString* url;
#property (nonatomic,strong)NSMutableArray* resourceNotesArray;
#property(nonatomic,strong)NSString* name;
#property(nonatomic,strong)NSString* resourceUniqueID;
#property(nonatomic)BOOL isResourceDirty;
This method in a ViewController adds the Rresource to the NSMutableDictionary
-(void)saveResource
{
Rresource* resource = self.currentResource;
Rresource* temp;
if (resource)
{
if ( resource.isResourceDirty)
{
[self.model.resourceLib setObject:resource forKey:resource.resourceUniqueID];
temp = [self.model.resourceLib objectForKey:resource.resourceUniqueID];
}
}
}
Resource and temp contain identical info showing the info was added correctly.
In model's method the following causes the error message described above.
for (Rresource* resource in self.resourceLib)
{
NSString* string = resource.url;
}
where model contains:
#property(nonatomic,strong)NSMutableDictionary* resourceLib;
and :
#implementation Model
- (instancetype)init
{
self = [super init];
if (self)
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);
self.path = [[paths objectAtIndex:0] stringByAppendingString:#"/Application Support/E2"];
BOOL exists = [[NSFileManager defaultManager] createDirectoryAtPath:self.path withIntermediateDirectories:NO attributes:nil error:nil];
if (!exists)
{
[[NSFileManager defaultManager] createDirectoryAtPath:self.path withIntermediateDirectories:NO attributes:nil error:nil];
}
self.resourceLibPath = [NSString pathWithComponents:#[self.path,#"resources"]];
self.resourceLib = [[NSMutableDictionary alloc]init];
self.noteLibPath = [NSString pathWithComponents:#[self.path, #"notes"]];
self.noteLib = [[NSMutableDictionary alloc]init];
}
return self;
I have found this question difficult to ask clearly even after spending several hours formulating it. I apologize.
I've tried pretty much everything for about a week. I'm stumped.
Any ideas?
Thanks
According to this entry on Enumeration, when you iterate over a dictionary using the fast enumeration syntax, you're iterating over its keys. In the above code sample you're assuming the enumeration happens over its values. What you're effectively doing is casting an NSString object as an Rresource, and sending it a selector only an actual Rresource object can respond to.
This should fix the loop:
for (NSString* key in self.resourceLib)
{
NSString* string = [self.resourceLib objectForKey:key].url;
}

Populating NSOutlineView with bindings - KVO adding of items

I've created a small test project to play with NSOutlineView before using it in one of my projects. I'm successful in displaying a list of items with children using a NSTreeController who's content is bound to an Array.
Now while I created this object it took me ages to realize that my array contents would only show up if i created them in my init method:
- (id)init
{
self = [super init];
if (self) {
results = [NSMutableArray new];
NSMutableArray *collection = [[NSMutableArray alloc] init];
// Insert code here to initialize your application
NSMutableDictionary *aDict = [[NSMutableDictionary alloc] init];
[aDict setValue:#"Activities" forKey:#"name"];
NSMutableArray *anArray = [NSMutableArray new];
for (int i; i<=3 ; i++) {
NSMutableDictionary *dict = [NSMutableDictionary new];
[dict setValue:[NSString stringWithFormat:#"Activity %d", i] forKeyPath:#"name"];
[anArray addObject:dict];
}
results = collection;
}
return self;
}
If I put the same code in applicationDidFinishLaunching it wouldn't show the items.
I'm facing the same issue now when trying to add items to the view. My understanding of using the NSTreeController is that it handles the content similar to what NSArrayController does for a NSTableView (OutlineView being a subclass and all). However, whenever I use a KV compliant method to add items to the array the items do not show up in my view.
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
NSMutableDictionary *cDict = [[NSMutableDictionary alloc] init];
[cDict setValue:#"Calls" forKey:#"name"];
[results addObject:cDict];
[outlineView reloadData];
}
I've also tried calling reloadData on the outlineview after adding an object, but that doesn't seem to be called. What am I missing?
Here's a link to my project: https://dl.dropboxusercontent.com/u/5057512/Outline.zip
After finding this answer:
Correct way to get rearrangeObjects sent to an NSTreeController after changes to nodes in the tree?
It turns out that NSTreeController reacts to performSelector:#selector(rearrangeObjects) withObject:afterDelay:
and calling this after adding the objects lets the new objects appear.

Nested NSCollection View

I am trying to create a nested collection view. First I did for one level.
Created a data model class with String header. In app delegate created an array sectionTitle. Now in the nib, I added collection view & array controller and did all the bindings following this guide. Next in awakeFromNib I populated some random data
- (void)awakeFromNib {
int idx = 0;
NSMutableArray *sectionTitle = [[NSMutableArray alloc] init];
while (idx < 1) {
HeaderModel *header = [[HeaderModel alloc] init];
[header setHeader:[NSString stringWithFormat:#"Section %d", idx]];
[sectionTitle addObject:header];
idx++;
}
[self setHeaderData:sectionTitle];
}
Running it will give me 4 sections. I want to achieve similar layout as this. Section title, under it another collection of items. The answer given there only hints at using Nested collection view.
So I added another collection view in the first view prototype. Then I followed the same approach what I did for the first view(with different data model and array).
- (void)awakeFromNib {
int idx = 0;
NSMutableArray *sectionTitle = [[NSMutableArray alloc] init];
NSMutableArray *groupData = [[NSMutableArray alloc] init];
while (idx < 1) {
HeaderModel *header = [[HeaderModel alloc] init];
DataModel *name = [[DataModel alloc] init];
[header setHeader:[NSString stringWithFormat:#"Section %d", idx]];
[name setName:[NSString stringWithFormat:#"Name %d", idx]];
[sectionTitle addObject:header];
[groupData addObject:name];
idx++;
}
[self setHeaderData:sectionTitle];
[self setData:groupData]; //NSCollectionView item prototype must not be nil.
}
But now I get the error NSCollectionView item prototype must not be nil.
How do I resolve this ?
I have just answered a similar question here
But somehow by inserting the second NSCollectionView with I.B, you get a corrupted prototype for your inner NSCollectionViewItem. Simply try to extract each associated NSView into its own .xib

To add an class object in nsmuttable array of another class

I have two classes results and flight segment
Result
{
// Here some properties declared and
// Nsmuttable array also to store flight segment class object
}
I create object of both classes and adding in this way
[objresult.flightsegmentarray addobject: objflightsegment]
But this doesn't work
You should ensure you have properly declared the 'flightsegmentarray' property on the 'objresult' object and have initialised it before trying to add objects.
To declare the property - assuming your objresult is of type ObjResult - you should write on your ObjResult .h file:
#property (nonatomic, strong) NSMutableArray *flightsegmentarray;
Then, you must initialise this, typically in your .m file:
- (id)init {
if ((self=[super init])) {
_flightsegmentarray = [NSMutableArray new];
}
return self;
}
Now, once your objresult object has been initialised, you will have an empty mutable array available and you can begin adding objects:
objresult = [[ObjResult alloc] init];
objflightsegment = [[ObjFlightSegment alloc] init];
[objresult.flightsegmentarray addobject: objflightsegment];

NSMutableDictionary setObject:forKey - custom class

I am using this in a UINavigation environment.
I have customClassA. It inherits customClassB and one of its object is a NSMutableDictionary.
I alloc and init customClassA in a viewController, then for adding data, I am pushing a new viewController into the stack. The addNewDataViewController sends the newly added data, a customClassB object back by its delegate. Everything works fine so far.
customClassA has to store the returned object (customClassB) into its NSMutableDictionary object with a key (an NSString created from NSDate).
I get "mutating method sent to immutable object" error and can't think of any solution.
Any help is appreciated.
Thanks.
===========================
interface customClassA : NSObject
{
NSDate date;
NSArray *array; // will contain only NSString objects
}
// and the rest as customary
...
#import "customClassA.h"
interface customClassB : NSObject
{
NSString *title;
NSMutableDictionary *data; // will contain values of customClassA with keys of NSString
}
// and the rest as customary
...
#import "customClassB"
#interface firstViewController : UITableViewController <SecondViewControllerDelegate>
- (void)viewDidLoad
{
self.customClassB_Object = [customClassB alloc] init];
// and the rest...
}
- (void)secondViewControllerDidSaveData:(customClassA *)aData
{
[self.customClassB_Object.data setObject:aData forKey:[NSString stringWithFormat:#"%#", aData.date]];
// update tableView
}
Make sure you are initializing the NSMutableDictionary with something like
NSMutableDictionary *myDictionary = [[NSMutableDictionary alloc] init];
It would appear that your NSMutableDictionary is getting created with an NSDictionary instance instead of a NSMutableDictionary
Althoguh I added the following code to customClassB implementation, it still didn't work.
#implementation customClassB
- (id)init
{
self = [super init];
if (self)
self.data = [NSMutableDictionary alloc] init];
return self;
}
so I added two custom methods to my customClassB implementation, as well as in the header file:
- (void)appendData:(customClassA *)aData;
- (void)removeDataWithKey:(NSString *)aKey;
and instead of manipulating the data dicionary of customClassB in my viewController, I simply call that method and pass the data object to the class and it did the trick.

Resources