Hey all. I know this sounds simple, but I can't find a way to do it. I have a method in Obj-C that takes in a NSString and then should create a new class with the String as its title.
-(DataModel *)createDataModel:(NSString *)dataModel_name {
DataModel *[initWithString:dataModel_name] = [[DataModel alloc] init];
}
I know I have some problems in this. For starters, I don't know how to define a return on an object whose name could change. Second, I know this doesn't compile considering the initWithString method is wrong. I just don't know what to do or what method to use so that I can create this DataModel object with the specified name...
If your title is setup correctly, as a property:
-(DataModel *)createDataModel:(NSString *)dataModel_name {
DataModel *model = [[DataModel alloc] init];
model.title = dataModel_name;
return model;
}
That would require in your datamodel.h:
#interface DataModel {
NSString *title;
}
#property (nonatomic, retain) NSString *title;
#end
And in your .m:
#implementation DataModel
#synthesize title;
#end
But your question isn't clear if your real purpose is trying to instantiate different classes based on the dataModel_name or if you just have a single generic class with a title that should be set to dataModel_name.
Depending on what you want to do, there are different answers. If you really want different classes based on the name, then you should do things differently. You can use the Cocoa specific type: id, to return any object from a method. Then the method, NSClassFromString() to create the object:
- (id)createDataModel:(NSString *)dataModel_name {
id model = [[NSClassFromString(dataModel_name) alloc] init];
[model setTitle:dataModel_name];
return model;
}
Or you can define a Protocol (Interface in java parlance) that declares the features of your data model. Your method would return that instead.
NSClassFromString() will do what you want. Also, initially declaring variables as type id allows you to set their explicit type later on. So:
id dataModel = [[NSClassFromString(dataModel_name) alloc] init];
To locate or create a new class:
Class arbitraryClass = NSClassFromString(dataModel_name);
if ( nil == arbitraryClass ) arbitraryClass = objc_allocateClassPair( [DataModel class] , [dataModel_name UTF8String] , 0 );
To create a new instance of an object with your newly created class:
DataModel *modelWithArbitratyClassName = [[arbitraryClass alloc] init];
Creating new classes at runtime is not usually a good idea.
So, it seems you want to dynamically add an Instance variable to an object at runtime. You don't get this for free. CALayer and CAAnimation can do something similar to this, you can read about it here
You could add similar functionality to your own objects using Key-value-coding, and more specifically the method valueForUndefinedKey. There will be some KVC specific caveats so you should really make sure you are familiar with and understand KVC. Take a look at this, it might be just want you want.
A dictionary is used to store the value and key, and to retrieve the value when you try to access it.
Related
I have an NSDictionary that I am passing to a NSObject Class where I pull all of the values out of the dictionary and pass them into their correct types.
For instance NSInteger, BOOL, NSString, char are the types of values I am pulling out of the NSDictionary and putting into their only variables.
My question what is the best way to turn these values into one big object that can then be putt into an array?
I have heard that I can use the class itself as an Object.. But I am not really sure how to do this.
or could I just put them back into a NSDictionary?... but if thats the case do NSDictionaries allow for multiple value types?
Actually, you are in the right path. this is basically MVC architecture way. so you are questioning about M = Model.
Model in here example is class that defines all variables. cut to the point, here's you should do:
-> create a class that contain your variable, with #property & #synthesize name : ClassA.
then you could set object ClassA into dictionary.
ClassA *myClass = [[ClassA alloc] init];
myClass.myString = #"test String";
myClass.myBoolean = True;
[dictionary setObject:myClass forKey:#"myObject"];
[myClass release]; //we no longer need the object because already retain in dictionary.
then retrieve it by :
ClassA *myClass = (ClassA*)[dictionary objectForKey:#"myObject"];
NSLog(#"this is value of myString : %# & boolean : %i",myClass.myString,myClass.myBoolean);
You can put the collection of values in NSDictionary, NSArray, NSMutableArray, etc. Any of the collection types. Or if you have a fixed number of values/types, you can create a class that has a data member for each value/type and put it in that. The class solution would eliminate having to do a lot of casting, but it also only works if there are a fixed number of values/types.
Here is the AppleDoc on collections.
Yeah, You can create a class itself with these as different values as a properties.Once you pass this object to any class you can access those values there by obj.propertyName.Doing by this Lead to create Modal in MVC pattern.
Please let me know if there is doubt.
Test *object = [[Test alloc] init];
object.testBool=true;
object.testString=#"Test";
NSDictionary *passData = [[NSDictionary alloc] initWithObjectsAndKeys:object,#"testObject", nil];
Test *getObject = (Test*)[passData objectForKey:#"testObject"];
NSLog(#"%d",getObject.testBool);
NSLog(#"%#",getObject.testString);
You can customized the init method of Test Class.
i have a problem in Coping a Object
I created a Model Class and use the Object Where i required it.
Certainly i required a copy of it for Some Reason
so i use in the following manner
Modeldata *copyOfDate=[[[Modeldata alloc]init ]autorelease];
copyOfDate=[g_Data copy];//This Line Gives me a Exception .
i think i need to OVERRIDE the copy Method and assignment Operator.
Please provide Me a solution for it, i am waiting for the Quick Response
You need to override copyWithZone method in your model class implementation as follows.
#implementation Modeldata
-(id) copyWithZone: (NSZone *) zone
{
Modeldata *objModeldata = [[Modeldata allocWithZone:zone] init];
objModeldata.yourProperty = yourProperty;
objModeldata.yourProperty1 = yourProperty1; //All your properties
return objModeldata;
}
#end
Now if you do following will work
Modeldata *copyOfDate=[g_Data copy];
You don't need to allocate memory there by writing
Modeldata *copyOfDate=[[[Modeldata alloc]init ]autorelease];
I have a Core Data model entity NoteObject that has a transformable type arrayOfTags. In the NoteObject.h file, which is a subclass of NSManagedObject, the arrayOfTags is declared as:
NSMutableArray *arrayOfTags;
#property (nonatomic, retain) NSMutableArray *arrayOfTags;
//.m
#dynamic arrayOfTags;
The issue is that changes that are made to this array are not saved. Someone suggested the following as the solution:
If there are mutable and immutable versions of a class you use to
represent a property—such as NSArray and NSMutableArray—you should
typically declare the return value of the get accessor as an immutable
object even if internally the model uses a mutable object.
However I'm not exactly sure what that means. How would I follow those instructions for my case?
Even of you've found a workaround in the meantime try this:
[noteObject willChangeValueForKey:#"arrayOfTags"];
// make changes to noteObject.arrayOfTags
[noteObject didChangeValueForKey:#"arrayOfTags"];
Implementing accessor functions for Core Data varies with your relationship model. This document should help you get started. Most likely you will be using this setup for your getter:
- (NSArray*)data
{
[self willAccessValueForKey:#"data"];
NSArray* array = [[NSArray alloc] initWithArray:arrayOfTags copyItems:YES];
[self didAccessValueForKey:#"data"];
return array;
}
Please note that the above snippet is just an example and will have to be modified for your use.
I have a small function which I want to rewrite, so that function is valid for every class.
At the moment I have 10 of the same functions which all work same but every function is for another class.
I know, that I have to do it with reflections, but I am not so sure how to do it.
I already read this link:
http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/ObjCRuntimeRef/Reference/reference.html
The functions I am talking about are:
-(NSCountedSet *)MissionGetReferecedNested:(id)modelObject
{
setOfObjects = [[NSCountedSet alloc]initWithArray:modelObject.MissionSectionList];
return setOfObjects;
}
-(NSCountedSet *)MissionGetSectionReferecedNested:(id)modelObject
{
setOfObjects = [[NSCountedSet alloc]initWithArray:modelObject.DamageAccountList];
return setOfObjects;
}
MissionSectionList and DamageAccountList are both NSMutableArrays from two different classes.
Is it possible to see if a class consists a NSMutableArray and if yes then it should call the .... modelObject.MyMutableArray?
You can use reflection like this:
- (NSCountedSet *)MissionGet:(id)modelObject
{
SEL propertySelector = NULL;
if ([modelObject respondsToSelector:#selector(MissionSectionList)]) {
propertySelector = #selector(MissionSectionList);
} else if ([modelObject respondsToSelector:#selector(DamageAccountList)]) {
propertySelector = #selector(DamageAccountList);
}
if (!propertySelector) {
[NSException raise:#"Invalid modelObject value" format:#"Model object %# does not contain any recognised selectors", modelObject];
}
return [[NSCountedSet alloc] initWithArray:[modelObject performSelector:propertySelector]];
}
But a more common technique among cocoa programmers would be:
- (NSCountedSet *)MissionGet:(id <MyCustomProtocol>)modelObject
{
return [[NSCountedSet alloc] initWithArray:[modelObject missionArray]];
}
Where you would accept any object which confirms to the protocol MyCustomProtocol. The protocol is defined in a header files somewhere, using:
#protocol MyCustomProtocol
#property (readonly) NSArray *missionArray;
#end
And then in each of your classes, declare it as implementing the protocol:
#interface MissionSectionListClass <MyCustomProtocol>
And add a method implementation:
#implementation MissionSectionListClass <MyCustomProtocol>
- (NSArray *)missionArray
{
return self.MissionSectionList;
}
#end
Using protocols is a bit more code, but it's the "right" way to go. It allows you to add support for new classes, without any change to your MissiongGet... method.
More info about protocols: http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocProtocols.html
EDIT : Cleared all my answer to this :
I think it's not possible to check if a class has a member variable of specified type. You can only check if a class has a specified method.
So, in this case it will be best if you make all your NSMutableArray list the same name, and then create a declared property for this list, and then do a respondsToSelector in your ...GetReferencedNested method.
So, for example, in all of your class create this property :
#property (nonatomic, retain) NSMutableArray * list;
and then in the ..MissionGetReferencedNested method :
if ([modelObject respondsToSelector:#selector(list)])
...
Correct me if i'm wrong...
In terms of style I'd also follow Abhi's suggestion.
But if you really want to inspect a class that you are stuck with and, for example build a NSCountedSet with the first NSMutableArray variable you can find, you could do it like this:
#import "Utilities.h"
#import <Foundation/Foundation.h>
#import <objc/objc-runtime.h>
#implementation Utilities
+ (NSCountedSet*)initCountedSetWithFirstArrayinObject:(id)someObject {
unsigned int c;
Ivar *ivar_arr = class_copyIvarList([someObject class], &c);
for (unsigned int i = 0; i < c; i++) {
if ([#"#\"NSMutableArray\"" isEqualToString:
[NSString stringWithCString:ivar_getTypeEncoding(ivar_arr[i]) encoding:NSUTF8StringEncoding]
]) {
return [[NSCountedSet alloc] initWithArray:object_getIvar(someObject, ivar_arr[i])];
}
}
return nil;
}
#end
Of course this has very limited real world use because it depends on you knowing that the first array will be the one you're interested in.
I think I have to go with the runtime type editing.(http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/ObjCRuntimeRef/Reference/reference.html)
The idea with the protocols was good but there I have to change a lot of things in the classes.(which is not possible/allowed) for me. My intension was only to change the functions so that I have only one function for all classes.
I think with the runtime type editing I can check what classes and attributes I have (?) Am I right?
Did somebody already work with runtime type editing?
I want to make a singleton containing information "title, comments, Two picture" and it saves all the information in an array
I want to do is these objects in my application I use it All The Time
#interface CarteManager : NSObject {
NSMutableArray *carteMan ;
}
#property(nonatomic,retain) NSMutableArray *carteMan;
+(CarteManager*)sharedInstance;
-(void)ajouttitre:(NSString*)txt;
-(void)ajoutcom:(NSString*)com;
-(void)ajoutimage1:(UIImage*)img;
-(void)ajoutimage2:(UIImage*)img;
#end
In order to create a Singleton you will need a static instance.
#implementation CarteManager
static CarteManager *_carteManager = nil;
+(CarteManager*)sharedInstance {
if (!_carteManager) {
_carteManager = [[CarteManager alloc] init];
}
return _carteManager;
}
// your other codes
#end
And before creating a Singleton, make sure that you really need a Singleton. Please pay special attention to Singleton: How should it be used.
You didn't state your problem. If it's how to make the object a singleton, you can find several possible implementations in the question What does your Objective-C singleton look like?.