Getting a property from parent class - ios

I've added a view controller as child like this:
UIViewController *sendViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"send"];
[self addChildViewController:sendViewController];
In the sendViewController I got this property:
#property (strong, nonatomic) IBOutlet StringInputTableViewCell *nameCell;
and in that class I can do something like self.nameCell.textField.text = #"test"; to set the textField to test
But how can I get this text thats filled in the textField in the parent class?

You are mixing model and view, thus breaking the MVC design pattern.
You should not try to read what is the content of a UI element. Rather you should have all the data (i.e. model) and the view (i.e. the UI, such as text fields) managed by a controller.
There are (easy) ways to get to this information, but I strongly advise you not to go down that road!

Basic inheritance between the parent and child class should allow you to pass the property forward.
You'll need to create a child object of the class say obj. Then to get the text value of the field you'll use (in the parent class)
id obj = [[ChildClassName alloc] init];
NSString *myChildsText = obj.nameCell.textField.text; // will get the value #"test" as assigned in the childclass.
Or of course, you can create a getter and setter in the Child Class for your #property. For example ::
- (IBOutlet)nameCell {
// returns the value
}
- (IBOutlet)setNameCell :(StringInputTableViewCell)newValue {
//set the value to the #synth value here…
}
then you can call the child objects getters/setters as below ::
NSString *text = [obj nameCell]; //etc etc

You can use 4 approaches in here
a) keep reference to you childviewcontroller -> get the value directly
b) use delegate method ( best for observing changes in your textfield )
c) send NSNotification -> this comes with overhead, well at certain points it can help you a lot
d) KVO

Related

IOS Data Between View Controllers

I have a navigation controller with 2 view controllers, A and B.
A and B both have a property
#property (strong, nonatomic) NSString *string;
string is created in controller A and passed to controller B
ViewControllerB.string = self.string;
[self.navigationController pushViewController:ViewControllerB];
In View Controller B, string is modified and when I pop to View Controller A, the value of string has not changed.
Since they both hold a strong reference to it, shouldn't string be changed in both View Controllers?
Am I missing something?
In View Controller B, string is modified
This is impossible since you're using NSString, not NSMutableString. If you replace it within ViewControllerB:
self.string = #"some other string";
Then you are setting ViewControllerB's string property to reference that new string, but other references to the original string are not affected.
If you really want both view controllers to modify the same string, use NSMutableString. But shared mutable state is probably bad. Instead, consider using an intermediary class (like a data source), or the delegate pattern for ViewControllerB to hand ViewControllerA an updated string.

Non-Object Attribute in Core Data, transient properties

