Passing by reference [closed] - ios

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 9 years ago.
NSString *firstName2 = #"foo";
NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:firstName2, #"storeData", nil];
NSString * __strong *storeData = NULL;
storeData = &[dict objectForKey:#"storeData"];
*storeData = #"bar";
When setting storeData, I want that firstName will be changed as well.
I get a build error: "address expression must be an lvalue or a function designator"
How should I do it?
EDIT
In the big picture, I'm trying to create a subclass of UITextField that gets a reference to a variable and sets it in the textField:DidEndEditing method.

That code doesn't make sense and C (Objective-C) doesn't work that way.
The return value of a method is generally in a register and, thus, has no address. Even if it did, getting pointers to the innards of objects so you can muck with them directly is a really bad design pattern.

I don't think you need to subclass UITextField to accomplish your goal. In any case, the solution you are trying to implement has a philosophical flaw because it breaks encapsulation.
How to solve? Your text fields are almost certainly owned by a view controller subclass. So long as that object conforms to the UITextFieldDelegate protocol and each of the text fields has the controller object as its delegate, you should be good. The only task remaining, then, is to map the text fields to a property on your controller or other object.
Let's assume for a second that your controller owns an instance of some data object whose properties you are trying to set with the controller's UI. We'll call it MyDataObject:
#interface MyDataObject : NSObject
#property (nonatomic, strong) NSString *firstName;
#property (nonatomic, strong) NSString *lastName;
#end
#implementation MyDataObject
#end
To map the text fields to the properties on this object, you could do something like:
- (NSString *)propertyNameForTextField:(UITextField *)field {
static NSDictionary *map;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
map = #{(id)self.fnField: #"firstName",
(id)self.lnField : #"lastName" };
});
return map[field];
}
Then in our UITextFieldDelegate method, we do:
- (void)textFieldDidEndEditing:(UITextField *)textField {
[_dataObject setValue:textField.text forKey:[self propertyNameForTextField:textField]];
}
Note that I'm doing no error checking, validation, etc. etc. This is just to show one way of mapping UI elements to properties they should affect. This is on iOS; on Mac OS bindings are available for this use-case.

Related

Setters, Getters and Exposing real core data types, how do I do that?

