Crash in NSDateformatter setDateFormat method - ios

-(NSString*) convertToDateString:(NSString*)str{
static NSDateFormatter *InDateFormatter = nil;
static NSDateFormatter *OutDateFormatter = nil;
NSString *outDate = nil;
if([str isKindOfClass:[NSString class]] && [str length] > 0){
NSString *dateStr = [[NSString alloc] initWithString:str];
if (InDateFormatter == nil) {
InDateFormatter = [[NSDateFormatter alloc] init];
InDateFormatter.dateFormat = #"yyyy-MM-dd";
}
if (OutDateFormatter == nil) {
OutDateFormatter = [[NSDateFormatter alloc] init];
OutDateFormatter.dateFormat = #"MM/dd/yy";
}
NSRange rangeOfDash = [dateStr rangeOfString:#"T"];
dateStr = (rangeOfDash.location != NSNotFound) ? [dateStr substringToIndex:rangeOfDash.location] : dateStr;
if([dateStr isKindOfClass:[NSString class]] && [dateStr length] == 10){
NSDate* date = [InDateFormatter dateFromString:dateStr];
if (date != nil) {
outDate = [OutDateFormatter stringFromDate:date];
}
}
}
return outDate;
}
Crash occurred in the line "InDateFormatter.dateFormat = #"yyyy-MM-dd";
There will be multiple instances of class that gets created in parallel and invokes the above method. Crash is rarely reproducible.
Am I not using the date formatter correctly? Thanks in advance

For a thread-safe lazy initialization, you can use the GCD dispatch_once()
function:
static NSDateFormatter *inDateFormatter;
static NSDateFormatter *outDateFormatter;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
inDateFormatter = [[NSDateFormatter alloc] init];
inDateFormatter.dateFormat = #"yyyy-MM-dd";
outDateFormatter = [[NSDateFormatter alloc] init];
outDateFormatter.dateFormat = #"MM/dd/yy";
});

Related

can't get images for any contact from contact book

Below is my code but with this code i can't get image for any contact.
Please help me for this.
- (void)loadAddressBook
{
arrContacts = [[NSMutableArray alloc]init];
APAddressBook *addressBook = [[APAddressBook alloc] init];
[addressBook loadContacts:^(NSArray <APContact *> *contacts, NSError *error)
{
if (!error)
{
for (APContact *strcontact in contacts)
{
NSMutableDictionary *addressDict=[[NSMutableDictionary alloc]init];
[addressDict setValue:strcontact.name.compositeName forKey:COMPOSITENAME];
if (strcontact.thumbnail != nil)
{
NSData *imgData = [NSData dataWithData:UIImagePNGRepresentation(strcontact.thumbnail)];
// From data to string
NSString *strImage = [[NSString alloc] initWithData:imgData encoding:NSUTF8StringEncoding];
[addressDict setObject:strImage forKey:IMAGE];
}else {
[addressDict setObject:NOIMAGE forKey:IMAGE];
}
for (APPhone *phones in strcontact.phones) {
// NSLog(#"Number %#",phones.number);
[addressDict setValue:phones.number forKey:PHONE];
}
for (APEmail *emails in strcontact.emails) {
// NSLog(#"Emails %#",emails.address);
[addressDict setValue:emails.address forKey:EMAIL];
}
for (APAddress *address in strcontact.addresses) {
// NSLog(#"Number %#",phones.number);
[addressDict setValue:address forKey:ADDRESS];
}
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
formatter.dateFormat = #"dd.MM.yyyy";
NSString *strDate = [formatter stringFromDate:[NSDate date]];
[addressDict setValue:strDate forKey:IMPORTDATE];
[arrContacts addObject:addressDict];
}
[tblmportContacts reloadData];
}
else
{
// show error
}
}];
}
I am getting all details but can not get images from APAddressBook.
Please provide solution for this.
Try code below.
addressBook.fieldsMask = APContactFieldAll;

