Hard to get the headline correct since there is so much to tell.
I got this NSArray (A portion of it):
Mon, 06:00, Radioshow Morning, Mon, 10:00, Lunch radio, 14:00, Afternoon Radio and so on.
The NSArray is from an plist in the app.
What I need to build (and failed with) is a search function that shows me the right program with these search values:
searchDay and searchTime
Both those values are from NSDate.
I've been Googling for about and hour now and hasn't come up with anything usefull so my last hope stands to stackoverflow to show me what I am missing.
I've been dabbling with dateFromString, compare, timeIntervalSinceNow but for some reason failed to achive what I am about to do.
Greatful for any help givven.
TIA
Mattias
You should use an NSArray of NSDictionary objects instead of various object types in your NSArray:
NSDictionary *morningShow = [NSDictionary dictionaryWithObjectsAndKeys:#"Mon",#"day","10:00",#"time","morning",#"name",nil];
Then add that to your array. Then, when you are searching, you have a uniform data structure to search inside of.
I think I have solved it.
But I must say I am intrigued by phooze answer.
The way I am doing it now is reading the values (NSString) from the array converting them into an NSDate object and comparing those with timeIntervalSinceDate.
By that I can figure out if currentTime is between two times in the array and such I know what show is on. I've just come up with the solution, the base code is working but the whole code isn't done yet, just on paper/in my mind.
But it feels like a somewhat ugly code... lots of doing small things.
But I will pre sue this to the end and if it still looks inefficient and ugly I will look in to other solutions.
Related
I have a NSArray with many different hours as NSStrings. My question is, how can I compare the actual time of the user with the values into the NSArray and get which is the next hour to the actual user? For example, if the NSArray has got #"07:00", #"07:30", #"08:00", and now it's 07:40, how can I achieve that the app returns 08:00 as the next hour?? Maybe with NSTimers??
I know it's hard to understand thus many thanks.
Lookup NSDate , after you've read that you might find NSDateComponents and NSDateFormatter useful. The rest is programming... If you get stuck ask another question giving the code you've produced and the problem you are having.
HTH
I am sorry to ask this but I have searched for hours on doing this but I really don't understand it. Please help me. I have a .plist file in my Xcode project and it's root is a Dictionary type. It contains about 50 more dictionaries. Inside the dictionary contains strings. (Dictionary(root) > Dictionary > String. I added a search field to my toolbar and linked it to my code. I am able to get what the user types but then how do I "search" after getting what the user typed? Is there a method for this and how do I link it into my .plist? Thank you so much!!!
You want to search for the user entered string in your Dictionary of Dictionaries?
You're going to have to iterate each dictionary, asking [dict objectForKey:userEntry] in each. Not sure if you want to only find first match or all matches too.
Additionally, you may want to create an abstraction of your Dictionary of Dictionaries to reduce the scale of the problem and clarify the API. In simpler terms, wrap your Dictionary of Dictionaries in a class and put a sensible (non-dictionary-based) set of methods on it. It's probably worth the effort.
To load the plist into a Dictionary, look at [Dictionary dictionaryWithContentsOfFile].
Edit: Filtering options on NSDictionary
Have you looked at the following options for filtering values in an NSDictionary:
[NSDictionary keysOfEntriesPassingTest:] (10.6 and later) or
take the [rootDictionary allValues] NSArray and use Predicates, perhaps like this.
I've been developing iOs and OsX applications for several months now and it still feels like I'm doing something wrong. I try to stick to the Guidelines and I try to use the objects Apple provides as often as I can. But it seems they are making my code very hard to understand.
Example:
When I want to just "increment" a NSNumber Object (which is not mutable, but you get what I mean), I use awkward lines like this:
int value = [counter intValue];
counter = [NSNumber numberWithInt:value +1];
Is this really necessary? Are there more elegant ways (i++, inc(i), etc) to do simple things like this? Especially when you're working with coordinates it gets really frustrating and hard to work with.
When working with Objective C I feel like I'm allocating, deallocating and converting objects all the time and wasting so much of my own time and the CPU time with all those conversions. Thanks for your time, I really appreciate your answers and I'm looking forward to your tipps!
Using your example, is there any particular reason you are using NSNumber for a counter? It would be much better to use int so that you can use value++.
The key to good Objective-C code is to use objects when they make sense. Don't be afraid to use non-object data types and don't be afraid to drop down (not the best term) to C when required.
As #sosborn wrote: use objects only when it's required. But: when it's required, and you still feel wrong, simply don't. Write a macro for incrementing an NSNumber, use ARC for let the compiler do the memory management for you as efficiently as possible, etc. If you really worried about time, use C or assembly for time-critical tasks, or C++ if you want OO.
P. s.: NSNumber increment macro:
#define NSNUM_INC(n) do { n = [NSNumber numberWithInt:[n intValue] + 1]; } while (0);
You can write your category for NSNumber to implement the methods you need. For your example the file of category contains the following function:
-(NSNumber *)numberByAddingInt:(int)i
{
...
}
Include this file and then you can call it as:
counter = [counter numberByAddingInt:1];
currently, i am working on an app that uses Core Data. One of my managed objects has a property that keeps track of the day of week (Sunday - Saturday) as an integer (0-6). For the sake of sorting the objects by day as well as less overhead in saving, i definitely believe the best practice is to save the days as indexes and then convert to string during runtime. The question becomes the best practice to convert the index to its corresponding day as a string. ie. 0=>#"Sunday" and 6 => #"Saturday". I can obviously use NSCalendar and NSDate and NSDateComponents to achieve this. It just seems like a very roundabout way to go about it given the simplicity of the task. Naturally, a simple NSString array defined as such could do the trick:
NSString *dayOfWeek[7] = {#"Sunday",#"Monday",#"Tuesday",#"Wednesday",#"Thursday",#"Friday'"#"Saturday"};
But then i find myself constantly redefining this same variable over and over again. A global constant NSString could work. Another idea I had was creating a function that used this dayOfWeek array and then including it in the files that need it. What do you think. What's the best practice?
How about one of the weekdaySymbols methods of NSDateFormatter?
Another solution would be to define a category method on NSString, for example, to return the string based on the number. Then the strings array can be static and only used in that method.
I just finished reading the "Functions" chapter from Uncle Bob's Clean Code. The main advice was to make sure that functions are short -- really short. And they should only do one thing per level of abstraction. Here's a function from an app I'm making to learn Cocoa (idea from Andy Matuschak).
- (IBAction)go:(id)sender
{
NSString *output = nil;
if ([[nameInputField stringValue] isEqualToString:#""])
{
output = #"Please enter your name";
}
else
{
NSString *date = [[NSDate date] descriptionWithCalendarFormat:#"%A, %B %d"
timeZone:nil
locale:[[NSUserDefaults standardUserDefaults] dictionaryRepresentation]];
output = [NSString stringWithFormat:#"Hello, %#! Today is %#.", [nameInputField stringValue], date];
}
[responseOutputField setStringValue:output];
}
Basically, this function reads a name from a text field (nameInputField) and outputs a message to another text field (responseOutputField) I'm wondering a) if this function does 'one thing' per level of abstraction and b) how to make it shorter.
I disagree that this function is at the right level. The core computation of working out what to output based on current input should be factored into another function. This will make that computation much more testable (since you don't need any text fields, you can unit test in isolation) and reusable, since it has much less contextual baggage. As it is, the function is hard-wired to a specific use and so is not reusable.
As it is, how do you test it without actually running the application?
It does two things. First it gets/determines the output to print. Then it prints it. You could separate these. But I wouldn't. That seems like going too far to me.
I think this function does a reasonable amount of work, and does not need to be broken down further.
I would suggest changing the name of the function to more clearly describe what it does (i.e. updateResponse). This will make the code easier to understand, when looking at the source and when looking at the NIB in interface builder. Also, if you can't find a name that succinctly describes what the function does, its a tip that you are violating the "one thing" goal.
You also ask how to make this code shorter. I think in this case you might be able to use bindings to keep the responseOutputField in sync with the nameInputField, without any code at all (depending on how exactly you want things to behave).