I have a core data entity that has a structure like this:
number (integer 16),
reference (binary)
image (binary)
I have created a class for that entity.
The header of that class has these declarations for the entity property.
#property (nonatomic, retain) NSNumber * number;
#property (nonatomic, retain) NSData * reference;
#property (nonatomic, retain) NSData * image;
but in fact, these 3 properties are
number = NSInteger
reference = NSArray
image = UIImage
because I cannot store arrays and images on core data directly, I have to convert it to NSData to save but I don't care for the property being declared as NSData, because the conversion to and from NSData is something internal to the entity and should not be exposed to code outside the class.
I want these header properties to be declared like
#property (nonatomic, assign) NSInteger number;
#property (nonatomic, retain) NSArray * reference;
#property (nonatomic, retain) UIImage * image;
and I want to, for example, when I assign an array to reference that is converted to NSData internally.
I know I have to create setters and getters to do that but my problem is that the entity is already using these names. Obviously I can rename all core data entities to have a prefix like xnumber, xreference, ximage, etc., so I will have no collisions between the names/types I want to expose and those I want to hide internally.
Is there any other alternative to that? My fear is ending with a sea of references that are similarly.
What you did in your application is probably most common fail using core data. By no means you should be encouraged to use the core data classes directly as you did, do always use subclassing, categories or (best of all) use wrappers.
Since in most cases when you edit an entity in your model you wish to delete the auto generated file(s) and create new ones those files should be unmodified. This is the main reason I discourage you to use any quick fixes such as modifying the names in your model and then creating the custom setters.
Why I suggest the wrappers most is because you can build your own interface with it. You can create exactly as many methods, accessories as you need on it, you can use data protection such as having read-only parameters... So when you modify the data model there should be no difference in the application at all, when you will possibly add some extra tables for some optimisations or some internal functionality you will have no issues hiding those accessories. Other then that having an extra layer will make it very easy for you to create some caching, easy debugging since you can put a breakpoint or log to more or less any and every accessory, you can internally maintain multithreading operations...
I can understand at this point migrating your code to some other system might take a bit long but that is something you should consider. If the application is anything but almost done I suggest you do migrate it: If you create a wrapper with same properties as are already used in the application it is possible to simply change the class names where it was already used, this shouldn't take too long. If you choose to continue working as it is you will most likely encounter some much harder issues and if nothing else remember this when you will start a new application.
Edit: Wrapper explanation and example
By wrapper I mean a class instance that holds another instance and builds an interface around it. Let me show you a nice example first:
Interface:
#interface EntityWrapper : NSObject
#property NSInteger number;
#property UIImage *image;
+ (NSArray *)fetchAll;
+ (void)invalidateCache;
#end
Implementation:
#class EntityName;
static NSArray *__entityCache = nil;
#interface EntityWrapper() {
EntityName *_boundEntity;
}
#end
#implementation EntityWrapper
- (instancetype)initWithEntity:(EntityName *)entity {
if((self = [super init])) {
_boundEntity = entity;
}
return self;
}
+ (NSArray *)fetchAll {
if(__entityCache == nil) {
NSMutableArray *toReturn = [[NSMutableArray alloc] init];
NSArray *entityArray = nil; //fetch from data base
for(EntityName *entity in entityArray)
[toReturn addObject:[[EntityWrapper alloc] initWithEntity:entity]];
__entityCache = [toReturn copy];
}
return __entityCache;
}
+ (void)invalidateCache {
__entityCache = nil;
}
- (void)setNumber:(NSInteger)number {
_boundEntity.number = #(number);
}
- (NSInteger)number {
return [_boundEntity.number integerValue];
}
- (void)setImage:(UIImage *)image {
_boundEntity.image = UIImagePNGRepresentation(image);
}
- (UIImage *)image {
return [[UIImage alloc] initWithData:_boundEntity.image];
}
#end
As you can see here I am building an interface around the entity using custom setters and getters. I even create a method to fetch all objects from the data base, next step might be to fetch them with some predicate or in this case rather some custom options. I also added a most simple cache just to see the concept.
The number is now a NSInteger instead of a NSNumber which can be quite a convenience but be careful doing this as you might need to know if number is nil. For this case you could also create another property such as BOOL numberIsSet.
Pretty much the same goes for the image. You need no transformers at all, just a getter and a setter (which is pretty much the same with transformers but this approach is much more dynamic).
So creating the wrapper kind of gives you the ultimate power. The idea is to create as small interface as possible and as simple as possible. That means there are just as many methods in the header file as needed, rest is hidden. The logic behind these methods can be extremely complicated but will still be maintainable since it is a closed system (does not depend on nothing but the entity), to give you an example:
Interface:
#property (readonly) NSDecimalNumber *heavyValue;
Implementation:
- (NSDecimalNumber *)heavyValue {
NSDecimalNumber *valueA = _boundEntity.valueA;
NSDecimalNumber *valueB = _boundEntity.valueB;
NSDecimalNumber *valueC = _boundEntity.valueC;
return [[valueA decimalNumberByAdding:valueB] decimalNumberByDividingBy:valueC];
}
Now this is quite a standard procedure and will work great but this method can be quite heavy on the CPU. If this method is called a lot you might get to a point where you want to optimise by storing the result into the entity itself. So all you do is add another value into the model heavyValue and the code:
- (NSDecimalNumber *)heavyValue {
NSDecimalNumber *toReturn = _boundEntity.heavyValue;
if(toReturn == nil) {
NSDecimalNumber *valueA = _boundEntity.valueA;
NSDecimalNumber *valueB = _boundEntity.valueB;
NSDecimalNumber *valueC = _boundEntity.valueC;
toReturn = [[valueA decimalNumberByAdding:valueB] decimalNumberByDividingBy:valueC];
_boundEntity.heavyValue = toReturn;
}
return toReturn;
}
- (void)setValueA:(NSDecimalNumber *)valueA {
_boundEntity.valueA = valueA;
_boundEntity.heavyValue = nil; //this invalidates the value
}
So that is quite an extreme change in logic behind a simple getter but the rest of your code is unharmed, it still all works as it should.

