dynamic initialize any objective C class with property - ios

Can we initalize dynamically any Modal class. rather than creating any NSObject class with property values as likes string inside that class.
default we do code as like:
in .h file
#interface MyUser : NSObject
#property (nonatomic, strong) NSString *username,*bio,*website;
#end
in .m file
#implementation InstaUser
#synthesize bio;
#end
To use that we do:
MyUser *sendUser = [[MyUser alloc]init];
sendUser.username = #"JHON";
sendUser.bio = #"abcdcskdfhksfjhfkjsdf";
I Don't want to create so many this type of modal class rather then this just any dynamic method to initalize class property and use it by inline code.

You can use run time feature of objective c class.
Create a single model class and add property to it dynamically at run time:
For more reference :
How can I add properties to an object at runtime?

I think you meant a flexible model object with dynamically declared properties something like this:
MyModel *user = [[MyModel alloc] init];
user.name = #"name";
MyModel *something = [[MyModel alloc] init];
something.dynamicProperty = #"blahblah";
If so, you cannot. Use NSMutableDictionary instead, or consider to generate model classes from a simple config file by some scripts.

Related

Objective-C variable that is accessible in other classes

I have a NSString object called language and I want to access it from other classes what is the proper way? I tried following steps:
1) I created delegate method and send string via delegate
-(void)setLanguageForController:(NSString *)language {
self.language = language;
}
Console showed this
unrecognized selector sent to instance delegate
2) I created method getCurrentLanguage
static NSString *language;
+(NSString*)getCurrentLanguage {
return language;
}
And access like this
NSString *myLanguage = [[MyView alloc] getCurrentLanguage];
you should declare language as a property in your class .h file.
#property (nonatomic, copy) NSString* language;
When you want to set language:
initalize your class instance: yourObj
call: yourObj.language = "whatever"
or [yourObj setLanguage:"whatever"];
Each property declaration ends with a type specification and a name.
For example:
#property(copy) NSString *title;
This syntax is equivalent to declaring the following accessor methods:
- (NSString *)title;
- (void)setTitle:(NSString *)newTitle;
read more about objective-C property here
You don't need to create your method like setLanguageForController and getCurrentLanguage to get and set the your variable like this if you want to access it from other class. You need to create a property in your interface file or .h file, it will be public and it provide its getter and setter method which you can access from any class by the instance variable of your class that contains your property.
You can declare your property in .h or class interface file like this:
#property (nonatomic, strong) NSString* language;
To set it's value you can use.
obj.language = #"value"; or [obj setLanguage:#"value"];
To get its value. You need to use same instance variable like this
NSString *strLanguageValue = obj.language;

Why NSManagedObject Subclass can't use class_copyMethodList find dynamic generated method?

