Nesting NSDictionary based on value - ios

i've data from Library that return this:
NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:distanceNumber,#"distance",idChallengerN,#"idChallenger",dateFrom, #"date", nil];
[_array addObject:dict];
If i print _array this is there result:
{
date = "2015-07-31 14:50:40 +0000";
distance = "-1";
idChallenger = 43;
},
{
date = "2015-07-31 16:18:57 +0000";
distance = "-1";
idChallenger = "-1";
},
{
date = "2015-07-31 16:19:05 +0000";
distance = "-1";
idChallenger = "-1";
},
and it's ok, now I should get each date and group this _array based on weeks...
I've tried:
NSMutableDictionary *tempDic = [NSMutableDictionary dictionary];
for (int i = 0; i<_array.count; i++) {
NSDictionary *dict = [_array objectAtIndex:i];
NSDate *date = [dict objectForKey:#"date"];
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *dateComponents = [calendar components:NSWeekOfYearCalendarUnit fromDate:date];
NSLog(#"date week = %ld",(long)[dateComponents weekOfYear]);
NSNumber *weekN = [NSNumber numberWithInteger:[dateComponents weekOfYear]];
if ([tempDic objectForKey:weekN]) {
//contains
}
else{
//not contains
}
weekN return the number of the week in year based on 'date',
now i'm stuck to how group certain data if have the same number of week, like this for example:
weekN = 31 {
{
idChallenger = 43;
idChallenger = 22;
}
}
weekN = 32 {
{
idChallenger = 55;
idChallenger = 21;
idChallenger = 678;
}
}
thanks to popctrl :
NSMutableArray *weekArray = [NSMutableArray array];
for(int i = 0; i < 52; i++){
[weekArray addObject:[NSMutableArray array]];
}
//This replaces your for loop
for (int i = 0; i<_array.count; i++) {
NSDictionary *dict = [_array objectAtIndex:i];
NSDate *date = [dict objectForKey:#"date"];
NSCalendar *calendar = [NSCalendar currentCalendar];
//Notice that I changed NSWeekOfYearCalendarUnit to NSCalendarUnitWeekOfYear, as NSWeekOfYearCalendarUnit has been deprecated
NSDateComponents *dateComponents = [calendar components:NSCalendarUnitWeekOfYear fromDate:date];
NSMutableArray *innerArray = weekArray[[dateComponents weekOfYear] - 1];
[innerArray addObject:dict];
}
this code produce very well structure, but if I want divide weeks in year before?

If you're looking for something that follows the example you've given at the bottom of your post, that would be an array of arrays, where the first array is indexed by date and the inner arrays have no specific order.
If you would like to preserve the initial dictionary data structure, just make the values contained in that array of arrays the dictionary.
EDIT: Here's the code I would use
//To initialize the array
NSMutableArray *weekArray = [NSMutableArray array];
for(int i = 0; i < 52; i++){
[weekArray addObject:[NSMutableArray array]];
}
//This replaces your for loop
for (int i = 0; i<_array.count; i++) {
NSDictionary *dict = [_array objectAtIndex:i];
NSDate *date = [dict objectForKey:#"date"];
NSCalendar *calendar = [NSCalendar currentCalendar];
//Notice that I changed NSWeekOfYearCalendarUnit to NSCalendarUnitWeekOfYear, as NSWeekOfYearCalendarUnit has been deprecated
NSDateComponents *dateComponents = [calendar components:NSCalendarUnitWeekOfYear fromDate:date];
NSMutableArray *innerArray = weekArray[[dateComponents weekOfYear] - 1];
[innerArray addObject:dict];
}

Related

Unable to get all Matching string from NSDictionary iOS

I am new to iOS and little weak in logic.
Can any one help me here,
I want to get all matching data from NSDictionary.
eg:
my tempDict is NSDictionary which contains this,
tempDict:
errorCode = 00;
errorMessage = "<null>";
pastConsultations = (
{
date = "16 December 2016";
day = Friday;
doctorName = "<null>";
localTime = "07:30 AM";
symptoms = q;
today = Yes;
},
{
date = "16 December 2016";
day = Friday;
doctorName = "<null>";
localTime = "07:30 AM";
symptoms = g;
today = Yes;
},
{
date = "13 December 2016";
day = Tuesday;
doctorName = "<null>";
localTime = "12:30 PM";
symptoms = fever;
today = No;
}
);
upcomingConsultations = (
{
date = "16 December 2016";
day = Friday;
localTime = "09:30 PM";
symptoms = "";
today = Yes;
},
{
date = "16 December 2016";
day = Friday;
localTime = "09:30 PM";
symptoms = chj;
today = Yes;
},
{
date = "18 December 2016";
day = Sunday;
localTime = "12:30 PM";
symptoms = "test an incoming ";
today = No;
}
);
}
Inside a pastConsultations key i want to get all nested data which contains AM
i.e my output should be:
{ //Array at 0th index
date = "16 December 2016";
day = Friday;
doctorName = "<null>";
localTime = "07:30 AM";
symptoms = q;
today = Yes;
},
{ //Array at 1st index
date = "16 December 2016";
day = Friday;
doctorName = "<null>";
localTime = "07:30 AM";
symptoms = g;
today = Yes;
}
}
Here is the code i have tried but it is not working, please help where i am making mistake?
NSArray *allKeys;
for (int i=0; i<[tempDict count]; i++) {
allKeys = [[[tempDict valueForKey:#"upcomingConsultations"] objectAtIndex:i] allKeys];
NSString *targetKey = nil;
// NSArray *allKeys = [[tempDict valueForKeyPath:#"pastConsultations"] allKeys];
for (int j = 0; j < [allKeys count]; ++j) {
NSString *key = [allKeys objectAtIndex:i];
NSString *obj = [[[tempDict valueForKey:#"upcomingConsultations"] objectAtIndex:i] objectForKey:key];
if ([obj rangeOfString:searchText].location != NSNotFound) { // searchedString is what you're looking for
targetKey = key;
NSLog(#"found match");
break;
}
}
}
Try this code:
assuming you already have tempDict dictionary loaded.
NSMutableArray *morningPastArr = [[NSMutableArray alloc] init];
NSArray *pastArray = [tempDict objectForKey:#"pastConsultations"];
for (int i=0;i<[pastArray count]; i++) {
NSDictionary *eachPast = [pastArray objectAtIndex:i];
NSString *time = [eachPast objectForKey:#"localTime"];
if (![time rangeOfString:#"AM"].location == NSNotFound) {
[morningPastArr addObject:eachPast];
}
}
// finally you will have like what you need in morningPastArr.
EDIT:
If you want to combine search results, for example, results for AM entry and Friday only you can do like this:
NSMutableArray *morningAndFridayPastArr = [[NSMutableArray alloc] init];
NSArray *pastArray = [tempDict objectForKey:#"pastConsultations"];
for (int i=0;i<[pastArray count]; i++) {
NSDictionary *eachPast = [pastArray objectAtIndex:i];
NSString *time = [eachPast objectForKey:#"localTime"];
NSString *day = [eachPast objectForKey:#"day"];
if ((![time rangeOfString:#"AM"].location == NSNotFound)&&([day isEqualToString:#"Friday"])) {
[morningAndFridayPastArr addObject:eachPast];
}
}
You can use NSPredicate for that as follows:
NSPredicate *predicate;
NSMutableArray *filteredData=[[NSMutableArray alloc]init];
predicate = [NSPredicate predicateWithFormat:#"localTime contains[c] %#",#"AM"];
//OR Use below predicate as suggested by Rishi
predicate = [NSPredicate predicateWithFormat:#"localTime ENDSWITH 'AM'"];
filteredData=[[[tempDict valueForKey:#"pastConsultations"] filteredArrayUsingPredicate:predicate]] mutableCopy];
Hope this will help.

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);

Performing Core Data Operations in self created multiple threads to save processing time

I have surfed a lot about performing core data operations in multiple threads but no good luck to solve my problem.
My code is such that I have to download a csv file after every ten minutes which contains each entry of 10 seconds. This file once downloaded is parsed and the contents are saved in database and then files are removed as then, when needed, I can fetch data from database.
Now, I have a huge existing content of more than a month for now which may extend to years also as time passes by, performing this huge task of saving new files to database and fetching objects from core data into an array for already downloaded files using a single thread is causing a huge processing time. Also, views in app needs to be adjusted with all previous data (They are basically plots of quantity vs time).
How can I achieve this in multiple threads and optimize my code processing time and reduce UI Blockage to minimum?
Please note that : Performing the task in background thread is not my concern as I in any case have to show graphs on the basis of total data. Please provide valuable advices.
EDIT: PERFORMED SOME MULTITHREADING
HERE IS THE NEW CODE,
- (void) downloadFiles:(NSString *)dataPath{
__block AppDelegate *appD = (AppDelegate *)[[UIApplication sharedApplication] delegate];
backgroundMOC = [[NSManagedObjectContext alloc] init];
[backgroundMOC setPersistentStoreCoordinator:[[appD managedObjectContext] persistentStoreCoordinator]];
if (parsedDetailsDataArrayForCurrentDay) {
parsedDetailsDataArrayForCurrentDay = nil;
}
if (parsedDetailsDataArrayForCurrentMonth) {
parsedDetailsDataArrayForCurrentMonth = nil;
}
if (parsedDetailsDataArrayForCurrentYear) {
parsedDetailsDataArrayForCurrentYear = nil;
}
parsedDetailsDataArrayForCurrentDay = [[NSMutableArray alloc] init];
parsedDetailsDataArrayForCurrentMonth = [[NSMutableArray alloc] init];
parsedDetailsDataArrayForCurrentYear = [[NSMutableArray alloc] init];
dispatch_group_t d_group = dispatch_group_create();
for (NSInteger i = 0; i <= (self.filesListArray.count - 1); i++) {
NSString *filePathOnPhone = [dataPath stringByAppendingString:[NSString stringWithFormat:#"/%#", [[self.filesListArray objectAtIndex:i] objectForKey:#"kCFFTPResourceName"]]];
NSFetchRequest *fetch = [NSFetchRequest fetchRequestWithEntityName:#"ParsedInfiDetails"];
NSString *nameToGet = [[self.filesListArray objectAtIndex:i] objectForKey:#"kCFFTPResourceName"];
NSLog(#"File Check: %#", nameToGet);
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"fileName = %#", nameToGet];
[fetch setPredicate:predicate];
NSError *error = nil;
NSArray *results = [backgroundMOC executeFetchRequest:fetch error:&error];
NSArray *definedResults = [results copy];
if(definedResults && (definedResults.count !=0)) {
NSLog(#"Entities with that name: %#", results);
#autoreleasepool {
NSArray *result = [[definedResults sortedArrayUsingDescriptors:[NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:#"modDate" ascending:YES]]] copy];
NSDate *specificDate = [NSDate date];
NSMutableArray *sortedDateArray = [[NSMutableArray alloc] init];
NSMutableArray *sortedDateCurrentYearArray = [[NSMutableArray alloc] init];
NSMutableArray *sortedDateCurrentMonthArray = [[NSMutableArray alloc] init];
for (int i = 0; i < result.count; i++) {
NSManagedObject *obj = [result objectAtIndex:i];
NSDate *objDate = [obj valueForKey:#"modDate"];
NSCalendar *gregorian = [NSCalendar currentCalendar];
NSDateComponents *components = [gregorian componentsInTimeZone:[NSTimeZone timeZoneWithAbbreviation:#"UTC"] fromDate:objDate];
NSInteger day = [components day];
NSInteger month = [components month];
NSInteger year = [components year];
NSDateComponents *specificComps = [[NSCalendar currentCalendar] components:NSCalendarUnitDay | NSCalendarUnitMonth | NSCalendarUnitYear fromDate:specificDate];
NSInteger specificDay = [specificComps day];
NSInteger specificMonth = [specificComps month];
NSInteger specificYear = [specificComps year];
if(day == 24){
}
if (day == specificDay && month == specificMonth && year == (specificYear-2000)) {
[sortedDateArray addObject:obj];
}
NSDate *todayDate = [NSDate date];
NSDateComponents *componentsForToday = [[NSCalendar currentCalendar] components:NSCalendarUnitDay | NSCalendarUnitMonth | NSCalendarUnitYear fromDate:todayDate];
NSInteger currentMonth = [componentsForToday month];
NSInteger currentYear = [componentsForToday year];
if (year == (currentYear-2000)) {
[sortedDateCurrentYearArray addObject:obj];
}
if (year == (currentYear -2000) && month == currentMonth) {
[sortedDateCurrentMonthArray addObject:obj];
}
}
NSMutableArray *sortedTimedArray = [[NSMutableArray alloc] initWithArray:[sortedDateArray sortedArrayUsingDescriptors:[NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:#"modTime" ascending:YES]]]];
NSMutableArray *sortedTimedCurrentYearArray = [[NSMutableArray alloc] initWithArray:[sortedDateCurrentYearArray sortedArrayUsingDescriptors:[NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:#"modTime" ascending:YES]]]];
NSMutableArray *sortedTimedCurrentMonthArray = [[NSMutableArray alloc] initWithArray:[sortedDateCurrentMonthArray sortedArrayUsingDescriptors:[NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:#"modTime" ascending:YES]]]];
[parsedDetailsDataArrayForCurrentDay addObjectsFromArray:sortedTimedArray];
[parsedDetailsDataArrayForCurrentYear addObjectsFromArray:sortedTimedCurrentYearArray];
[parsedDetailsDataArrayForCurrentMonth addObjectsFromArray:sortedTimedCurrentMonthArray];
}
} else {
NSLog(#"Error: %#", error);
NSString *threadName = [NSString stringWithFormat:#"%ld THREAD", (long)i];
dispatch_queue_t myQueue = dispatch_queue_create([threadName UTF8String], NULL);
dispatch_group_async(d_group, myQueue, ^{
NSManagedObjectContext *backgroundMOC1;
backgroundMOC1 = [[NSManagedObjectContext alloc] init];
[backgroundMOC1 setPersistentStoreCoordinator:[[appD managedObjectContext] persistentStoreCoordinator]];
NSLog(#"Entered Thread ");
BOOL success = [appD.ftpManager downloadFile:[[self.filesListArray objectAtIndex:i] objectForKey:#"kCFFTPResourceName"] toDirectory:[NSURL URLWithString:dataPath] fromServer:srv];
if (success) {
// dispatch_group_async(d_group, myQueue, ^{
NSMutableDictionary *dict = [appD.ftpManager progress];
NSString *filePath = [dataPath stringByAppendingString:[NSString stringWithFormat:#"/%#", [[self.filesListArray objectAtIndex:i] objectForKey:#"kCFFTPResourceName"]]];
CHCSVParser *parser = [[CHCSVParser alloc] initWithContentsOfCSVURL:[NSURL fileURLWithPath:filePath]];
[parser parse];
NSMutableArray *currentFileComponentsArray = [NSArray arrayWithContentsOfCSVURL:[NSURL fileURLWithPath:filePath]];
NSMutableArray *parsedDetailsEntitiesArray = [[NSMutableArray alloc] init];
for (int j = 1; j <= (currentFileComponentsArray.count-1); j++) {
NSArray *detailsArray = [currentFileComponentsArray objectAtIndex:j];
if (!(detailsArray.count < 32)) {
NSManagedObject *parsedDetails = [NSEntityDescription
insertNewObjectForEntityForName:#"ParsedInfiDetails"
inManagedObjectContext:[appD managedObjectContext]];
NSString *totalDateString = [NSString stringWithFormat:#"%# %#", [detailsArray objectAtIndex:0], [detailsArray objectAtIndex:1]];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
dateFormatter.dateFormat = #"dd/MM/yyyy HH:mm:ss";
NSTimeZone *gmt = [NSTimeZone timeZoneWithAbbreviation:#"GMT"];
[dateFormatter setTimeZone:gmt];
NSDate *startDate = [dateFormatter dateFromString:totalDateString];
[parsedDetails setValue:startDate forKey:#"modDate"];
[parsedDetails setValue:startDate forKey:#"modTime"];
———————————————————————PERFORM PARSEDDETAILS STATEMENTS----------------
NSError *error;
NSLog(#"Saved File in Database: %#", [[self.filesListArray objectAtIndex:i] objectForKey:#"kCFFTPResourceName"]);
NSLog(#"Saved thread");
if (![backgroundMOC1 save:&error]) {
NSLog(#"Whoops, couldn't save: %#", [error localizedDescription]);
}
else{
if ([[NSFileManager defaultManager] fileExistsAtPath:filePath]) {
//if the download fails, we try to delete the empty file created by the stream.
[[NSFileManager defaultManager] removeItemAtPath:filePath error:nil];
//when data is stored in coredata remove the downloaded file.
}
[parsedDetailsEntitiesArray addObject:parsedDetails];
}
}
}
NSSet *set = [[NSSet alloc] initWithArray:parsedDetailsEntitiesArray];
[self.relevantInverId setValue:set forKey:#"infiDetails"];
NSDate *specificDate = [NSDate date];
#autoreleasepool {
NSMutableArray *sortedDateArray = [[NSMutableArray alloc] init];
NSMutableArray *sortedDateCurrentYearArray = [[NSMutableArray alloc] init];
NSMutableArray *sortedDateCurrentMonthArray = [[NSMutableArray alloc] init];
for (int i = 0; i < parsedDetailsEntitiesArray.count; i++) {
NSManagedObject *obj = [parsedDetailsEntitiesArray objectAtIndex:i];
NSDate *objDate = [obj valueForKey:#"modDate"];
NSCalendar *gregorian = [NSCalendar currentCalendar];
NSDateComponents *components = [gregorian componentsInTimeZone:[NSTimeZone timeZoneWithAbbreviation:#"UTC"] fromDate:objDate];
NSInteger day = [components day];
NSInteger month = [components month];
NSInteger year = [components year];
NSDateComponents *specificComps = [[NSCalendar currentCalendar] components:NSCalendarUnitDay | NSCalendarUnitMonth | NSCalendarUnitYear fromDate:specificDate];
NSInteger specificDay = [specificComps day];
NSInteger specificMonth = [specificComps month];
NSInteger specificYear = [specificComps year];
if(day == 24){
}
if (day == specificDay && month == specificMonth && year == (specificYear-2000)) {
[sortedDateArray addObject:obj];
}
NSDate *todayDate = [NSDate date];
NSDateComponents *componentsForToday = [[NSCalendar currentCalendar] components:NSCalendarUnitDay | NSCalendarUnitMonth | NSCalendarUnitYear fromDate:todayDate];
NSInteger currentMonth = [componentsForToday month];
NSInteger currentYear = [componentsForToday year];
if (year == (currentYear-2000)) {
[sortedDateCurrentYearArray addObject:obj];
}
if (year == (currentYear-2000) && month == currentMonth) {
[sortedDateCurrentMonthArray addObject:obj];
}
}
NSMutableArray *sortedTimedArray = [[NSMutableArray alloc] initWithArray:[sortedDateArray sortedArrayUsingDescriptors:[NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:#"modTime" ascending:YES]]]];
[parsedDetailsDataArrayForCurrentDay addObjectsFromArray:sortedTimedArray];
NSMutableArray *sortedTimedCurrentYearArray = [[NSMutableArray alloc] initWithArray:[sortedDateCurrentYearArray sortedArrayUsingDescriptors:[NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:#"modTime" ascending:YES]]]];
NSMutableArray *sortedTimedCurrentMonthArray = [[NSMutableArray alloc] initWithArray:[sortedDateCurrentMonthArray sortedArrayUsingDescriptors:[NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:#"modTime" ascending:YES]]]];
[parsedDetailsDataArrayForCurrentYear addObjectsFromArray:sortedTimedCurrentYearArray];
[parsedDetailsDataArrayForCurrentMonth addObjectsFromArray:sortedTimedCurrentMonthArray];
}
// });
}
});
}
BOOL isFileAlreadyPresent = [[NSFileManager defaultManager] fileExistsAtPath:filePathOnPhone];
}
NSMutableArray *sortedParsedDetailsArrayForCurrentDay = [[NSMutableArray alloc] initWithArray:[parsedDetailsDataArrayForCurrentDay sortedArrayUsingDescriptors:[NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:#"modTime" ascending:YES]]]];
NSDate *startDate ;
NSDate *endaDate;
dispatch_group_notify(d_group, dispatch_get_main_queue(), ^{
dispatch_async(dispatch_get_main_queue(), ^{
[self stopLogoSpin];
[hud dismiss];
});
NSLog(#"All background tasks are done!!");
});
}
Now, logs #"Entered Thread " is visible in log but, #"Saved File in Database: %#", [[self.filesListArray objectAtIndex:i] and #"Saved thread" are not called.
Also,
BOOL success = [appD.ftpManager downloadFile:[[self.filesListArray objectAtIndex:i] objectForKey:#"kCFFTPResourceName"] toDirectory:[NSURL URLWithString:dataPath] fromServer:srv];
helps download file with their seperate thread in the download method.
Should uncommenting below help?
// dispatch_group_async(d_group, myQueue, ^{
Main thread is intentionally made to wait but this block below is also never called:
dispatch_group_notify(d_group, dispatch_get_main_queue(), ^{
dispatch_async(dispatch_get_main_queue(), ^{
[self stopLogoSpin];
[radialHUD dismiss];
});
NSLog(#"All background tasks are done!!");
});
Please advice any modification and solution to problems above.
Optimised the code by moving all what is not needed in loop outside and the performing the looping operation using GCD.
dispatch_queue_t myOwnQueue = dispatch_queue_create([#"MyOwnQueue" UTF8String], NULL);
dispatch_apply(self.filesListArray.count, myOwnQueue, ^(size_t i) { });
This lead to reduction in time by half. However any further optimisations need to be seen.

Check whether time falls between two time iOS

I have two times let say 8.40am and 4.00pm,
What i want to do is, want to check whether current time falls between given time or not ?
I have tried this code snippet but it is not working :(
can you please help me out where i am making mistake ?
NSDateComponents *components = [[NSCalendar currentCalendar] components:NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit fromDate:[NSDate date]];
NSInteger currHr = [components hour];
NSInteger currtMin = [components minute];
NSString startTime = #"21:00";
NSString endTime = #"07:00";
NSArray *arr=[NSArray arrayWithObjects:startTime,endTime, nil];
int stHr = [[[[arr objectAtIndex:0] componentsSeparatedByString:#":"] objectAtIndex:0] intValue];
int stMin = [[[[arr objectAtIndex:0] componentsSeparatedByString:#":"] objectAtIndex:1] intValue];
int enHr = [[[[arr objectAtIndex:1] componentsSeparatedByString:#":"] objectAtIndex:0] intValue];
int enMin = [[[[arr objectAtIndex:1] componentsSeparatedByString:#":"] objectAtIndex:1] intValue];
int formStTime = (stHr*60)+stMin;
int formEnTime = (enHr*60)+enMin;
int nowTime = (currHr*60)+currtMin;
if(nowTime >= formStTime && nowTime <= formEnTime) {
NSLog(#"Btween......");
}
Thnaks in advance
EDIT:
NSDateComponents *openingTime = [[NSDateComponents alloc] init];
openingTime.hour = [timeA integerValue]; //8
openingTime.minute = [timeB integerValue]; //45
NSDateComponents *closingTime = [[NSDateComponents alloc] init];
closingTime.hour = [timeC integerValue]; //4
closingTime.minute = [timeD integerValue]; //43
NSDateFormatter *formatter = [[NSDateFormatter alloc]init];
[formatter setDateFormat:#"hh:mm"];
NSString *nowTimeString = [formatter stringFromDate:[NSDate date]];
NSDate *now = [formatter dateFromString:nowTimeString]; //3:30
NSDateComponents *currentTime = [[NSCalendar currentCalendar] components:NSCalendarUnitHour|NSCalendarUnitMinute|NSCalendarUnitSecond
fromDate:now];
NSMutableArray *times = [#[openingTime, closingTime, currentTime] mutableCopy];
[times sortUsingComparator:^NSComparisonResult(NSDateComponents *t1, NSDateComponents *t2) {
if (t1.hour > t2.hour) {
return NSOrderedDescending;
}
if (t1.hour < t2.hour) {
return NSOrderedAscending;
}
// hour is the same
if (t1.minute > t2.minute) {
return NSOrderedDescending;
}
if (t1.minute < t2.minute) {
return NSOrderedAscending;
}
// hour and minute are the same
if (t1.second > t2.second) {
return NSOrderedDescending;
}
if (t1.second < t2.second) {
return NSOrderedAscending;
}
return NSOrderedSame;
}];
if ([times indexOfObject:currentTime] == 1) {
NSLog(#"We are Open!");
} else {
NSLog(#"Sorry, we are closed!");
}
create date components for opening and closing time.
create date components with hour, minute, second from date to check
place opening, closing and current time in an array
sort array. if current time is at index 1, it lies between opening and closing time
NSDateComponents *openingTime = [[NSDateComponents alloc] init];
openingTime.hour = 8;
openingTime.minute = 40;
NSDateComponents *closingTime = [[NSDateComponents alloc] init];
closingTime.hour = 16;
closingTime.minute = 0;
NSDate *now = [NSDate date];
NSDateComponents *currentTime = [[NSCalendar currentCalendar] components:NSCalendarUnitHour|NSCalendarUnitMinute|NSCalendarUnitSecond
fromDate:now];
NSMutableArray *times = [#[openingTime, closingTime, currentTime] mutableCopy];
[times sortUsingComparator:^NSComparisonResult(NSDateComponents *t1, NSDateComponents *t2) {
if (t1.hour > t2.hour) {
return NSOrderedDescending;
}
if (t1.hour < t2.hour) {
return NSOrderedAscending;
}
// hour is the same
if (t1.minute > t2.minute) {
return NSOrderedDescending;
}
if (t1.minute < t2.minute) {
return NSOrderedAscending;
}
// hour and minute are the same
if (t1.second > t2.second) {
return NSOrderedDescending;
}
if (t1.second < t2.second) {
return NSOrderedAscending;
}
return NSOrderedSame;
}];
if ([times indexOfObject:currentTime] == 1) {
NSLog(#"We are Open!");
} else {
NSLog(#"Sorry, we are closed!");
}
Try this -
NSString *startTimeString = #"08:00 AM";
NSString *endTimeString = #"06:00 PM";
NSDateFormatter *formatter = [[NSDateFormatter alloc]init];
[formatter setDateFormat:#"hh:mm a"];
NSString *nowTimeString = [formatter stringFromDate:[NSDate date]];
int startTime = [self minutesSinceMidnight:[formatter dateFromString:startTimeString]];
int endTime = [self minutesSinceMidnight:[formatter dateFromString:endTimeString]];
int nowTime = [self minutesSinceMidnight:[formatter dateFromString:nowTimeString]];;
if (startTime <= nowTime && nowTime <= endTime)
{
NSLog(#"Time is between");
}
else {
NSLog(#"Time is not between");
}
-(int) minutesSinceMidnight:(NSDate *)date
{
NSDateComponents *components = [[NSCalendar currentCalendar] components:NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond fromDate:date];
return 60 * (int)[components hour] + (int)[components minute];
}
Check the screenshot -

UITableView scroll to section that is closest to todays date

I have a tableview with a calendar it's appointments in it. Each day is a separate section.
You can see what I mean over here
Now I want that the tableview scrolls to the section of today or if there is no section for today to the closest one.
I know that I should use the following piece of code:
[tableView scrollToRowAtIndexPath:scrollIndexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES];
Now I have an NSMutableDictionary that contains my sorted Appointments/day. You can see the function below:
-(NSDictionary *)sortKalendar:(NSMutableArray *)appointments{
NSMutableDictionary *buffer = [[NSMutableDictionary alloc] init];
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:#"dd-MM-yyyy"];
for (int i = 0; i < appointments.count; i++) {
Appointment *object = [appointments objectAtIndex:i];
NSString *date = [formatter stringFromDate:object.app_start];
if(!(date == NULL) ){
NSLog(#"date is %#",date);
if ([buffer objectForKey:date]) {
[(NSMutableArray *)[buffer objectForKey:date] addObject:object];
} else {
NSMutableArray *mutableArray = [[NSMutableArray alloc] initWithObjects:object, nil];
[buffer setObject:mutableArray forKey:date];
}
}
}
NSDictionary *result = [NSDictionary dictionaryWithDictionary:buffer];
return result;
}
My question is now, how can I find the correct NSIndexpath ?
Thanks in advance !
EDIT
At the moment I'm using the following. But something is still not right.
NSArray *keys = [dictAppointments allKeys];
NSLog(#"KEYS ARE %#",keys) ;
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:#"dd-MM-yyyy"];
NSArray *sortedArray = [keys sortedArrayUsingComparator:^(id obj1, id obj2) {
NSDate *date1 = [formatter dateFromString:obj1];
NSDate *date2 = [formatter dateFromString:obj2];
NSNumber *interval1 = [NSNumber numberWithDouble:[date1 timeIntervalSinceNow]];
NSNumber *interval2 = [NSNumber numberWithDouble:[date2 timeIntervalSinceNow]];
return (NSComparisonResult)[interval1 compare:interval2];
}];
NSLog(#"Sorted Array %#",sortedArray);
NSString *closestDateString = [sortedArray objectAtIndex:0];
NSLog(#"Closest date string is %#",closestDateString);
int section = [keys indexOfObject:closestDateString];
NSIndexPath *scrollIndexPath = [NSIndexPath indexPathForRow:0 inSection:section];
[tableView scrollToRowAtIndexPath:scrollIndexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES];
This gives me the following logs:
2014-01-07 13:28:42.420 Adsolut[9579:60b] KEYS ARE (
"03-12-2013",
"20-12-2013",
"17-12-2013",
"05-01-2014",
"21-12-2013",
"31-12-2013",
"04-01-2014",
"06-01-2014",
"16-01-2014",
"29-12-2013",
"03-01-2014",
"11-01-2014",
"18-12-2013",
"31-01-2014"
)
2014-01-07 13:28:42.437 Adsolut[9579:60b] Sorted Array (
"03-12-2013",
"17-12-2013",
"18-12-2013",
"20-12-2013",
"21-12-2013",
"29-12-2013",
"31-12-2013",
"03-01-2014",
"04-01-2014",
"05-01-2014",
"06-01-2014",
"11-01-2014",
"16-01-2014",
"31-01-2014"
)
You can sort the array using time interval between appointment date and current date,
NSArray *keys = [yourDictionary allKeys];
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:#"dd-MM-yyyy"];
NSArray *sortedArray = [keys sortedArrayUsingComparator:^(id obj1, id obj2) {
NSDate *date1 = [formatter dateFromString:obj1];
NSDate *date2 = [formatter dateFromString:obj2];
NSNumber *interval1 = [NSNumber numberWithDouble:abs([date1 timeIntervalSinceNow])];
NSNumber *interval2 = [NSNumber numberWithDouble:abs([date2 timeIntervalSinceNow])];
return (NSComparisonResult)[interval1 compare:interval2];
}];
And the closest date by,
NSString *closestDateString = [sortedArray objectAtIndex:0];
And from that,
int section = [keys indexOfObject:closestDateString];
NSIndexPath *scrollIndexPath = [NSIndexPath indexPathForRow:0 inSection:section];
Get the list of dates (from your dictionary or one you already have). Sort it. Loop over it (indexOfObjectPassingTest:) to find the date >= today (or use a predicate to filter and then take the first item from the result and get the index).
You have a sorted date array, don't you? Let's say it as dateArray.
Get today date object: NSDate * today = [NSDate date];
Search for dateArray to the nearest date, get the index of nearest date.
NSDate * today = [NSDate date] ;
__block NSUInteger section = NSNotFound ;
__block NSTimeInterval timeInterval = NSTimeIntervalSince1970 ;
[dateArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
NSDate * date = obj ;
NSTimeInterval ti = [today timeIntervalSinceDate:date] ;
if (ti < 0)
ti = -ti ;
if (ti <= timeInterval) {
section = idx ;
timeInterval = ti ;
} else {
*stop = YES ;
}
}] ;
You know the section index now, let's say it as sectionIndex, the first row index in the section is 0.
So the NSIndexPath is [NSIndexPath indexPathForRow:0 inSection:sectionIndex]

Resources