Accessing Variables in another class and dividing NSString

Hy I have a problem accessing variables in another class.
Im making an app that makes note and let you study from the notes you make, for example the user makes a note that says "Oceanic dolphins: are members of the cetacean...", and when the user press a button to study it appears something like this "what are Oceanic Dolphins" then the user press a button it appears something like this "they are members of the cetacean..." the problem I have is this When i enter the ViewController that makes the question it appears empty I think the problem lies on one of the next codes
I make the Variable Globals like this
QueRes.h
#import <Foundation/Foundation.h>
#interface QueRes : NSObject
#property NSString *question;
#property NSString *response;
#end
QueRes.m
#import "QueRes.h"
#implementation QueRes
#end
I divide the NSString of the note like this
NSArray *card = [_argumentTextView.text componentsSeparatedByString:#":"];
QueRes *make = [[QueRes alloc] init];
if ([card count] >= 2)
{
make.question = card [0];
make.response = card [1];
}
the I apply the variable question and response in a ViewController like this
- (void)viewDidLoad
{
[super viewDidLoad];
QueRes *make = [[QueRes alloc] init];
_questionTextView.text = make.question;
}
then in other view controller i have the same code but apply with the response variable
Please help me I been stuck in this for weeks (I have Xcode 5 and the app runs in IOS 7)
(if you need more of the code of the program to help me fix it just tell me )
You are making a new instance of a QueRes in your viewDidLoad method. Unless the init method of QueRes sets its question and response properties to something, they will be uninitialized, which is why you are not seeing anything in your text view: there is nothing to show.
Naming the QueRes instance you make in the third code block you posted make does not make it the same instance as the instance in the viewDidLoad method, and it is not a global variable at all. It is a separate instance of QueRes.

How do I declare a global variable to be used in both the main view and the flipside view of an app? ios iphone

Okay, so I was reading here declaring global variables in iPhone project and I noticed the line with this code: [[[UIApplication sharedApplication] delegate] myNSString];.
Basically, I want a user to input something in a text field on the flipside view, then have it stored in a variable which is accessed on the main view. Ideally, the main view would be able to just read the text field from the flipside view, but this seems to be impossible (I've spent several hours each day for the past few days scouring the web and various books for an answer about how to do this and no one seems to be able to give a definitive answer). Therefore, I'm resorting to using a global variable to tackle this.
Will the code that I printed above somehow allow me to do this? I've been trying to adapt it for the past hour, but have come up with nothing except No known instance method for selector 'myNSString' and I'm not quite sure what that means in this case.
Can someone please help me out? I feel like I can keep trying different things but without some sort of help, I'm just shooting in the dark here. Thank you!
You may want to think about using a singleton to hold your data if you're set on using a global variable. There's a good tutorial on singletons here: http://www.galloway.me.uk/tutorials/singleton-classes/ -basically it's a class that can be shared throughout the application and accessed/modified by different controllers. You'd be able to create a property on it, write to that property from the flip view, and then access that property from your main view.
#import "Singleton.h"
#implementation Singleton
#synthesize yourTextField;
#pragma mark Singleton Methods
+ (id)sharedManager {
static Singleton *sharedMyManager = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedMyManager = [[self alloc] init];
});
return sharedMyManager;
}
- (id)init {
if (self = [super init]) {
yourTextField = #"";
}
return self;
}
You could call it in code by importing its header file and:
Singleton *mySingleton = [Singleton sharedManager];
the mySingleton object will have the text field attached. It can be accessed by:
mySingleton.yourTextField;
.h file:
#import <Foundation/Foundation.h>
#interface Singleton : NSObject
#property (nonatomic, strong) NSString *yourTextField;
+ (id)sharedManager;
#end
Singleton (remember about dispatch_once), static variables or NSUserDefaults. It really depends what you really need.
If you are using storyboards and just want to pass data between VC, then you can use "prepareForSegue" method (described here https://developer.apple.com/library/ios/documentation/uikit/reference/UIViewController_Class/Reference/Reference.html#//apple_ref/occ/instm/UIViewController/prepareForSegue:sender:).
Segue has "destinationController" property, so you can setup VC before showing it.

created object which store patient information. need to use it throughout the application [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
I need to find a way to make an object which stores patient information "global" to my application in objective c. Example, class A creates the object, (its basically a user name/ password screen). When they close out the application, I would like the appdelegate's applicationdidEnterBackground to read information from this object(which was created in Class A).
You have a few options:
Make your object a property on your App Delegate
Make it a singleton
One of the options is to create a singleton: https://developer.apple.com/library/mac/documentation/general/conceptual/devpedia-cocoacore/Singleton.html
You can also simply write that data inside NSUserDefaults or to a file, a read it afterwards - if you are using this only occasionally it's better idea.
Make this as a public property of your view and read it from appdelegate - however this is not best option if you later change the view to be a subview or you also lose this object when you gets deallocated.
singleton is the way:
you can make class as UserdataSingleton which overrides NSObject. which you can use all over your application to share data globally (for your case array). this code template may help you:
#import <Foundation/Foundation.h>
#interface UserDataSingleton : NSObject
{
#private
NSArray *globalArray;
}
+(UserDataSingleton *) getInstance;
-(void)saveInUserDatasingletonWithArray:(NSArray *)array;
-(NSDictionary *)getGlobalArray;
#end
and implementation file will be some thing like:
#import "UserDataSingleton.h"
#implementation UserDataSingleton
static UserDataSingleton *userDataSingletonInstance;
+(UserDataSingleton *) getInstance
{
if (userDataSingletonInstance == nil) {
userDataSingletonInstance = [[UserDataSingleton alloc] init];
}
return userDataSingletonInstance;
}
-(void)saveInUserDatasingletonWithArray:(NSArray *)array
{
globalArray = array;
}
-(NSDictionary *)getGlobalDictionary
{
return globalArray;
}
#end
usage:
#import "UserDataSingleton.h"
define USERDATASINGLETON (UserDataSingleton *)[UserDataSingleton getInstance]
......................your code...
NSArray *this_IS_Array_Populated_here_For_Global_Access = [NSArray alloc] initWith....];
[USERDATASINGLETON saveInUserDatasingletonWithArray:this_IS_Array_Populated_here_For_Global_Access];//you put your array for global access.
later some where in any other view or view controller you can get that global array for example lets say you have YourViewController class:
NSMutableArray *yourArrayFromWebResponse = [USERDATASINGLETON getGlobalArray];

Accessing Instance Method from other class in Obj-C [closed]

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 10 years ago.
First off, I am using the game engine LevelHelper.
Does anyone know the proper way to access an instanced LevelHelper helper class from another class?
For example:
I have my main gameLayer class and a hudLayer class. The hudLayer class is being imported and instanced in the gameLayer class. However i need to be able to access and manipulate the sprites that are loaded in the hudLayer class with gameLayer class.
I was recommended to use the LevelHelper helper instance method. So i create the instance method inside of my hudLayer class, and then call it inside of my init method to load the sprites. I tried using this method as an instance method and i get an error saying unrecognized selector
+[hudLayer hudLoader];
If i try using the method as a class method i get an EXC_BAD_ACCESS Error.
I cant seem to find a solution.
My code:
hudLayer.h :
+(LevelHelperLoader*)hudLoader;
hudLayer.mm :
+(LevelHelperLoader*)hudLoader
{
LevelHelperLoader* lh;
finishScreen = [lh spriteWithUniqueName:#"finishScreen"];
return lh;
}
gameLayer.h :
LHSprite* finishScreen;
gameLayer.mm :
#import hudLayer.h
-(id) init {
[self retrieveRequiredObjects];
}
-(void) retrieveRequiredObjects {
finishScreen = [[hudLayer hudLoader] spriteWithUniqueName:#"finishScreen"];
NSAssert(finishScreen!=nil, #"Couldn't find the menu!");
}
Note: This code is just to make sure my logic and implementation of this is correct.
Any help is appreciated, thanks.
Have you tried stepping through your code in the debugger to find exactly which line causes the crash?
To me it looks as if it is here:
LevelHelperLoader* lh;
finishScreen = [lh spriteWithUniqueName:#"finishScreen"];
You have declared 1h, but you haven't created it. So you are sending a message to a non-existent object.
At very least, something like
LevelHelperLoader* lh = [[LevelHelperLoader alloc] init];
would help.
A cursory glance at the documentation adds more detail:
LevelHelperLoader* loader = [[LevelHelperLoader alloc] initWithContentOfFile:#"level1"];
In the docs, this is an instance variable - which suggests that hudLoader should be an instance method, not a class method:
- (LevelHelperLoader*) hudLoader;
and you should create your LevelHelperLoader* instance in your hudLoader initialiser.
update
You say in your comment:
inside of my init method for hudLayer.mm i call
lh = [[LevelHelperLoader alloc] initWithContentOfFile:#"level1"];
and in the .h i have
LevelHelperLoader* lh;
I am not sure if this is modifications since reading my answer or not. However here are some more thoughts.
Firstly can you sort out your naming conventions. Classes should start with Capitals.
HudLayer.h
Let's declare this lh instance variable as a property in your #interface and improve it's name:
#property (strong) LevelHelperLoader* levelHelper
HudLayer.mm
Allow it to be auto-synthesized or synthesize in your #implementation as:
#synthesize levelHelper = _levelHelper;
Then in your init method
_levelHelper = [[LevelHelperLoader alloc] initWithContentOfFile:#"level1"];
and hudLoader becomes
-(LevelHelperLoader*)hudLoader
{
finishScreen = [self.levelHelper spriteWithUniqueName:#"finishScreen"];
return self.levelHelper;
}
but then ask yourself, what is -hudLoader actually doing? The line that assigns to finishscreen? Is finishscreen an iVar? Do you need it? Perhaps not. Aside from that, all -hudLoader is doing is returning your already-created instance of LevelHelperLoader. Now that your iVar is a property you can access this from gameLayer using dot-notation property syntax, and remove hudLoader altogether:
GameLayer.h
#interface
#property (strong) Hudlayer* hudLayer;
#end
GameLayer.m
-(id) init {
_hudLayer = [[Hudlayer alloc] init];
[self retrieveRequiredObjects];
}
-(void) retrieveRequiredObjects {
finishScreen = [self.hudLayer.levelHelper spriteWithUniqueName:#"finishScreen"];
NSAssert(finishScreen!=nil, #"Couldn't find the menu!");
}
This makes me wonder whether you need a hudLayer class at all (maybe it is doing other useful work)... it looks as if you can get at your levelHelper directly from gameLayer.
GameLayer.h
#interface
#property (strong) LevelHelperLoader* levelHelper;
#end
GameLayer.m
-(id) init {
_levelHelper = [[LevelHelperLoader alloc] initWithContentOfFile:#"level1"];
[self retrieveRequiredObjects];
}
-(void) retrieveRequiredObjects {
finishScreen = [self.levelHelper spriteWithUniqueName:#"finishScreen"];
NSAssert(finishScreen!=nil, #"Couldn't find the menu!");
}
To conclude, I am not suggesting you follow this code line-for-line because I have no idea the broader context of your project. But you do need to sort out your confusion between classes and instances, allocation, instantiation, local vs instance variables. Please take care with naming conventions so that you know when you are sending a message to a Class or an instance of that class, and you know when you are addressing an iVar _directly or via a #property (eg self.property). Be consistent. And think about what a class is actually doing for you.

Resources