Feel lost after reading this section: A Non-Object Attribute
According to the Basic-Approach also contained in above link, I should have 2 attributes in my custom-code when handling "transient properties":
1st attribute, for the actually-wanted (un-supported) custom type => transient attribute
2nd attribute, for shadow-representation (concrete supported) type => persistent attribute
......
My reading was very enjoyable, until reached "A Non-Object Attribute" section, which puzzle me deeply, as quoted below:
...When you implement the entity’s custom class, you typically add an instance variable for the attribute. ...
《 OK, I can follow this...make an iVar is no big deal》
If you use an instance variable to hold an attribute, you must also implement primitive get and set accessors
《 OK, I know how to do primitive-accessor. why need them? because internal-optimized-storage inside MO can be efficiently used, I guess.》
#interface MyManagedObject : NSManagedObject
{
 NSRect myBounds; // I assume this suppose to be the **transient attribute**
}
#property (nonatomic, assign) NSRect bounds; // I assume this is the **persistent attribute**
#property (nonatomic, assign) NSRect primitiveBounds; // because complier forces me to implement below primitive-accessors ?
#end
- (NSRect)primitiveBounds
{
return myBounds; // accessing iVAR storage for **transient attribute**? I hope so
}
- (void)setPrimitiveBounds:(NSRect)aRect
myBounds = aRect; // accessing iVAR storage for **transient attribute**? I hope so
}
From here down below, I have... too many ???????????? unsolved
- (NSRect)bounds
{
[self willAccessValueForKey:#"bounds"]; //KVO notice of access **persistent attribute**, I guess
NSRect aRect = bounds; //will this invoke primitive-Getter ???
[self didAccessValueForKey:#"bounds"];
if (aRect.size.width == 0) //bounds has not yet been unarchived, Apple explained
 {
NSString *boundsAsString = [self boundsAsString]; // unarchiving pseudo method, I guess
if (boundsAsString != nil) //if that value is not nil, transform it into the appropriate type and cache it...Apple explained.
{
bounds = NSRectFromString(boundsAsString); //will this invoke primitive-Setter???
}
}
return bounds;
}
I put my final question list here:
1, do I STILL need to have 2 attributes to handle NON-Object-Attribute, transient attribute and persistent attribute?
2, how can iVar "myBounds" be represented/connected with "#property bounds"? Is this "#property bounds" the modeled-property in a MOM?
3, what is the purpose of implementation of primitive-accessor here? for enforcing me write KVO (will...did...) methods pair? for transferring values (in and out) between iVar "myBounds"and "#property bounds"?
4, in this line of code
bounds = NSRectFromString(boundsAsString); //will this invoke primitive-Setter???
is primitive-Setter called OR public/standard-Setter gets called? Why?
In iOS, there are the very convenient NSStringFromCGRect and CGRectFromNSString functions. Why not just use those and store a string?
Your questions:
Yes, you need the 2 attributes, as explained in the documentation.
Yes, this is based on the managed object model. The primitiveX name for x is generated / interpreted automatically.
You need the primitive accessor methods here to make it KVC - which is not the case with primitives.

Access what property of the sender was passed into a method

This may be a ridiculous question, but I have a method like this in my view controller:
[self registerProperty:self.currentUser];
and in the implementation of registerProperty: I would like to get the string "currentUser".
I'm doing this because I want to observe the property of the view controller "currentUser", not the actual user object, so I can intercept the setter.
At the moment I'm checking the Objective-C runtime for a list of all properties of the view controller and checking if the value of the property equals the currentUser object:
-(void)registerProperty:(id)property
{
for (NSString *propertyName in [self allPropertiesOfClass:[property class]])
if ([property isEqual:[self valueForKey:propertyName]])
NSLog(#"The property passed into the method is %#", propertyName);
}
The problem with this is that I may have two properties that both contain the same user object, in which case either of them would pass that test. How could I fix this?
Pass in the object whose property you want to observe and, separately, the property name as a string. That is, mirror (a subset of) the arguments of the KVO -addObserver:... method.

Setting delegate in "unrelated" class

I am having trouble using a protocol to get some data from another class. I can't see how to set the delegate in a class that doesn't segue to the MVC that needs the data. I create the protocol in the MVC and implement the method(s) in some arbitrary class that contains the data I need. But I can't see how to refer back to the delegator MVC to set the delegate if there is no reference to the delegator MVC, like when you use segue.destinationViewController.
If MyViewController can create the instance of SomeDataClass, then you set the delegate there. If there is no connection between the controllers, then you might use an NSNotification instead. That is a completely anonymous way to connect instances -- you send out a notification, and any class that registers for that notification can get it.
Something like this?
#implementation MyViewController {
// keep a pointer to the data supplier class as long as this object exists
// so that it will continue to exist and send me delegate callbacks
SomeDataClass *myInstanceOfSomeDataClass; // instance variable to point to my data supplier
}
// ...
- (void)updateMyView {
if (myInstanceOfSomeDataClass == NULL) // I haven't created an instance yet
myInstanceOfSomeDataClass = [[SomeDataClass alloc] init];
SomeType *results;
if (instantResultsAreAvailable)
results = [myInstanceOfSomeDataClass getResults];
if (resultsAreOnlyAvailableFromDelegateCallback)
myInstanceOfSomeDataClass.delegate = self;
}
- (void) delegateCallbackMethod {
//...
}
#end
you want to pass data from one from viewcontroller to another class? just go through this Passing Data between View Controllers

Pass Value as Parameter from View Controller to Method of Entity Class

I have a ViewController with a UITextField. The user enters a string of characters into the textField, clicks a done button and then this value should be passed to a method in the entity class. I know I need to pass this value as a parameter but I'm getting stuck.
I've tried to pass this value by adding a parameter to the end of the clickDone IBAction for the done button with no luck. Thank you for even the smallest bit of help or point into the right direction.
- (IBAction)doneClicked:(NSString*) name {
...
}
I've tried creating an ivar for ViewController in my entity class h file but Xcode asks "Unknown type name 'ViewController'; did you mean UIViewController?
#interface EntityClass : NSManagedObject{
ViewController* refVC;
UITextField* textBox;
}
and then use
self.name = self.refVC.textBox.text;
in my method in entity class m file to return the NSString self.name
Don't pass the ViewController to the Entity Object. Instead, update the entity object's property in your doneClicked action.
- (IBAction)doneClicked:(NSString *)name {
myObject.name = name;
}
I figured it out. This is my final code. It works. Help is no longer needed.
Thanks!
- (IBAction)doneClicked:(NSString*) name {
...
superClass.name = headingText.text; //headingText is UITextField on ViewController
[superClass doSomething];
...
}

Resources