cocoa: speech and time - cocoa

I'm building an app that a part of will speak the time. However, when I pass in my date strings (like 10/24/11) to the NSSpeechSynthesizer it will speak them literally, as "one, zero, slash two four slash one one", same with a timestamp, "eight colon one one colon colon", etc. etc.
I looked at the NSSpeechSynthesizer docs and I guess I'd have to work with the phonemesFromText method but that seems like a lot of grunt work to get the app to speak the time and date smoothly. Is there a quicker method?
Thanks

You could try something like this:
#implementation MDAppController
- (id)init {
if ((self = [super init])) {
}
return self;
}
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
NSDateFormatter *dateParser = [[[NSDateFormatter alloc]
initWithDateFormat:#"%m/%d/%y" allowNaturalLanguage:YES] autorelease];
NSDate *date = [dateParser dateFromString:#"10/24/11"];
NSDateFormatter *dateFormatter = [[[NSDateFormatter alloc] init] autorelease];
[dateFormatter setTimeStyle:NSDateFormatterNoStyle];
[dateFormatter setDateStyle:NSDateFormatterLongStyle];
NSString *string = [dateFormatter stringFromDate:date];
NSLog(#"string == %#", string);
// prints "October 24, 2011"
NSSpeechSynthesizer *alex = [[NSSpeechSynthesizer alloc]
initWithVoice:[NSSpeechSynthesizer defaultVoice]];
[alex setDelegate:self];
[alex startSpeakingString:string];
}
- (void)speechSynthesizer:(NSSpeechSynthesizer *)sender
didFinishSpeaking:(BOOL)finishedSpeaking {
if (finishedSpeaking) [sender autorelease];
}
#end
Basically, this is using 2 NSDateFormatters: one to "translate" the string representation of a date into an actual NSDate object, and then another to translate that NSDate back into a more desirable string representation.
Obviously, you'll need to adjust the dateParser format to fit your expected input string type. (Preferably, you could just use an input date rather than the string representation of it).

Why not use NSDateComponents to and -[NSString stringWithFormat:] construct a spoken sentence as your string, then speak that?

Related

UIPickerView Changing UIButton Title Size

So I'm making Alarm Clock to test my skills but can't seem to figure this out... What I've got a UIPickerView that gives a user a time that they can select. Once the time is selected the titleLabel on a UIButton is supposed to update with the time they selected and it does, but it shrinks the new time so it's unreadable... Is there something that needs adjusted with the formatting?
Before when my page loads
Here's my code
- (NSDate *)dateFromString:(NSString *)string {
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:#"HH:mm"];
NSDate *date = [[NSDate alloc] init];
date = [formatter dateFromString:#"15:00"];
assert(date != nil); // Error converting string to date
return date;
}
After when a user has set a time
Any reason why it might be doing this?
You're experiencing middle truncation of the button's text, and there are a couple of cures for this. You can either make the button bigger by simply adjusting its frame. Or, you can adjust the text size of the title label:
[myButton.titleLabel setFont:[UIFont fontWithName:myButton.titleLabel.font.fontName size:10.0f]];
Actually this seemed to resolve the issue.
alarmButton.titleLabel.adjustsFontSizeToFitWidth = YES;

How to trim off symbols from NSNumber?

Im making an iOS app to do with currency. My app receives the value of maybe: $4. This value the app receives is put into an NSNumber. The trouble is the value actualy has a $ in it. How do I trim out the $ in the NSNumber? Or would I be better of putting it into an NSString?
Use NSNumberFormatter:
// set up your number formatter
NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init];
[numberFormatter setNumberStyle:NSNumberFormatterCurrencyStyle];
// get a string that you'll be converting to a NSNumber
NSString *myNumberString = [NSString stringWithFormat:#"$4"]
// convert then print to the console
NSNumber *myNumber = [numberFormatter numberFromString:myNumberString];
NSLog(#"myNumber: %#", myNumber);
This should accomplish what you're looking to do. myNumberString will need to be altered to contain whatever string you're receiving.
NSNumberFormatter Documentation: https://developer.apple.com/library/ios/#documentation/Cocoa/Reference/Foundation/Classes/NSNumberFormatter_Class/Reference/Reference.html

Google Xml parser

can anyone help me in getting the formatted date from the parsed XML.
I can format that using NSXML formatter but now i am found difficulty in using it through Google XMl parser. where i can get the values through the key but i need that in a formatted way,
return [NSDictionary dictionaryWithObjectsAndKeys:
[[[xmlItem elementsForName:#"title"] objectAtIndex:0] stringValue], #"title",
[[[xmlItem elementsForName:#"link"] objectAtIndex:0] stringValue], #"link",
[[[xmlItem elementsForName:#"pubDate"] objectAtIndex:0] stringValue], #"Date",
nil];
here the pubDate is returned as such from xml with hr,min,sec i need the date alone.
Thanks in advance!!!!
I got the answer
//cell.textLabel.text = [item objectForKey:#"pubDate"];
NSString *yourXMLDate = [item objectForKey:#"pubDate"];
NSDateFormatter *inputFormatter = [[NSDateFormatter alloc] init];
[inputFormatter setDateFormat:#"E, d LLL yyyy HH:mm:ss Z"];
NSDate *inputDate = [inputFormatter dateFromString:yourXMLDate];
NSDateFormatter *outputFormatter = [[NSDateFormatter alloc] init];
[outputFormatter setDateFormat:#"MMM dd, HH:mm a"];
NSString *outputDate = [outputFormatter stringFromDate:inputDate];
cell.textLabel.text=outputDate;
where this results in Oct 12, 12:30 AM. whatever parser used in the xcode this works fine....

NSDate: Right way to work with time of day?

I am working with a schedule that specifies times of day, such as 10:30 AM. I do not know the dates, however. I'm going to store these as values in a NSDictionary and would like to deal with them in a straightforward way.
I can't use NSDate, since I don't have a date. At least, not in a straightforward way.
The other way that seems obvious is NSTimeInterval, but that looks like it's probably a source of very subtle errors. I'm thinking in particular of daylight savings time (which is on my mind this week for some reason!).
Other than that, the only things that really spring to mind are keeping it in a formatted string or encoding it in a NSNumber (like hours * 60 + minutes). Both of which would work out fine, of course, but seem like I'm inventing a square wheel where I'm sure there's already a round one somewhere.
What's the least against the grain way of dealing with raw times using Cocoa?
The short answer is that there's no built-in mechanism for storing time-of-day, so just use whatever is most convenient to you. I've used strings in the past using my own encoding and parsing code, (e.g., "22:00") because they're easy to read and debug, but there's nothing wrong with storing seconds or minutes past midnight as you suggest. Just remember that you'll have to do the math yourself.
How ever you do it, you will need separate year, month, day, hour, minute, and second values so that you can construct an NSDate from NSDateComponents, using NSCalendar's -dateFromComponents: method.
And as others have said, you cannot set the time-of-day by adding hours and minutes to an existing NSDate because if you cross a DST boundary you won't get the value you expect. (However, I assume you can still add day and month components without worrying about DST)
So, I guess there's no simple inbuilt way of doing this. It also looks like the only way to get Cocoa to build the time I expect on DST boundaries is with strings.
So for posterity, it looks like I'll be using something like this.
Test harness:
//
// TimeTest.m
//
#import <Foundation/Foundation.h>
#import "Utility.h"
id utility;
void testTime( NSTimeInterval time ) {
id gregorian = [[[NSCalendar alloc] initWithCalendarIdentifier: NSGregorianCalendar] autorelease];
id oneDay = [[[NSDateComponents alloc] init] autorelease];
[oneDay setDay: 1];
id thisDay = [gregorian dateFromComponents: [gregorian components: (NSEraCalendarUnit | NSYearCalendarUnit)
fromDate: [NSDate date]]];
for (NSInteger dayIdx = 0; dayIdx < 365; ++dayIdx ) {
NSDate *dateTime = [utility timeInSeconds: time
onDate: thisDay];
NSLog( #"%#", dateTime );
thisDay = [gregorian dateByAddingComponents: oneDay
toDate: thisDay
options: 0];
}
}
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
utility = [[[Utility alloc] init] autorelease];
testTime( ((10 * 60.0) + 0.0) * 60.0 );
testTime( ((9 * 60.0) + 30.0) * 60.0 );
[pool drain];
return 0;
}
Utility header:
//
// Utility.h
//
#import <Foundation/Foundation.h>
#interface Utility : NSObject {
NSCalendar *gregorian;
NSDateFormatter *dateWithoutTimeFormatter, *dateWithTimeFormatter;
}
- (NSDate *)timeInHours: (NSInteger)hours
minutes: (NSInteger)minutes
seconds: (NSInteger)seconds
onDate: (NSDate *)inDate;
- (NSDate *)timeInSeconds: (NSTimeInterval)inTime
onDate: (NSDate *)inDate;
#end
Utility implementation:
//
// Utility.m
//
#import "Utility.h"
#interface Utility()
#property (nonatomic, readwrite, retain) NSCalendar *gregorian;
#property (nonatomic, readwrite, retain) NSDateFormatter *dateWithoutTimeFormatter, *dateWithTimeFormatter;
#end
#implementation Utility
#synthesize gregorian, dateWithoutTimeFormatter, dateWithTimeFormatter;
- (NSDate *)timeInHours: (NSInteger)hours
minutes: (NSInteger)minutes
seconds: (NSInteger)seconds
onDate: (NSDate *)inDate;
{
id timeStr = [[NSMutableString alloc] initWithFormat: #"%02d:%02d:%02d", hours, minutes, seconds];
id dateStr = [dateWithoutTimeFormatter stringFromDate: inDate];
id dateTimeStr = [[NSString alloc] initWithFormat: #"%# %#", dateStr, timeStr];
[timeStr release];
id dateTime = [dateWithTimeFormatter dateFromString: dateTimeStr];
[dateTimeStr release];
return dateTime;
}
- (NSDate *)timeInSeconds: (NSTimeInterval)inTime
onDate: (NSDate *)inDate;
{
NSAssert1( inTime < 24.0 * 3600.0, #"Time %f must be less than 24hrs", inTime );
double temp = inTime;
int hours = rintf(floor( temp / 3600.0 ));
temp -= ( hours * 3600 );
int minutes = rintf(floorf( temp / 60.0 ));
temp -= ( minutes * 60 );
int seconds = rintf( temp );
return [self timeInHours: hours
minutes: minutes
seconds: seconds
onDate: inDate];
}
- (id)init;
{
if (( self = [super init] )) {
self.gregorian = [[[NSCalendar alloc] initWithCalendarIdentifier: NSGregorianCalendar] autorelease];
self.dateWithoutTimeFormatter = [[[NSDateFormatter alloc] init] autorelease];
[dateWithoutTimeFormatter setDateFormat: #"yyyy-MM-dd"];
self.dateWithTimeFormatter = [[[NSDateFormatter alloc] init] autorelease];
[dateWithTimeFormatter setDateFormat: #"yyyy-MM-dd HH:mm:ss"];
}
return self;
}
- (void)dealloc;
{
self.gregorian = nil;
self.dateWithoutTimeFormatter = nil;
self.dateWithTimeFormatter = nil;
[super dealloc];
}
#end
Why bother with a separate unit for this? Well, I've written enough date formatting code to know that constructing NSCalendar and NSDateFormatter on the fly utterly kills performance.
You can use NSDateComponents to store only the components you need (hour and minutes for example), and then use NSCalendar dateByAddingComponents:toDate:options: to create an absolute date reference, when you need using the serialized components and a base date.

How to sort NSMutableArray of NSMutableDictionary?

I have NSMutableArray of NSMutableDictionary(NSString objects). One of NSString object is actually a date, and i need to sort NSMutableArray based on that date and I don't want it to sort dates as strings. How can i make it?
If I understand correctly, your array contains dictionaries that contain strings and you want to sort on those strings... as dates. Something like this perhaps:
[someArray sortWithOptions: 0 usingComparator: ^(id inObj1, id inObj2) {
NSDate *date1 = [NSDate dateWithString: [inObj1 objectForKey: #"dateString"]];
NSDate *date2 = [NSDate dateWithString: [inObj2 objectForKey: #"dateString"]];
return [date1 compare: date2];
}];
You will need to use the sortedArrayUsingFunction:context: method. For example:
NSInteger comparator( NSDictionary *d1, NSDictionary *d2, void *context )
{
return [[d1 objectForKey:#"date"] compare:[d2 objectForKey:#"date"]];
}
// In some method:
NSArray *sortedArray = [array sortedArrayUsingFunction:comparator context:nil];
Note: This is not tested.

Resources