iOS -- trying to setup a dictionary of locks - iphone

I have some code that takes an NSString as input and uses that string to create an object. I need to make sure that it does not operate on the same string twice, e.g. if called from different threads, or even if the same thread tries to do it recursively.
I can make a start by making a dictionary of my initialized objects and grabbing that object if passed the same string again. But this still leaves the problem of what happens when the object is requested a second time while other code is initializing it.
I see that Apple has provided me with the NSLock class. I am at a loss as to how to apply it to my problem. I see Apple lets me name my locks, but I don't see any way to access the lock with a given name. I suppose I could make a dictionary of locks, but even that does not seem bulletproof -- what if two threads try to make the lock of the same name at the same time?
Can anyone point me in the right direction here?

What about making a static NSMutableArray with all your strings and synchronize your code.
Of course you need to initialize the array somewhere first ;)
Maybe like this:
static NSMutableArray* myArrayWithStrings;
-(void) someMethod:(NSString*) key
{
#synchronized(myArrayWithStrings)
{
if(![myArrayWithStrings containsObject:key])
{
NSLog(#"Working with the key %#", key);
[myArrayWithStrings addObject:key];
}else
{
NSLog(#"Ignoring key '%#'. Already worked with it.",key);
}
}
}

Related

UISearch bar in two NSMutables arrays

I see item UISearchBar search two arrays and very much items and not found solution, the problem its similar, have two NSMutablesArrays "subdetail" and "sublista" its show in Cell cell.textLabel and cell.detailTextLabel.
I try UISearchbar but i tray with NSPredicate and not run, try with NSRange and have more errors, i am desperate.PLEASE help me, any comments agree.
This its my code in Search:
- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope
{
NSMutableDictionary *playas = [NSMutableDictionary dictionaryWithObjectsAndKeys:sublista, #"nombre", subdetail, #"localidad", nil];
[alldata addObject:playas];
for(NSDictionary *playas in alldata){
NSString *nombre = [playas objectForKey:#"nombre"];
NSRange nombreRange = [[nombre lowercaseString] rangeOfString:[searchText lowercaseString]];
if(nombreRange.location != NSNotFound)
[filteredList addObject:playas];
}
}
Add rest of code .m and .h
https://dl.dropboxusercontent.com/u/6217319/BuscarViewController.h
https://dl.dropboxusercontent.com/u/6217319/BuscarViewController.m
Thanks in advance.
BEST REGARDS
Your code has a lot of issues with it. I don't know which ones are actually breaking it, but any of these issues could be causing severe problems.
First, the code sample you provided doesn't provide declarations for a lot of hte objects you're referencing. No way this could possibly compile as given. If these are properties of the view controller instance, you need to use the accessor methods -- self.alldata or [self alldata], whichever you prefer.
Second, it looks like you're just adding to these properties. If you never reset their contents, every time this method is called, you're going to increase the size of your data set -- looking at your code, possibly recursively.
Third, you try to merge the two datasets together, and then try to search through only one of them. Either don't merge, or search through both seperately and then merge the results. As it is, what you're doing won't work.
Fourth, your table view should really only be displaying one type of data, so you shouldn't need to merge.
Edit:
Based on the code samples you've provided, your entire VC is going to need restructuring. Given how much of your code is written in what appears to be spanish, I'm doing a bit of guesswork at what you're actually doing.
First off, assuming you're using a modern version of xcode, get rid of the #synthesize in the .m file (it's no longer needed anymore). That will cause every single place you're using the actual ivar instead of a proper getter to turn into an error, so you can fix them quickly. iVars will by default use a prefixed underscore of their property name, so you can still access them if you have to -- but only by explicitly accessing the ivar instead of the property.
Second, you should restructure how you handle the data. I don't know where you get your data, but it looks like the various objects are fairly consistent. You should go ahead and either create a new class to hold all the data, or just put them all into a single dictionary. At that point, the 'alldata' property should, in fact, be an array of all valid data. What you should do is then have a filtered list of data (filteredData would be a good name), and you place whatever data matches the search criteria in there. Just remember to either reload the table or update it appropriately as items move into and out of the filtered list.

dynamic Instance naming

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.

Global Objects iphone

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....

How to manage memory load of static, lazily loaded dictionaries and arrays

Generally, I use static arrays and dictionaries for containing lookup tables in my classes. However, with the number of classes creeping quickly into the hundreds, I'm hesitant to continue using this pattern. Even if these static collections are initialized lazily, I've essentially got a bounded memory leak going on as someone uses my app.
Most of these are arrays of strings so I can convert strings into NSInteger constants that can be used with switch statements, etc.
I could just recreate the array/dictionary on every call, but many of these functions are used heavily and/or in tight loops.
So I'm trying to come up with a pattern that is both performant and not persistent.
If I store the information in a plist, does the iphoneOS do anything intelligent about caching those when loaded?
Do you have another method that might be related?
EDIT - ANSWER EXAMPLE
Based on a solution proposed below, here's what I'm going to work with...
First, add a method to NSObject via category.
- (void)autoreleaseOnLowMemory;
Now, whenever I want to create lazy-loading static array or dictionary in a helper function, I can just use the following pattern...
- (id)someHelperFunction:(id)lookupKey {
static NSDictionary *someLookupDictionary = nil;
if (!someLookupDictionary) {
someLookupDictionary = [[NSDictionary dictionaryWithObjects:X, Y, Z, nil] autoreleaseOnLowMemory];
}
return [someLookupDictionary objectForKey:lookupKey];
}
Now, instead of that static dictionary living until the end of the program, if we're running out of memory it will be released, and only re-instantiated when needed again. And yes, in a large project running on an iphone, this can be important!
PS - The implementation of autoreleaseOnLowMemory is trivial. Just create a singleton class with a method that takes an object and retains it in a set. Have that singleton listen for low memory warnings, and if it gets one, release all the objects in that set. May want to add a manual release function as well.
I generally prefer plists for this just because they're easy to maintain and reuse in different sections of code. If the speed of loading them into an NSDictionary from file is a concern (and check the profiler to be sure) you can always put them into an instance variable which you can release when you get a memory warning.
If you are just doing strings, you could use C arrays.
id keys[] = { #"a" , #"b" , #"c" };
id values[] = { #"1" , #"2" , #"3" };
And if you occasionally need a true NSArray or NSDictionary from that:
[NSArray arrayWithObjects:values count:3];
[NSDictionary dictionaryWithObjects:values forKeys:keys count:3];
A plist will involve a disk hit and xml parsing for each collection. As far as I know only NSUserDefaults are cached.

Best way to use my singleton

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.