When I create a NSManagedObject Subclass Employee,it has a property nameaccording the EntityDescription in xcdatamodelfile. And in the .m file, the code modify it using #dynamic like this:
#interface Employee (CoreDataProperties)
#property (nullable, nonatomic, retain) NSString *name;
#end
#implementation Employee (CoreDataProperties)
#dynamic name;
#end
According to the Apple's Document:
Core Data dynamically generates efficient public and primitive get and set attribute accessor methods and relationship accessor methods for properties that are defined in the entity of a managed object’s corresponding managed object model. Therefore, you typically don’t need to write custom accessor methods for modeled properties.
According this, I think the CoreData Framework will create two method named name and setName:in the runtime. So I use such code to verify my thinking.
Employee *object = [NSEntityDescription insertNewObjectForEntityForName:#"Employee" inManagedObjectContext:self.managedObjectContext];
object.name = #"1";
[[self class] showInstanceMethod:[Employee class]];
+ (void)showInstanceMethod:(Class)class {
unsigned int outCount;
//..show InstanceMethodList
Method *methodsList = class_copyMethodList(class, &outCount);
for (int i = 0; i < outCount; i ++) {
SEL sel = method_getName(*methodsList);
NSString *methodName = NSStringFromSelector(sel);
NSLog(#"\nmethodName:%#\n", methodName);
methodsList++;
}
}
I'm sad it didn't log any method name like name or setName:.But I use this code object.name = #"1"; and didn't have any problem.
When they say "dynamically" they really do mean it - the dynamic implementation seems to be provided only as and when the selector is called (directly or via valueForKey:). You can see this happening if you override resolveInstanceMethod: in your Employee class. Call the super implementation and log the selector name and return value. Presumably the method will be listed by class_copyMethodList at this point, though I've never checked.

iOS Programming: Access instance variables from View Controller

I have created a custom class of NSObject, and I would like to access some instance variables from my main View Controller to that custom class, how do you do that?
EDIT: Perhaps I was unclear in my first formulation. It is the instance variables from the ViewController class I would like to access, not the ivars from my custom class.
If I got you right, the simplest way is to pass view controller instance during initialization. Just implement initWithViewController:(UIViewController*)vc in your custom class.
You should expose your data as properties in your NSObject subclass. You can find a description of properties at this tutorial: http://rypress.com/tutorials/objective-c/properties.html.
You should better use properties to easy access to some info in your custom class.
They automatically generate iVars.
Also you can access public (declared in .h file) ivars directly:
#interface CustomClass : NSObject
{
NSArray *_array1;
}
#property (nonatomic, strong) NSArray *array2;
CustomClass *instance = [CustomClass new];
NSArray *a1 = instance->_array1;
NSArray *a2 = instance.array2;

Saving and accessing a variable from a separate class

I'm working in Xcode using Spritekit and I'm struggling to build a separate class to display high scores.
Level 1 has a property called highscore(#synthesize highscor = highscore;) as its name suggests, records the highest scores, but I can't figure out how to send it to the high score class.
JKGLevel1 *class1Instance = [[JKGLevel1 alloc] init];
int x = class1Instance.highscor;
That's how I tried it, but when I leave level 1 and go to the high score class, it keeps telling me that the high score is 0.
First of all you do not need to #sythesize anything anymore, but thats just an aside. What you will need to do is create a singleton class, i.e.: a class with properties that are only instantiated once and can be accessed ANYWHERE in you code where you please.
For example I use this for storing account information :
In the .m file
+ (id)sharedManager {
static AppManager *sharedMyManager = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedMyManager = [[self alloc] init];
});
return sharedMyManager;
}
- (id)init {
return [super init];
}
in the .h file
#import <Foundation/Foundation.h>
#import <Accounts/Accounts.h>
#interface AppManager : NSObject
#property (nonatomic, retain) ACAccount *twitterAccount;
#property (nonatomic, retain) NSMutableArray *arrayOfAccounts;
+ (id)sharedManager;
#end
**Then in any file I want to use this : **
AppManager *sharedManager;
sharedManager = [AppManager sharedManager];
NSString *usrName = sharedManager.twitterAccount.username;
Hope this actually helps you. There are also other ways you can do this by just creating a class that you manage carefully without this singleton nonsense, but this is a cleaner way of doing it.
Do something like this:
In your HighScoreClass make a property named lavel1HighScore. (if you don't want to make property for each level then you can do it by an array. :) )
When your level 1 is complete pass the highScore of level1 to that property of HighScoreClass.
Like:
JKGLevel1 *class1Instance = [[JKGLevel1 alloc] init];
HighScoreClass *highScore = [[HighScoreClass alloc] init];
highScore.lavel1HighScore = class1Instance.highscor;
Hope this helps.. :)
You could put the scores in a plist to be read in viewdidload or if there is a reason to pass a live score object from level to level -
I would suggest that you put in your scores in a separate class (just an ordinary class with a header and method (.h & .m) and just make the class available to all your levels (class) this can easily be done via the following code:
... levelx.h
#import <UIKit/UIKit.h>
#class Class_scores;
#interface LevelxViewController : UIViewController <> {
}
#property (nonatomic, strong) Class_scores *highscore_class;
needless to say you will need to define a function in the (high_score) class to return the high score and call it from your level class.

Accessing an array from another class

I have an array called client in one of my classes and I want to use the information in that array in another class that i have. I have set up the property and synthesized the array in my first class. The code for my first class is
#synthesize client;
...
- (IBAction)testing:(id)sender {
NSString *textContent = myTextView.text;
textContent = [textContent stringByReplacingOccurrencesOfString:#" " withString:#""];
client = [textContent componentsSeparatedByString:#"."];
NSLog(#"%#", client);
}
In my second class I tried importing the h file for my first class and then just accessing the array. The code that I am using is
- (IBAction)ButtonStuff:(id)sender {
ArrayManipulationViewController *myClass = [[ArrayManipulationViewController alloc]init];
NSLog(#"Second Interface");
NSArray *test = myClass.client;
NSLog(#"%#", test);
}
To access object from multiple classes, a common approach is to declare the object in the parent class, and then pass a shared instance of that object to all child classes that require access. For instance, you could declare the array in the AppDelegate, and set array properties in your subclasses, and pass the instance of the array from the AppDelegate to all your subclasses.
Eg: create an NSArray (myArray) in your app delegate, then in the AppDelegate implantation, pass the myArray instance to your sub view controllers using properties.
Or, if you'd prefer; you can declare the array in your first class, and then pass the array instance from your first class to your second class using properties. Then, any changes made in your second class will be available in your first class, since the INSTANCE is the same.
UPDATED ANSWER:
For the second approach, you're best declaring the array in your first class implementation, and then when you instantiate the second class, pass the instance of the array to the second class using properties. In this example, you'll need to have an NSArray property in your second class to be able to pass the array over to it using [secondClassInstance setClient: client];
Your second class interface might look like this:
#interface SecondClass : NSObject
{
NSArray *client;
}
#property (nonatomic, retain) NSArray *client; // don't forget to synthesize
#end
Then, in your first class, you can do the following to pass over your instance of the array:
NSArray *client = [[NSArray alloc] initWithObjects:#"Object 1", #"Object 2"];
//...
SecondClass *secondClass = [[SecondClass alloc] init];
[secondClass setClient: client]; // passing the original client instance here
// don't forget to release secondClass instance when finished

Resources