I'm trying to make a deep copy of an NSMutableArray whose objects are instances of a custom class similar to this:
#interface CustomParent : NSObject
#property NSInteger Id;
#property (strong, nonatomic) NSString *IdStr;
#property (weak, nonatomic) NSDate *Date;
#property (strong, nonatomic) NSMutableArray *CustomChildren;
#property (strong, nonatomic) CustomType *Type;
#property float Value;
#end
I know there are lots of posts dealing with copying objects, but I donĀ“t find examples for getting a complete copy of objects with collection members or properties. NSMutableArray *dstArray = [[NSMutableArray alloc] initWithArray:srcArray copyItems:YES]; raises an exception involving the copyWithZone method.
How can I do this? Thanks!
In order to deep copy the content of the array
[[NSMutableArray alloc] initWithArray:srcArray copyItems:YES];
will send copyWithZone: to every object inside the collection. If they don't respond to this selector, you'll get a crash.
Have your CustomParent class to conform to the NSCopying protocol and you're done.
Here's some extra info on how do achieve it: Implementing NSCopying
Related
I'm creating an app that will create a form which a user will then fill out and save for later use.
#interface DataModel : NSObject
#property (strong, nonatomic) NSString *whiskeyName;
#property (strong, nonatomic) NSNumber *whiskeyRating;
#property (strong, nonatomic) NSString *whiskeyColor;
#property (strong, nonatomic) NSString *whiskeyNose;
#property (strong, nonatomic) NSString *whiskeyFlavors;
#property (strong, nonatomic) NSString *whiskeyFinish;
#property (strong, nonatomic) NSString *whiskeyNotes;
The app will store multiple copies of these forms (think of Apple's Notes app). I've created a class composed of NSStrings and NSNumbers but I'm having a difficult time figuring out a way save them to an NSArray to access later. I've just started fooling around with Core Data but everything I've found will only save a single form. How can I save multiple versions of a class in an array to be opened and edited for later use? Sorry if the question is vague, but I've been hitting my head on a wall and am having a hard time finding a working solution.
If I understand correctly you have sub-classed NSObject and want to save multiple instances of this class into an array? If that is the case, then a MutableArray should be able to hold any object:
// .m file
#import "DataModel.h"
#interface YourViewController
#property (strong, nonatomic) NSMutableArray *myArray;
#end
#implementation YourViewController
- (void) viewDidLoad {
NSMutableArray *myArray = [[NSMutableArray alloc] initWithCapacity:numberOfObjectsToStore];
DataModel *myClassInstance1 = [[DataModel alloc] init];
myClassInstance1.whiskeyName= #"somevalue";
myClassInstance1.whiskeyRating= 5;
DataModel *myClassInstance2 = [[DataModel alloc] init];
myClassInstance2.whiskeyName= #"someothervalue";
myClassInstance2.whiskeyRating= 2;
[myArray addObject:myClassInstance1];
[myArray addObject:myClassInstance2];
}
This question already has an answer here:
Confusion with distinct and indistinct object
(1 answer)
Closed 7 years ago.
I'm trying to do a NSCountedSet but I need to ignore a property, I tried overriding the isEqual method of my object, and doing a manual compare of all the properties except the one I want to ignore but it doesn't work
Any idea on how to achieve it?
UPDATE
My class
#interface GSOrderMenuMenuContent : GSBaseModel
#property (copy, nonatomic) NSNumber *order_content_id;
#property (copy, nonatomic) NSNumber *item_id;
#property (copy, nonatomic) NSNumber *price;
#property (copy, nonatomic) NSNumber *priceWithModifiers;
#property (copy, nonatomic) NSString *course;
#property (copy, nonatomic) NSString *itemName;
#property (nonatomic) GSMenuItem* item;
#property (nonatomic) NSMutableArray *modifiers;
#property (copy, nonatomic) NSNumber *isAlreadyPrinted;
#property (copy,nonatomic) NSNumber *isDeleted;
-(GSOrderMenuMenuContent*)deepCopy;
-(GSOrderContent*) orderContent;
-(BOOL)isEqual:(GSOrderMenuMenuContent*)object;
#end
Usage:
NSCountedSet* countedSet = [[NSCountedSet alloc] initWithArray:contents];
Where contents is an array of class objects
Adding a breakpoint to the isEqual gets not called (however it is if doing a [NSarray containsObject:...]
As mentioned in the docs for the isEqual: method, you must always implement a corresponding hash method. Those two methods must always be implemented together.
Two objects that compare as equal must also return the same hash value.
I have a custom NSObject called MAAssignment. It's basically a data type that has a number of #properties and one custom init method:
#property (nonatomic, strong) NSDate *date;
#property (nonatomic, strong) NSString *assignmentName;
#property (nonatomic, strong) NSNumber *totalPoints;
#property (nonatomic, strong) NSNumber *recievedPoints;
#property (nonatomic, strong) NSNumber *classAverage;
#property (nonatomic, strong) NSNumber *extraCredit;
#property (nonatomic, strong) NSNumber *notGraded;
- (id)initWithDate:(NSString *)date assignmentName:(NSString *)assignmentName totalPoints:(NSNumber *)totalPoints recievedPoints:(NSNumber *)recievedPoints classAverage:(NSString *)classAverage extraCredit:(NSNumber *)extraCredit notGraded:(NSNumber *)notGraded;
I create an instance of it in the viewController, hoping to populate the newly created item with some data... But I can't figure out how to access the variables of the object. I went MAAssignment *assignment = [[MAAssignment alloc] init];, then I tried [assignment setDate] or assignment.date = ddate but none of them seem to work.
Am I misunderstanding how the accessors for objects work?
You should place these variables in h. file
of MAAsignment
I'm not understanding your question very well (where are you declaring this code? What's the full code of your MAAsiignment initialization example?), however I'll try to answer anyway.
Are you sure that the #property declarations are inside the #interface in .h and not inside .m?
The #interface inside .m is a private class extensions, and allows you to declare private properties. To make them available outside, you need to put them inside the header (.h).
Please post more code to let us provide a more exhaustive answer.
What you describe is a data container object. It should work as described:
MAAssignment *anAssignment = [[MAAssignment alloc] init];
anAssignment.date = [NSDate date];
anAssignment.totalPoints = #(10);
NSLog(#"anAssignment.date = %#", anAssignment.date);
NSLog(#"anAssignment.totalPoints = %#", anAssignment.totalPoints);
Should work perfectly. Are you getting any warnings?
I've read the other threads about arrays of UIImageView-objects, but I can't get it to work. Note that I'm completely new to Objective-c.
I have some UIImageView objects declared in the .h - file like this:
#property (weak, nonatomic) IBOutlet UIImageView *obj1;
I also have an array declared at the same place:
#property (weak, nonatomic) IBOutlet NSArray *arr;
In the viewDidLoad-method I want to add obj1 to arr. How can I do that?
I've tested to initialize arr and add objects to it, but it doesn't work.
_arr = [[NSMutableArray alloc] init];
[_arr addObjects: obj1];
Hank
make sure in debugger that _arr is not nil. You need to declare it as
#property (strong, nonatomic) NSMutableArray *arr;
since arr is not a ui control on view controller, you do not need to add IBOutlet.
Also, your view controller posses it, so it should be strong rather than weak.
You also should use NSMutableArray instead of NSArray, since only the first one can be used for adding objects, and this is how you say to the compiler of the type of this object
Change
#property (weak, nonatomic) IBOutlet NSArray *arr;
to
#property (strong, nonatomic) NSMutableArray *arr;
If you want to add UIImageView Object in your Array you can do that.But the thing is if your want to add object in NSArrar after its initialization than you have to declare NSMutableArray as you can add and remove object in that than the addObject method would work.
Also their is no need to declare NSArray of NSMutableArray as IBOutlet.
My project is ARC-enabled, I have two models something like:
Category:
#interface Parent : NSObject
#property (assign, nonatomic) Category *parent;
#property (strong, nonatomic) NSArray *children;
#property (strong, nonatomic) NSArray *subCategories;
#end
Product:
#interface Child : NSObject
#property (strong, nonatomic) NSString *name;
#property (assign, nonatomic) Category *category;
#end
To avoid reference loop, and to deploy on iOS 4.x, I set the parent property of Child as assign but not weak.
From JSON data, I can get a tree containing my categories and products. When I use the tree to enumerate, all the things went perfect. And I have a recursion method to search products with name matching a keyword. The method is something as followed:
- (NSArray *)productsWithKeyword:(NSString *)keyword
{
NSMutableArray *filteredProducts = [NSMutableArray array];
for (Category *cat in self.children) {
NSArray *subResult = [cat productsWithKeyword:keyword];
[filteredProducts addObjectsFromArray:subResult];
}
return [filteredProducts copy];
}
The problem is when I'm using the returned array, I can get the right category property. But from the second time and on, the category property becomes 0 (caught from debugger).
So, what's the problem? And what's the fix to the problem?
To avoid a reference loop you want to make one object have a weak reference to the other not have both with weak references to each other. I think what's happening in this case is that the product doesn't own the category and the category doesn't own the product, so ARC releases both of the objects assuming no one claims them.
FIX: make one of these objects the "parent" of the other.