Convert string into variable - iphone

If in a class, I have a instance variable: nsstring *foo, now I want a create a variable with a string #"foo".
Example: I have the string #"foo", and with this string, I want a do: myobject.foo.

I think what you are looking for is KVC Key-Value Coding.
It enables you to retrieve or set a property or an instance variable on an object by it's name (a String). You can do something like:
id fooValue = [myobject valueForKey:#"foo"];
[myobject setValue:barValue forKey:#"foo"];

If you have setter and getter methods (or have synthesized them), you could use NSSelectorFromString() to access and modify your variable.
Accessing:
id foo = [self performSelector:NSSelectorFromString(#"foo")];
Modifying:
[self performSelector:NSSelectorFromString([NSString stringWithFormat:#"set%#:, [#"foo" capitalizedString]]) withObject:foo];

Related

How to create property from the path

I need to manipulate properties of the dictionary from taking path to that property like 'a.b.c' and setting property value. I have root object 'obj' (NSObject derived) that has property named 'a' of the type of NSObject derived class. That class has property named 'b' that is dictionary var map = [String: CGFloat]() and 'c' is key name in the dictionary. If I call obj.setValue(value, forKeyPath: 'a.b.c') it works fine if property in dictionary exist. I would like to automatically create that property if it doesnt. Is there way?
setValue(_:forKeyPath:) is not a dictionary method, it is an NSObject method.
Implement setValue(_:forUndefinedKey:) and store the key-value pair yourself. Also need to implement value(forUndefinedKey:) for obtaining the value.

Core Data Boolean property NSNumber doesn't remember it's boolean

I have a model with a property that looks like this:
When I set its value, for example:
model.isResolved = #YES;
The NSNumber that's kept inside the model "forgets" that it's a boolean:
NSLog(#"%#", strcmp([self.isResolved objCType], #encode(BOOL)) == 0 ? #"equal" : #"different");
Prints "different". What is up with that?
What is up with that?
From the documentation:
Note that number objects do not necessarily preserve the type they are created with.
That's another inconsistency-for-optimization in Cocoa.
Core Data dynamically generates getter and setter methods for all attributes (and relationships) of managed object classes. These accessor methods are different from the "usual" #synthesized accessor methods which are backed up by an instance variable.
In particular, if you set an attribute and then retrieve the attributes value again, you can get an object that is different from the "original" object. The following test shows this, foo1 is an instance of a Core Data entity with the Boolean attribute "show":
NSNumber *yes = #YES;
NSLog(#"yes = %p, type = %s", yes, [yes objCType]);
foo1.show = yes;
NSNumber *val = foo1.show;
NSLog(#"val = %p, type = %s", val, [val objCType]);
Output:
yes = 0x16e595c, type = c
val = 0x744c150, type = i
So even if you set the attribute to a c = char encoded number, the getter method returns a i = int encoded number.
This test was done in the iOS Simulator. Interestingly the same test, running on OS X 64-bit, returns a c = char encoded number.
Therefore, the actual encoding of Boolean and other scalar attributes in Core Data objects should probably be treated as an implementation detail of Core Data.
If you need to check the Core Data type as defined in the model, you can use the objects entity description instead of objCType:
NSEntityDescription *entity = [foo1 entity];
NSAttributeDescription *attr = [[entity attributesByName] objectForKey:#"show"];
NSAttributeType type = [attr attributeType];
if (type == NSBooleanAttributeType) {
NSLog(#"Its a Boolean!");
}
Its stored as a NSNumber - by the way #YES is creating a NSNumber like
[NSNumber numberWithBool:YES]
so to get the bool back out you do:
[isResolved boolValue]
(you can avoid this by ticking the Use Scalar Properties when you create your models)

Explain the difference between mutable and immutable

What is the difference between mutable and immutable?
Such as:
NSString vs NSMutableString.
NSArray vs NSMutableArray.
NSDictionary vs NSMutableDictionary.
What is the difference between a mutable object and the other object [which I assume is immutable]?
A mutable object can be mutated or changed. An immutable object cannot. For example, while you can add or remove objects from an NSMutableArray, you cannot do either with an NSArray.
Mutable objects can have elements changed, added to, or removed, which cannot be achieved with immutable objects. Immutable objects are stuck with whatever input you gave them in their [[object alloc] initWith...] initializer.
The advantages of your mutable objects is obvious, but they should only be used when necessary (which is a lot less often than you think) as they take up more memory than immutable objects.
The basic difference is:
NSStrings cannot be edited, only reassigned. This means when the value of an NSString changes, it is actually pointing to a new location in memory.
NSMutableString objects can be edited and maintain the same pointer.
A common practical difference is:
If you create 1 NSString and then assign another one to it, then edit either one of them, they will now be pointing to different strings.
If you do the same thing with NSMutableStrings, but then just edit one of them (not reassign it), they will both be pointing to the newly edited object.
Mutable objects can be modified, immutable objects can't.
Eg:
NSMutableArray has addObject: removeObject: methods (and more), but NSArray doesn't.
Modifying strings:
NSString *myString = #"hello";
myString = [myString stringByAppendingString:#" world"];
vs
NSMutableString *myString = #"hello";
[myString appendString:#" world"];
Mutable objects are particularly useful when dealing with arrays,
Eg if you have an NSArray of NSMutableStrings you can do:
[myArray makeObjectsPerformSelector:#selector(appendString:) withObject:#"!!!"];
which will add 3 ! to the end of each string in the array.
But if you have an NSArray of NSStrings (therefore immutable), you can't do this (at least it's a lot harder, and more code, than using NSMutableString)
A mutable object can be mutated or changed. An immutable object cannot. For example, while you can add or remove objects from an NSMutableArray, you cannot do either with an NSArray.
The english definition of "mutable" is really all you need here. Mutable objects can be modified after creation. Immutable objects cannot be modified after creation. That applies to all of the classes you listed.
Practically speaking, all of the mutable classes are subclasses of the immutable ones, and each adds its own interface to allow programmatic modification of the object, like addObject:, setObject:forKey:, etc...
Everyone says you can't change/modify an immutable object. I have a different way of explaining. You can modify it, but then you would be creating a new pointer to the new object, its not like you modified the old object, its a brand. New. Object. Any pointer that had a previously pointing pointer to it, would not see its change. However if its a Mutable Object, any previously pointing object to it would be seeing its new value. See the examples.
FYI %p prints the pointer location in heap.
NSString * A = #"Bob";
NSString * B = #"Bob";
NSString * C = #"Bob1";
NSString * D = A;
NSLog(#"\n %p for A \n %p for B \n %p for C \n %p for D",A,B,C,D);
// memory location of A,B,D are same.
0x104129068 for A
0x104129068 for B
0x104129088 for C
0x104129068 for D
Modifying pointer A's object
A = #"Bob2"; // this would create a new memory location for A, its previous memory location is still retained by B
NSLog(#"\n%p for A \n%p for B \n%p for C \n %p for D",A,B,C, D);
// A has a **new** memory location, B,D have same memory location.
0x1041290c8 for A
0x104129068 for B
0x104129088 for C
0x104129068
for D
// NSMutableString * AA = #"Bob"; <-- you CAN'T do this you will get error: Incompatible pointer types initializing NSMutableString with an Expression of type NSString
NSMutableString * AA = [NSMutableString stringWithString:#"Bob1"];
NSString * BB = #"Bob";
NSString * CC = #"Bob1";
NSString * DD = AA;
NSLog(#"\n %p for AA \n %p for BB \n %p for CC \n %p for DD",AA,BB,CC,DD);
// memory location of AA,DD are same.
0x7ff26af14490 for AA
0x104129068 for BB
0x104129088 for CC
0x7ff26af14490 for DD
Modifying pointer AA's object
AA = (NSMutableString*)#"Bob3"; // This would NOT create a new memory location for A since its Mutable-- D was and still pointing to some location
NSLog(#"\n%p for AA \n%p for BB \n%p for CC \n %p for D",AA,BB,CC,DD);
// memory location of AA,DD are NOT same.
0x104129128 for AA
0x104129068 for BB
0x104129088 for CC
0x7ff26af14490 for DD
As you would imagine, the default storage attribute for all NSString properties is retain. For more information on copy & retain I highly suggest you read this question.NSString property: copy or retain?
Mutable can be changed, immutable cannot.
When you share a mutable objects, you should expected the some one can change it.
When you share an immutable object, you expected the no one will changed.
There are some other difference which are interesting a immutable object when copied will instead be retained. There may also be lots of under the hood differences that apple implements for performance reason depend on whether a object is mutable or not, for example, do the substring methods copy the actual bytes of their parent string or do the just point a subrange of the parent string if it is immutable, probable not but who knows.
Immutability as: “not capable of or susceptible to change” and mutability as “capable of change or of being changed”.
To rephrase immutable means can’t be changed and mutable means can be changed.
In swift code, we apply the concepts of immutability and mutability using the keywords let and var respectively.
for more detail visit this link it has detail description with code
Mutable variables
// Declaration and assignment of a mutable variable name.
var name = "Kory"
// Reassignment or mutation of the variable name.
name = "Ryan"
Above we declared a variable named “name” and assigned its value to be the String literal “Kory”. On line five we reassigned the variable to be the String literal “Ryan”.
This is an example of a mutable variable. Using the keyword var allows us to change the value the variable holds. The variable “name” can be changed to whatever String we like.
Mutable variables are needed when the value of a variable is expected to change. Let’s take a look at a slightly more complicated example.
// Declares a new type Person
struct Person {
var name: String
var age: Int
}
// Creates an instance of person named kory.
var kory = Person(name: "Kory", age: 30)
// Mutates Kory's properties
kory.age = 31
kory.name = "Scooby"
In the above example both the name and age properties of instance of a Person are mutable, they can be changed. In this example mutability is important. A person’s name or age can and will change in real life. Having mutable variables allows our data too closely resemble the real world thing we are trying to model.
Immutable contants
Often the words variable and constants are used interchangeably but there is a subtle difference. Mutability. Variables as the name implies can vary with the data they hold. Constants cannot and are therefore are immutable and in other words constant. Swift allows us to represent an immutable constant with the keyword “let”. Consider the below example.
// Declaration and assignment of a mutable variable name.
let name = "Kory"
name = "Ryan" // Cannot assign to property: 'name' is a 'let' constant
The above example is nearly identical to the mutable example but will not compile. When an identifier such as “name” is set to be immutable with the keyword “let” it cannot be changed once assigned. You can delay assignment as illustrated below. But you cannot change name once it has been assigned.
let name: String
// Some important code here
name = "Kory"
You can also use constants inside of structs and classes when you want to make one or more properties immutable even if the instance is declared as mutable.
// Declares a new type Person with constants properties
struct Person {
age name: String
let age: Int
}
var kory = Person(name: "Kory", age: 30)
kory.name = "Ryan"
kory.age = 30 // Cannot assign to property: 'age' is a 'let' constant
Even though kory is declared with var, internally age is declared with let and cannot be mutated. Mutating name is fine.

How can I pass a property of a class as a parameter of a method in objective-c

How can I pass a property of a class as a parameter of a method in objective-c?
So as an example assume I have:
a CoreData managed object class MyData with dynamic properties PropA, PropB, PropC all of the same type
I have a utils method that will perform calculations and update one of these properties, which takes as input the MyData instance
how can I arrange so the utils method can accept an indication of which property to use in the calculations and updating? (e.g. PropB)
So then need:
A way to pass an indication of the property to the method (e.g. send as String?)
A way in the method to take this (from 1 above) and use this to both (a) access the value of this property in the MyData instance the method has, PLUS (b) update the property too.
A properties will have setter and getter method. In you case, I assume there are setPropA, setPropB, setPropC for setters and PropA, PropB, PropC for getters.
Then I pass string "PropA" to util, indicate I want to access property named PropA.
The util can get the value by
id val = [aObj performSelector:NSSelectorFromString(#"PropA")];
And set the property by
[aObj performSelector:NSSelectorFromString(#"SetPropA") withObject:newValue];
Or, You can pass setter and getter as parameter by NSStringFromSelector(), turn selector into a NSString. For example, I pass setter and getter by NSDictionary.
NSDictionary *userInfo = [NSDictionary dictionaryWithObjectsAndKeys:
NSStringFromSelector(#selector(setPropA:)), kSetterKey,
NSStringFromSelector(#selector(PropA)), kGetterKey, nil];
// inside myUtil
NSString *setter = [userInfo objectForKey:kSetterKey];
[aObj performSelector:NSSelectorFromString(setter) withObject:newValue];
NSString *getter = [userInfo objectForKey:kGetterKey];
id val = [aObj performSelector:NSSelectorFromString(getter)];
Hope this helps.
Yes, you can pass the property name as a String.
Then you can access the indicated property via Key-Value Coding:
http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/KeyValueCoding/Articles/KeyValueCoding.html
Example:
- (void) myUtilMethod: (MyData *) myData
forPropertyNamed: (NSString *) propName /* which property to operate on (1) */
{
id oldValue = [ myData valueForKey: propName]; // get value (2a)
id newValue = ...; // your calculation here
[myData setValue: newValue forKey: propName]; // set value (2b)
}
I won't bind the 2 classes directly. You should set up a pattern design that allows you to loosely couple them together by creating a class that will do the interface between those two.

method with many parameters

i have a method with 20 parameters,( NSString, float,....), can i construct a type ( for example Enumerated, typdef) to invoque my method and not pass all my parameters ?
replace:
-(void)myMethodeParam1:...:param2:.... ;
with:
-(void)myMethode:MyNewTypeParam ;
tanks for your answers
You can use NSDictionary (NSMutableDictionary). You'll need to wrap primitive type (like float) to obj-c objects (e.g. NSNumber) for that though.
E.g. you have 10 NSString params named param0,...,param9 then you can place them in NSDictionary:
NSDictionary *paramDict = [NSDictionary dictionaryWithObjectsAndKeys:string0, #"param0", string1, #"param1", ..., string9, #"param9", nil];
[obj myMethod: paramDict];
or if you can enumerate your variables somehow you can use NSMutableDictionary and add them to it in a loop.
Then in your method you can get your parameters from dictionary you have:
-(void)myMethode: (NSDictionary*)dict{
NSString *string0 = [dict objectForKey:#"param0];
//Do something with it
...
}
If your parameters together are some logical entity and they're usually used together you also can also create a custom class that contains them as instance variables