I started to develop my singleton class but I have a problem.
What I want to do is have a search objects containing the values of the search form that I could use in several views.
I want to have the ability to get the singleton in any view in order to perform the search or build the search form.
So I have a set of values with a boolean for each to know if the variable has been initialized by the user or not, cause not all the search fields needs to be filled in.
For example :
NSString name= Bob;
BOOL nameFilled =True;
NSString adress= nil;
BOOL adressFilled=false;
NSNumber numberOfChilds = 0;
BOOL numberOfChildsFilled = false;
So my problem is that I can't retain the boolean in my header file because it's not a class.
How can I do, is there a better solution than what I presented above?
Hope I have been clear
You dont need to have this BOOLean value to see if it is filled, why not just use the object itself to see if it has been initialized so something like
if(name==nil)
//this means i t hasnt been initialized
else
//this means it has
Instead of using int, use NSNumber. Then, for objects that haven't been specified, use 'nil', which is distinct from an NSNumber with 0 as a value.
You don't need to #retain BOOL or other primitive types in Objective-C - you only need use that for object types.
Seriously, don't implement a singleton. It isn't necessary for this application. You should have a model class to handle this.
Try using dependancy injection and/or plist files to save the information. You'll have a much better time debugging and extending functionality.
Related
I'm developing an iPad App and need some help.
Through a button within my App I want to create one object at a time.
So every time the button is touched one object should be created.
The problem I have is: I want to assign each object a dynamic name to identify this object.
This would be something like: form0, form1, form2, ..., formN.
This Name corresponds to an instance variable within every object.
So the form1 instance has a number attribute which is 1.
But how do I assign this form1, form2, etc. to a new instance?
I tried to initialize a new instance with the return of a method which creates the formX-String:
-(NSString*)giveMeName{
NSString* simpleName = #"form";
NSString* newName = [simpleName stringByAppendingString:[NSString stringWithFormat:#"%d", questionCounter]];
return newName;
}
where questionCounter is a variable which holds the int identifier for both formX and the instance number attribute.
But when I want to initialize a new instance with this function as name it's not working:
TSForm* [self giveMeName] = [[TSForm alloc] initWithInt:questionCounter headline:headlineText intro:introText];
Obviously I got something wrong with the inner working of Objective-C.
Please help me out.
what you're trying to do isn't really possible. One way that you could achieve the affect you're looking for is using an NSDictionary. For every TSForm object you create, you add that object to the dictionary with the key of the giveMeName return value.
So you start by creating your dictionary:
NSMutableDictionary *formDict = [[NSMutableDictionary alloc] init];
Then, every time you create an object, add it to the dictionary:
id *newTSForm = [[TSForm alloc] init]; // Or however you create a TSForm
[formDict setObject:newTSForm forKey:[newTSForm giveMeName]];
Then when you want to pull out the form you're looking for, you just ask the dictionary based on the name you provided:
[formDict valueForKey:nameOfForm]; // nameOfForm is the name provided by giveMeName
Hope this helps!
use NSMutableArray and keep adding your items there.
Even if what you are trying to do is technically possible, that's using tricsk in low-level objective-C runtime and KVC stuff and so on for nothing.
Using a simple NSMutableArray to keep track of all you instances (and using the index in the array to know which form you are dealing with) is the way to go.
I don't think you really need your unique identifier stuff for that (if so, you are probably thinking about your project the wrong way), as long as you have a way in your code to differentiate each form and manipulate them (the first form created will then be at index 0, the second at index 1… of your NSMutableDictionary)
If you really need this special unique identifier anyway for some strange reason, you can still use an NSMutableDictionary and use the unique identifier as your key of your dict and the form as the associated value. But you should probably think twice about your architecture ad the real need for this before, as it seems quite strange app architecture/design to do so based on your description of your needs in your question.
What you are looking for is some kind of variable variable, which don't really exist in objective-C.
This question (Objective C Equivalent of PHP's “Variable Variables”) has some different suggestions for getting similar results.
I want to populate [MyClass class] from a JSON string.
I use json-framework to get the NSDictionary, and it's dead easy to instantiate and setValue: forKey:... on my data object.
But for more complex data objects with classes as members of MyClass,
ie:
MyOtherClass *classNoTwo
I tried with
Class test = object_getClass(myClass.classNoTwo);
id foo = [[test alloc] init];
But foo is nil/null. The only way I found to get around it is to in my init method of MyClass is to alloc memory for it, and later replace it.
I would also like to know how to get rid of the myClass.classNoTo reference, as I am not supposed to know all the properties in my general parser.
Please don't just tell me to read the documentation, because I've done that, and I can't figure it out.
Thanks in advance
Try calling class_getProperty() to access a property of a particular name and then property_getAttributes() on the property returned by the first function. This will return a string that encodes the property's attributes, including the type. The format of the string is explained in Property Type Strings in the documentation.
Finally, when you have derived the type of the property, use NSClassFromString() to instantiate an object.
Also see the docs for the two functions mentioned for more details.
I have written a very simple dependency injection container called Factory. I do not get your question entirely, but the problems we solve look similar. Take a look at my sources, they are very simple and should get you started. You might be interested especially in the ClassAnalyzer class. It’s just a hack, but you should be able to get what you want from there.
I have an array filled with instances of a custom class which contains two String properties, firstname and lastname. Both have a getter method which is equal to the name of the property itself. There is also a method for retrieving the Full name of a person called "getFullName". Consider the example below.
CustomClass *person = [[CustomClass alloc] ...];
person.firstname // Returns "Thomas"
person.lastname // Returns "Meier"
[person getFullName] // Returns "Thomas Meier"
Now I would like to sort this Array by Fullname in a descending Order. I have been looking at some array sorting methods but was not quite able to figure out how to go about this. I guess that I have to create some kind of comparison function which compares two elements, yet how do I tell the SDK which values to pass to this method and where should I place it (in the custom class or in the class where the sorting happens?). Maybe there is another/better way of going about this? Admittedly I have close to none experience with sorting arrays.
Thanks a lot for your help!
Ps. The code should run on iOS 3.2
There are a couple ways to do this. One is to put a comparison method on the custom class. Call it -compare: or something like that. That method should take another object of the same custom type as its input. It should return NSOrderedAscending, NSOrderedDescending, or NSOrderedSame, depending on the result of the comparison. (Inside this compare function is where you look at your own fullName versus the passed-in object's fullName.)
Then you can use NSMutableArray's -sortUsingSelector: method, like this:
[myArray sortUsingSelector:#selector(compare:)];
This works on all versions of iOS. There are block comparison methods available in 4.0+.
What is the easiest way to create a global object. I have tried declaring the object outside the method with no luck.
#implementation UV_TouchpadViewController;
NSMutableString *string = [NSMutableString stringWithFormat:#"text"];
Very close -- you can't initialize a non-local variable with a non-const expression, and a method call is inherently non-const, even if it looks like it should be. So basically, change it to
NSMutableString *string;
but if it's only going to be used inside the implementation file (eg. other classes would only get at it through UV_TouchpadViewController, not get/set it directly (this is also the recommended pattern)), then qualify it as static, like so
static NSMutableString *string;
If on the other hand you do want to be able to access it directly from outside UV_TouchpadViewController, leave off the static, but add
extern NSMutableString *string;
to your header file (outside the class #interface), and whomever includes the header will be able to access it. (Note that you could instead just put NSMutableString *string; in your header file, however this is quickly becomes unclear)
Also, if you are trying to do this for a singleton class, (I can't think of a good reason to have a global mutable string -- you know they're not thread safe right?) I recommend reading Apple's docs on singletons first, where they suggest you use ivars, not global variables, even for singletons. However, UV_TouchpadViewController should not even be a singleton (if it is in any way a view controller), it should just have a single instance, if that's all you want.
If on the other hand you just want all UV_TouchpadViewControllers to have access to this one variable, note that across almost all languages this is considered a bad design pattern (globals are bad), and that you should instead stick it in, say, your app delegate (which is guaranteed to have a single globally accessible instance), where it can be an ivar+accessors, and generally considered a setting and (with a little extra code) persisted.
EDIT:
If you want to have a singleton that maintains global state, which I still recommend against -- you should create a class, like for instance ApplicationState, which handles all of the application's global state as a model object in the traditional model-view-controller pattern. I wont go into detail here because that would be highly redundant of a google search.
In your Application Delegate, somewhere, add an ivar ApplicationState *state, and a corresponding #property (and #synthesize in the implementation file).
There are few easier ways to shoot yourself in the foot than by using global variables.
You should never expose a dumb object like a string which has no access control to every object in the app. Any random piece of code anywhere in the app can change the mutable string leading to chaos as the app grows larger.
Usually when people want a global variable what they actually need is either the user defaults or a data model.
The user defaults (NSUserDefaults) is the preference persistence system that saves application state and user's settings both between launches and as the app runs. You can park small bits of data, such as strings, in the defaults and access them easily from anywhere in the app.
A data model is dedicated object that holds the applications data and manages access to it such that only the data model has final control. This makes it easy to tell what has changed the data and how. The data model can be a simple custom class or something elaborate such as core date. You can park the data model in the app delegate or create it as a singleton as the other answered have explained.
I have been using the Apple API for years and I have never needed to use a real global variable. If you think you need one, you probably have misunderstood something about application design in the Apple API. You might want to post a question explaining what you're trying to do with a global variable and what the best strategy should be for doing it without the dangers of using a global variable.
Do you need it for each instance of the class? If so, you should make it an Instance variable. Put
NSMutableString *string;
In your header
And then you can set it in any method in your class.
If this isn't what you meant, update your question or comment.
You can achieve that by implementing getter and setters in the delegate class.
In delegate .h file
Include UIApplication delegate
#interface DevAppDelegate : NSObject <UIApplicationDelegate>
NSString * currentTitle;
- (void) setCurrentTitle:(NSString *) currentTitle;
- (NSString *) getCurrentTitle;
In Delegate implementation class .m
-(void) setCurrentLink:(NSString *) storydata{
currentLink = storydata;
}
-(NSString *) getCurrentLink{
if ( currentLink == nil ) {
currentLink = #"Display StoryLink";
}
return currentLink;
}
So the variable you to assess is set in the currentlink string by setters method and class where you want the string ,just use the getter method.
AppDelegate *del=(AppDelegate *)[[UIApplication sharedApplication]delegate];
TO set:
[del setCurrentLink];
TO Get:
NSString *value=[del getCurrentLink];
All the best
Add:
NSMutableString *globalString = nil;
to any .m file of any object. The nil initialization adds a little safety, since nil objects can be "safely" messaged without outright crashing the app.
Add:
extern NSMutableString *globalString;
to the headers of any other objects that needs to access this global.
Add:
if (globalString == nil) {
globalString = [ [ NSMutableString stringWithFormat:#"text"] retain ];
}
to the init of any class(es) that could be the very first to touch this global, or to some init that happens even earlier.
Globals are a less verbose form of singleton, but with no access restriction or tracking. Use with caution.
actually as per my r&d i got that by use of extern we have to create an instance but the final thing is to #define your variable and can access any where you want without any creating of instance and other thing just directly use variable by its name....
Say I have the following Objective-C class:
#interface Foo {
int someNumber;
NSString *someString;
}
and for reasons I won't get into here, I want to use KVC to update, in a generic fashion, the values for those variables:
[f setValue:object forKey:#"someNumber"];
or
[f setValue:object forKey:#"someString"];`
If object is a string and I'm updating the someNumber variable, it seems that I need to know to use an NSNumberFormatter to get an NSNumber and then Cocoa automatically converts that to an int inside setValue:forKey:.
Is there any way to avoid this custom code and have Cocoa infer the conversion to an int from a string, or do I need to catch this situation each time and handle it myself?
The following code should handle the conversion automatically, as long as the object parameter is a member of a class that implements integerValue.
Note that both NSNumber and NSString implement this method.
- (void)setValue:(id)object forKey:(NSString *)key
{
if ([key isEqual:#"someNumber"])
{
someNumber = [object integerValue];
}
//...
}
edit: (side note):
You can avoid writing the method yourself by using objective-c properties. The default implementation of setValue:forKey: will do the work for you, as long as you create properties for someNumber and someString.
You should do the conversion yourself with a number formatter, it gives you finer control than anything that the framework might consider to be appropriate. It is also, probably, not a good idea to use a single instance of an object to update the values for your ivars. More appropriately, you could perform your update based on the class of the object (providing you are not storing in an id by querying the runtime as to the class of the object by means of object_getClassName. More information is available in the Objective-C 2.0 Runtime Reference. But in general, you will likely find bugs in your code as a result of doing things that way.
I'm with wisequark on this one. I think of setValue:forKey: as equivalent to calling the setter directly. If you had a method:
- (void)setSomeValue:(NSInteger)aValue
You wouldn't expect to be able to pass in an NSString and hope the method can figure it out.
Put another way, a key value gives you access to a property, and that property has a type. When using KVC, numbers just get wrapped in an NSNumber object so that there's only one setValue:forKey: method. Therefore, I say it's always the calling code's responsibility to package up the string in an NSNumber object.
It's times like these I lament that Cocoa Touch doesn't support bindings. Bindings would allow you to add a value transformer that could handle the transformation from string to number automatically for you. Maybe in the next version!