Find out next most close date from NSDate array of times

How can I find out the next prayer from the array of times, I have total 6 Prayers at different times and i want to compare each one with current time and have to find out which one is most near as a next prayer, Date format also creating problems because it give always in UTC format and I have to use local time zone, I am using the following code:
NSMutableArray *arrayTimeIntervals = [[NSMutableArray alloc]init];
NSMutableArray *intervals = [[NSMutableArray alloc]init];
NSMutableArray *arrayPrayers = [[NSMutableArray alloc]init];
[arrayPrayers addObject:#{#"prayer":#"prayer 1",#"time":#"1:12 am"}];
[arrayPrayers addObject:#{#"prayer":#"prayer 2",#"time":#"5:45 am"}];
[arrayPrayers addObject:#{#"prayer":#"prayer 3",#"time":#"12:03 pm"}];
[arrayPrayers addObject:#{#"prayer":#"prayer 4",#"time":#"3:30 pm"}];
[arrayPrayers addObject:#{#"prayer":#"prayer 4",#"time":#"6:20 pm"}];
[arrayPrayers addObject:#{#"prayer":#"prayer 6",#"time":#"7:50 pm"}];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"hh:mm a"];
NSMutableArray *dates = [NSMutableArray arrayWithCapacity:arrayPrayers.count];
for (NSDictionary *timeDict in arrayPrayers)
{
NSString *timeString = [timeDict objectForKey:#"time"];
NSString *name = [timeDict objectForKey:#"prayer"];
NSDate *date = [dateFormatter dateFromString:timeString];
[dates addObject:#{#"prayer":name,#"time":timeString, #"date":date}];
}
for (int i =0 ; i<arrayPrayers.count; i++) {
NSDictionary *timeDict = arrayPrayers[i];
NSString *timeString = [timeDict objectForKey:#"time"];
//NSString *name = [timeDict objectForKey:#"prayer"];
NSDate *date = [dateFormatter dateFromString:timeString];
NSComparisonResult result = [[NSDate date] compare:date];
if(result==NSOrderedAscending){
NSLog(#"next prayer");
}else if(result==NSOrderedDescending){
NSLog(#"last prayer");
}else{
NSLog(#"current prayer");
}
if ([date earlierDate:[NSDate date]]) {
NSTimeInterval interval = [date timeIntervalSinceNow];
NSDictionary *tempDict = #{#"Prayer":timeDict,
#"Time":timeString,
#"Index":[NSString stringWithFormat:#"%d",i],
#"Interval":[NSString stringWithFormat:#"%f",interval]};
[arrayTimeIntervals addObject:tempDict];
[intervals addObject:[NSString stringWithFormat:#"%f",interval]];
}
}
NSNumber * min = [intervals valueForKeyPath:#"#min.doubleValue"];
NSUInteger index = 0;
for(int i =0 ; i<intervals.count; i++)
{
NSDictionary* dict = arrayTimeIntervals[i];
if([[dict objectForKey:#"Interval"] intValue] == [min intValue]) {
index = i;
NSLog(#"next prayer is!!!:%ld",index);
break;
}
}
NSDictionary *dict = [arrayTimeIntervals objectAtIndex:index];
NSLog(#"next prayer object is:%#",dict);

NSDateFormatter no space to am/pm

I'm using the following date formatter:
+ (NSDateFormatter *)dateFormatter {
static NSDateFormatter *_dateFormatter = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
NSString *format = [NSDateFormatter dateFormatFromTemplate:#"MMM d h:mm a" options:0 locale:[NSLocale currentLocale]];
_dateFormatter = [[NSDateFormatter alloc] init];
[_dateFormatter setDateFormat:format];
});
return _dateFormatter;
}
An output example could be:
Mar 25, 2:05 PM
I need to change 1 thing:
no space between the hour and the am/pm
like this:
Mar 25, 2:05PM
Try this solution, it worked for me. (simply remove the space between mm and a)
+ (NSDateFormatter *)dateFormatter {
static NSDateFormatter *_dateFormatter = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
NSString *format = [NSDateFormatter dateFormatFromTemplate:#"MMM d h:mma" options:0 locale:[NSLocale currentLocale]];
_dateFormatter = [[NSDateFormatter alloc] init];
[_dateFormatter setDateFormat:format];
});
return _dateFormatter;
}
I was using DateFormatter.dateFormat(fromTemplate: "h:mma", options: 0, locale: Locale.current)!, but that consistently added a space before my am/pm marker. Setting the dateFormat property directly with a string worked.
let formatter = DateFormatter()
formatter.amSymbol = "a"
formatter.pmSymbol = "p"
formatter.dateFormat = "h:mma"
let timeLabel = formatter.string(from: Date())
+ (NSDateFormatter *)dateFormatter {
static NSDateFormatter *_dateFormatter = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_dateFormatter = [[NSDateFormatter alloc] init];
[_dateFormatter setDateFormat:#"MMM d, h:mmaaa"];
});
return _dateFormatter;
}
how about not to use template?
template's am/pm can't be sticked with minutes, weird
Can you try like this
static NSDateFormatter *_dateFormatter = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
NSString *format = [NSDateFormatter dateFormatFromTemplate:#"MMM d h:mm a" options:0 locale:[NSLocale currentLocale]];
_dateFormatter = [[NSDateFormatter alloc] init];
[_dateFormatter setDateFormat:format];
});
NSString *date = [_dateFormatter stringFromDate:[NSDate date]];
NSArray *aa = [date componentsSeparatedByString:#" "];
NSString *combinedString = [date stringByReplacingOccurrencesOfString:[NSString stringWithFormat:#" %#",[aa lastObject]] withString:[aa lastObject]];
NSLog(#"date : %#",combinedString);
I create a simple yet not necessary the best solution. So I used my string to present it in a UILabel. So I sublclassed UILabel called ClockLabel and override setter for label's text. Here is the code:
- (void)setText:(NSString *)text {
text = [text stringByReplacingOccurrencesOfString:#" am" withString:#"am"];
text = [text stringByReplacingOccurrencesOfString:#" pm" withString:#"pm"];
[super setText:text];
}
There must be some other soluton but I sticked to this one.

Combining 2 NSDateFormatters into one

Currently I have two NSDateFormatters in my app and I want to somehow "combine" them so I only have, since they're parsing the same date.
I have a NSObject called UpcomingReleases, thats where all my JSON info gets stored.
UpcomingRelease.h
- (NSString *) formattedDate;
UpcomingRelease.m
- (NSString *) formattedDate {
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"];
NSDate *readableDate = [dateFormatter dateFromString:self.release_date];
[dateFormatter setDateFormat:#"MMMM dd"];
return [dateFormatter stringFromDate:readableDate];
}
My UICollectionViewController (UpcomingReleasesViewController.m)
if([upcomingReleaseDictionary objectForKey:#"release_date"] != NULL)
{
NSString *readableDate = [upcomingReleaseDictionary objectForKey:#"release_date"];
UpcomingRelease *upcoming = [[UpcomingRelease alloc] init];
upcoming.release_date = readableDate;
cell.release_date.text = [NSString stringWithFormat:#"%#", upcoming.formattedDate];
}
My detailedViewController (ReleaseViewController.m)
(_singleRelease is a NSDictionary)
- (void)viewDidLoad
{
[super viewDidLoad];
if([_singleRelease objectForKey:#"release_date"] != NULL)
{
NSString *readableDate = [_singleRelease objectForKey:#"release_date"];
UpcomingRelease *singleRelease = [[UpcomingRelease alloc] init];
singleRelease.release_date = readableDate;
self.release_date.text = [NSString stringWithFormat:#"%#", singleRelease.formattedDate];
}
}
This was working fine, until I added a share on twitter action and I had to add another NSDateFormatter so it could show the readable date inside the tweet (I would get an error saying "No visible interface for ReleaseViewController declares the selected 'formattedDate'" otherwise).
- (NSString *) formattedDate:(NSString *)jsonDateString {
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"];
NSDate *readableDate = [dateFormatter dateFromString:jsonDateString];
[dateFormatter setDateFormat:#"MMMM dd"];
return [dateFormatter stringFromDate:readableDate];
}
#pragma mark - Share on twitter
- (IBAction)shareOnTwitter:(id)sender {
if ([SLComposeViewController isAvailableForServiceType:SLServiceTypeTwitter])
{
SLComposeViewController *tweetSheet = [SLComposeViewController
composeViewControllerForServiceType:SLServiceTypeTwitter];
NSString *formattedDate = [self formattedDate:[_singleRelease objectForKey:#"release_date"]];
[tweetSheet setInitialText:[NSString stringWithFormat:#"%#", formattedDate]];
[self presentViewController:tweetSheet animated:YES completion:nil];
}
}
How can I combine both these NSDateFormatters into one? They're both parsing the same string in the same way (also if there's a better way to show the formattedDate string than the one I'm currently doing would be great).
This is how my JSON shows the date string:
release_date: "2013-11-16T00:00:00.000Z"
Thanks.
As #Hot Licks says:
Make the date formatter a class method:
+ (NSString *) formattedDate:(NSString *)jsonDateString {
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"];
NSDate *readableDate = [dateFormatter dateFromString:jsonDateString];
[dateFormatter setDateFormat:#"MMMM dd"];
return [dateFormatter stringFromDate:readableDate];
}
Put it in a utility class and use it in both cases. In the first case just pass in self.release_date.

UIDatePicker and UITextView

I want to show a text in UITextView depend on the date, some thing like "in This Day App", I have this code in action
-(void)changingText:(id)sender {
NSDateFormatter *df = [[NSDateFormatter alloc] init];
df.dateStyle = NSDateFormatterMediumStyle;
label.text = [NSString stringWithFormat:#"%#", [df stringFromDate:datePicker.date]];
NSDictionary *pageData = [[DataSource sharedDataSource] dataForPage:pageIndex];
NSString *dateText = [pageData objectForKey:#"pageName"];
NSString *dateInfo = [df stringFromDate:datePicker.date];
if ([dateText isEqualToString: dateInfo]) {
myText.text = [pageData objectForKey:#"pageText"];
}
[df release];
}
My qustion is how to update UITextView With the data from NSDictionery ForKey#"pageText" , because it shows just the first object.
here is the Object that i want to triger when the date been selected.
- (id)init {
self = [super init];
if (self != nil)
{
dataPages = [[NSArray alloc] initWithObjects:
[NSDictionary dictionaryWithObjectsAndKeys:
#"Oct 3, 2009", #"pageName",
#"First Object", #"pageText",
nil],
[NSDictionary dictionaryWithObjectsAndKeys:
#"Oct 10, 2009", #"pageName",
#"second Object", #"pageText",
nil],
[NSDictionary dictionaryWithObjectsAndKeys:
#"Oct 27, 2009", #"pageName",
#"Third Object", #"pageText",
nil],
nil];
}
return self;
}
I'm not sure if I understand your question, but I think you need to make the object from your dictionary into an NSString like this:
-(void)changingText:(id)sender{
NSDateFormatter *df = [[NSDateFormatter alloc] init];
df.dateStyle = NSDateFormatterMediumStyle;
NSDictionary *pageData = [[DataSource sharedDataSource] dataForPage:pageIndex];
NSString *dateText = (NSString *)[pageData objectForKey:#"pageName"];
NSString *dateInfo = [df stringFromDate:datePicker.date];
label.text = [NSString stringWithFormat:#"%#", [df stringFromDate:dateInfo]];
if ([dateText isEqualToString: dateInfo]) {
myText.text = dateText;
}
[df release];
}

Resources