NSMutableArray removeObject crash - ios

I'm sorry I'm new to iOS development,this day I encountered a strange problem:
when I remove object from custom object , it always return crash:
reason: '-[__NSArrayI removeLastObject]: unrecognized selector sent to instance
the following code:
#interface Base : NSObject
#property (nonatomic, assign) BOOL isFinish;
#property (nonatomic, strong) NSString *title;
#property (nonatomic, strong) NSString *subTitle;
#property (nonatomic, strong) NSString *tagURL;
#property (nonatomic, assign) NSInteger taskScore;
#property (nonatomic, assign) BOOL inProgress;
#property (nonatomic, assign) NSInteger nowTime;
#property (nonatomic, assign) NSInteger totalTime;
#end
then I use on another class:
#property (nonatomic, strong) NSMutableArray *arr1;
#property (nonatomic, copy) NSMutableArray *arr2;
_arr1 = [[NSMutableArray alloc] init];
for (int i = 0; i < 10; i++) {
Base *b = [[Base alloc] init];
b.title = [[NSString alloc] initWithFormat:#"%d", i];
[_arr1 addObject:b];
}
self.arr2 = [_arr1 copy];// 001, I tried copy or mutable copy
[_arr2 removeLastObject]; //it always crash in here!!
So I look through some reference,some told me must conform nscopying or nsmutablecopying protocol
So I add some method in the Base class #implementation
- (id)copyWithZone:(struct _NSZone *)zone
{
Base *copy = [[[self class] allocWithZone:zone] init];
if (copy) {
[copy setIsFinish:[self isFinished]];
[copy setTitle:[self title]];
[copy setSubTitle:[self subTitle]];
[copy setTagURL:[self tagURL]];
[copy setTaskScore:[self taskScore]];
[copy setInProgress:[self inProgress]];
[copy setNowTime:[self nowTime]];
[copy setTotalTime:[self totalTime]];
}
return copy;
}
But it doesn't work , can some one help me?

First look at the error that you got. It quite clearly states that you sent "removeObject" to an NSArray which doesn't understand it, and not to an NSMutableArray. The logical conclusion is that at this point in time, _arr2 is not a mutable array but an NSArray.
Now as a software developer, you should try to think this through logically. You know the difference between copy and mutableCopy, right? You say you used mutableCopy, but what do you think happens when you set a property that is marked as "copy"? It copies. By calling copy. So you made a mutable copy of your mutable nsarray, and the property setter makes an immutable copy.

I think you need to use mutableCopy instead of copy. Copy will create immutable copy of the array. The removeLastObject is available on mutable version of the Array.

Related

Why can I not initialize this NSArray With Objects?

I have an array containing objects of a custom-made class. However, on initialization the compiler gives me an error - "Lexical or Preprocessor" Expected ':'
interface myClass : NSObject
#property (readwrite, strong) NSString* name;
#property (readwrite, strong) NSString* home;
#property (readwrite, strong) Preference pref; // This is another custom class
-(id) initWithName:(NSString*) name home:(NSString*) home preference:(Preference) preference;
end
#interface MyViewController()
#property (nonatomic, strong) NSArray *rowArray;
#end
#implementation MyViewController
...
...
...
- (void) initializeArray
{
self.rowArray = #{
[[myClass alloc] initWithName:#"Harry" home:#"New York" preference :Acura],
[[myClass alloc] initWithName:#"Win" home:#"Seattle" preference :Toyota];
};
}
Can someone tell me just where I am messing up and why I'm getting this error?
The Objective-C literal for an array is with square brackets,
NSArray *anArray = #[obj1, obj2].
In the code you posted it is trying to make a Dictionary,
NSDictionary *aDict = #{"key1" : obj1, #"key2" : obj2}
so this is why it is saying it expects a :.
The line should read,
self.rowArray = #[
[[myClass alloc] initWithName:#"Harry" home:"New York" preference :Acura],
[[myClass alloc] initWithName:#"Win" home:"Seattle" preference :Toyota];
];
As others have pointed out the there are a few other errors with the code and those city names are not NSString's, but I guess this is just an example snippet.

NSDictionary custom object store and retrieve

Trying to store value in NSDictionary and retrieve it
Objects
#import <Foundation/Foundation.h>
#class ATTTEstOBJ;
#interface ATTTEst : NSObject
#property (nonatomic, retain) NSString *string1;
#property (nonatomic, retain) NSString *string2;
#property (nonatomic, retain) ATTTEstOBJ *obj1;
#end
#interface ATTTEstOBJ : NSObject
#property (nonatomic, retain) NSString *string3;
#property (nonatomic, retain) NSString *string4;
#property (nonatomic, retain) NSString *array1;
#end
I know it needs to be encoded properly to save and retrieve values.but In this case it is a composite object and I have no idea, how to deal it with.
- (void) encodeWithCoder: (NSCoder *)coder
So TLDR , How to save the composite value into dictionary and retrieve it back
I want to store ATTTest into a dictionary and retrieve it back.
EDIT : Detailed explanation
ATTTEst *test=[[ATTTEst alloc]init];
test.string1=#"a";
test.string2=#"b";
ATTTEstOBJ *obj=[[ATTTEstOBJ alloc]init];
obj.string3=#"c";
obj.string4=#"d";
test.obj1=obj;
NSMutableDictionary *dict=[[NSMutableDictionary alloc]initWithCapacity:3];
[dict setObject:test forKey:#"test"];
NSLog(#"%#",dict);
ATTTEst *tester=[dict objectForKey:test];
NSLog(#"%#",tester.obj1.string3);
IT shows null.as output I want to get the value as c for tester.obj1.string3
ATTTEst *tester=[dict objectForKey:test];
should be
ATTTEst *tester=[dict objectForKey:#"test"];
You have used the object test (instead of the string #"test") as key when retrieving the object. I don't think that
was intentionally.
In order to store them into NSDictionary, you don't need to encode them.
Just do:
NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:, attestObject,#"attestObject", attest2Object,#"atttest2" nil];
Where attestObject and attest2Object are the objects you want to store, and strings are their keys.
This has nothing to do with encoding...

[MyClassName copyWithZone:]: unrecognized selector sent to instance?

I just implemented my class
#interface ExampleNestedTablesViewController ()
{
NSMutableArray *projectModelArray;
NSMutableDictionary *sectionContentDictionary;
}
- (void)viewDidLoad
{
[super viewDidLoad];
ProjectModel *project1 = [[ProjectModel alloc] init];
project1.projectName = #"Project 1";
ProjectModel *project2 = [[ProjectModel alloc] init];
project2.projectName = #"Project 2";
if (!projectModelArray)
{
projectModelArray = [NSMutableArray arrayWithObjects:project1, project2, nil];
}
if (!sectionContentDictionary)
{
sectionContentDictionary = [[NSMutableDictionary alloc] init];
NSMutableArray *array1 = [NSMutableArray arrayWithObjects:#"Task 1", #"Task 2", nil];
[sectionContentDictionary setValue:array1 forKey:[projectModelArray objectAtIndex:0]]; // **this line crashed**.
}
}
Here is my Project Model
#interface ProjectModel : NSObject
typedef enum
{
ProjectWorking = 0,
ProjectDelayed,
ProjectSuspended,
} ProjectStatus;
#property (nonatomic, assign) NSInteger idProject;
#property (nonatomic, strong) NSString* projectName;
#property (nonatomic, strong) NSMutableArray* listStaff;
#property (nonatomic, strong) NSTimer* projectTimer;
#property (nonatomic, assign) ProjectStatus projectStatus;
#property (nonatomic, strong) NSMutableArray* listTask;
#property (nonatomic, assign) NSInteger limitPurchase;
#property (nonatomic, strong) NSDate* limitTime;
#end
And the output is:
SDNestedTablesExample[1027:c07] -[ProjectModel copyWithZone:]: unrecognized selector sent to instance 0x7562920.
I didn't know which problem. Can you help me ?
Look at the docs for NSMutableDictionary setObject:forKey: (note you should use setObject:forKey:, not setValue:forKey:). Notice the expected type for the key. It must be of type id<NSCopying>. This means the key must conform to the NSCopying protocol.
Since your keys are of type ProjectModel, the error is complaining since your ProjectModel class doesn't implement the required method of the NSCopying protocol - copyWithZone:.
Are you sure you want to use a ProjectModel object as the key? Doing so also means you need a sane implementation of the isEqual: and hash methods, in addition to copyWithZone.
The solution is to update your ProjectModel class so it conforms to the NSCopying protocol and implements the copyWithZone: method. And also properly implement the isEqual: and hash methods. Or change the key to be just the idProject property (properly wrapped as an NSNumber).

Initialization of custom object return null [duplicate]

This question already has an answer here:
why is my code outputting *nil description*
(1 answer)
Closed 10 years ago.
Here is my custom class:
ClassA.h
#interface ClassA : NSObject<RKRequestDelegate>{
NSString *uri;
NSString *folderUri;
NSInteger idFolder;
NSString *kind;
bool isMine;
CustomUser *owner;
NSMutableArray *usersAdministrators;
NSMutableArray *usersContributors;
NSMutableArray *usersReaders;
NSString *visibility;
NSString *name;
NSString *description;
NSMutableArray *comments;
}
#property (nonatomic,copy) NSString *uri;
#property (nonatomic,copy) NSString *folderUri;
#property (nonatomic,assign) NSInteger idFolder;
#property (nonatomic,copy) NSString *kind;
#property (nonatomic,assign) bool isMine;
#property (retain) DMIUser *owner;
#property (nonatomic,copy) NSMutableArray *usersAdministrators;
#property (nonatomic,copy) NSMutableArray *usersContributors;
#property (nonatomic,copy) NSMutableArray *usersReaders;
#property (nonatomic,copy) NSString *visibility;
#property (nonatomic,copy) NSString *name;
#property (nonatomic,copy) NSString *description;
#property (nonatomic,copy) NSMutableArray *comments;
#end
ClassA.m
#implementation ClassA
#synthesize uri,folderUri,idFolder,kind,isMine,owner,usersAdministrators,usersContributors,usersReaders,visibility,name,description,comments;
-(NSString*)description {
return #"ClassA";
}
#end
Quite simple. But when i try to create new instance of this, like this:
datas = [NSMutableArray array]; // Tried with [[NSMutableArray alloc] init] => same thing
ClassA *classA = [[ClassA alloc] init];
[datas addObject:classA];
NSLog(#"classA = %#",classA);
NSLog(#"datas = %#",datas);
First NSLog returns "ClassA".
Second NSLog returns "datas = ()"
What's wrong here? I always created class like this and i've never had problem like this.
Thanks!
Ok guyzzz i found the problem. It's my attribute:
NSString *description;
Seems that iOs doesn't love that. It conflict with the -description method in NSObject...
After that, i found a similar question here:
Why can't I use "description" as an attribute name for a Core Data entity?
Cheers
if your want to return some value implement method description in the ClassA
- (NSString *)description {
return #"ClassA";
}
You've got everything you need. Are you sure the variable you're assigning to isn't a weak one? All delegate properties are weak, therefore not retaining the object. My guess is that you're doing something like this
someObject.delegate = [[ClassA alloc] init];
NSLog(#"%#", someObject.delegate);
Because the delegate property is weak it doesn't hold onto the variable.
Edit:
This whole answer assumes you are using ARC. If not, disregard.

Get related / associated entities from NSSet - CoreData

I have 2 autogenerated entities :
#interface ContactEntity : Entity
#property (nonatomic, retain) NSString *caption;
#property (nonatomic, retain) NSString *image;
#property (nonatomic, retain) NSString *name;
#property (nonatomic, retain) NSString *text;
#property (nonatomic, retain) NSSet *pointLink;
#end
#interface PointEntity : Entity
#property (nonatomic, retain) NSNumber *latitude;
#property (nonatomic, retain) NSNumber *longitude;
#property (nonatomic, retain) NSSet *entityLink;
#property (nonatomic, retain) EntityEntity *entityTypeLink;
#end
They are linked between each other as ManyToMany, i.e. one contact has many points, one point has many contacts inside.
Then a i get first entity :
ContactModel *contact = [[[ContactModel alloc] init] autorelease];
// this is FetchRequest, returns array of all entities
self.items = [contact list:contact];
// i get only one, all is OK here, this entity has related PointEntity in DB
ContactEntity *contactEntity = [self.items objectAtIndex:self.selection];
And when i try to get related PointEntity using NSSet in selected ContactEntity i always get NULL or empty array. Neither of this works :
NSArray *points = [contactEntity.pointLink allObjects];
PointEntity *pointEntity = [contactEntity.pointLink anyObject];
NSInteger x1 = [points count]; // always 0
id x2 = pointEntity.latitude; // always 0
for (PointEntity *x in contactEntity.pointLink) // isn't enumerated because count = 0
{
id x3 = x.latitude;
}
Any thoughts are appreciated. Did i miss something, maybe i need to use NSPredicate to select entities from PointEntity that are related to ContactEntity?
Thanks.
P.S. My question is similar to this but that suggestion does not work for me, i cannot get loaded associated entities using NSSet of main entity :(
CoreData: many-to-many relationship
Answer is found ... i tried to use property of the autogenerated entities when created new records in CoreData, in the meantime the correct way is to use generated methods like - addPointLinkObject, addEntityLinkObject, etc
Example, i have 3 tables :
Contacts (one person may have many locations)
<< - >>
Points (one location can contain many people)
<< - >
EntityTypes (just a type of a location, in this case type is CONTACT)
One of the entities autogenerated by xCode :
#interface PointEntity : Entity
#property (nonatomic, retain) NSNumber *latitude;
#property (nonatomic, retain) NSNumber *longitude;
#property (nonatomic, retain) NSSet *entityLink; // reference to Contacts table (ManyToMany)
#property (nonatomic, retain) EntityEntity *entityTypeLink; // reference to EntityType table (OneToMany)
#end
#interface PointEntity (CoreDataGeneratedAccessors)
- (void)addEntityLinkObject:(ContactEntity *)value;
- (void)removeEntityLinkObject:(ContactEntity *)value;
- (void)addEntityLink:(NSSet *)values;
- (void)removeEntityLink:(NSSet *)values;
#end
I tried to do the following :
// create 3 new instances - one for each entity
ContactEntity *contactEntity = [model create:model];
PointEntity *pointEntity = [point create:point];
EntityModel *entity = [[[EntityModel alloc] init] autorelease];
entity.name = model.table;
EntityEntity *entityEntity = [[entity list:entity] objectAtIndex:0];
// then i tried to use entity's properties directly to bind entities
// it works, but it works only on DB level when we add new records, but somehow something was missed and thus such selection did not work later - [pointEntity allObjects]
//pointEntity.entityTypeLink = entityEntity; // WRONG !!!
//pointEntity.entityLink = contactEntity.pointLink;
//contactEntity.pointLink = pointEntity.entityLink;
// then i replaced 3 lines above with these ones
[pointEntity addEntityLinkObject:contactEntity]; // CORRECT !!!
[contactEntity addPointLinkObject:pointEntity];
[entityEntity addPointLinkObject:pointEntity];
[context save]; // save changes made with entities in current CoreData context
// now [pointEntity allObjects] and [pointEntity anyObject] work as expected
Useful links -
Coredata and Generated subclass for NSManagedObject with relations
https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CoreData/Articles/cdAccessorMethods.html#//apple_ref/doc/uid/TP40002154

Resources