Trying to solve the error "Ambiguous reference to member 'subscript'" - xcode8

First I create some lists:
let day0 = [0] as NSArray
let day1 = [0, 8, 2, 3, 4] as NSArray
let day2 = [0, 1, 2, 3, 4] as NSArray
let day3 = [0, 1, 2, 3, 4] as NSArray
let day4 = [0, 1, 2, 3, 4] as NSArray
let month0 = [0] as NSArray
let january = [day0, day1, day2, day3, day4] as NSArray
let february = [day0, day1, day2, day3, day4] as NSArray
let march = [day0, day1, day2, day3, day4] as NSArray
let april = [day0, day1, day2, day3, day4] as NSArray
let may = [day0, day1, day2, day3, day4] as NSArray
let june = [day0, day1, day2, day3, day4] as NSArray
let july = [day0, day1, day2, day3, day4] as NSArray
let august = [day0, day1, day2, day3, day4] as NSArray
let september = [day0, day1, day2, day3, day4] as NSArray
let october = [day0, day1, day2, day3, day4] as NSArray
let november = [day0, day1, day2, day3, day4] as NSArray
let december = [day0, day1, day2, day3, day4] as NSArray
let calendar = [month0, january, february, march, april, may, june, july, august, september, october, december] as NSArray
Then I try to return an element:
#IBAction func SetVariablesButton(sender: UIButton)
{
var result = calendar[1][1][1] as String
BedTimeLabel.text = String(result)
}
Then I get the error. I've tried various changes such as
let day0 = [0] as! NSArray
and
let day0 = [0] as Array<T>
but those didn't work.
I originally didn't cast the vars at all, but after researching the common problem, the common solution was to cast the vars so the compiler could understand what was going on.
I'm using Xcode 8 with Swift 2.3

First of all declare the dummy month month0 as [[0]] to get the same type as the others.
Then remove all casts.
let day0 = [0]
let day1 = [0, 8, 2, 3, 4]
let day2 = [0, 1, 2, 3, 4]
let day3 = [0, 1, 2, 3, 4]
let day4 = [0, 1, 2, 3, 4]
let month0 = [[0]]
let january = [day0, day1, day2, day3, day4]
let february = [day0, day1, day2, day3, day4]
let march = [day0, day1, day2, day3, day4]
let april = [day0, day1, day2, day3, day4]
let may = [day0, day1, day2, day3, day4]
let june = [day0, day1, day2, day3, day4]
let july = [day0, day1, day2, day3, day4]
let august = [day0, day1, day2, day3, day4]
let september = [day0, day1, day2, day3, day4]
let october = [day0, day1, day2, day3, day4]
let november = [day0, day1, day2, day3, day4]
let december = [day0, day1, day2, day3, day4]
let calendar = [month0, january, february, march, april, may, june, july, august, september, october, december]
The compiler can infer that calendar is [[[Int]]].
Now you can write
var result = String(calendar[1][1][1])

Related

Sort NSMutableDictionary in ASC order

In my Xcode Project (Objective-C), i store json Result in a NSMutableDictionary, but the result is in false order direction.
How can i sort a NSMutableDictionary is ASC order on Objective-C.
Here is my NSMutableDictionary:
{
3 = (
11,
12,
13,
14,
15,
16,
17,
18,
19,
20
);
2 = (
2,
3,
4,
5,
6,
7,
8,
9,
10
);
1 = (
0,
1
);
4 = (
21,
22,
23,
24,
25,
26
);
}
I expect a sort order 1,2,3,4 for UITableView Section.
#rmaddy is right,the following is the implementation code, very simple.
- (NSMutableArray *)sortDictionary:(NSMutableDictionary *)dictionary {
NSArray *sortedKeys = [[dictionary allKeys] sortedArrayUsingSelector:#selector(compare:)];
NSMutableArray *sortedArray = [NSMutableArray arrayWithCapacity:sortedKeys.count];
for (NSString *key in sortedKeys) {
[sortedArray addObject:[dictionary objectForKey:key]];
}
return sortedArray;
}
example
NSDictionary *dict = #{#"3":#{#"3333":#"3333"},
#"2":#{#"2222":#"2222"},
#"1":#{#"1111":#"1111"},
#"4":#{#"4444":#"444"}};
[self sortDictionary:dict];
result:
sortedArray :(
{
1111 = 1111;
},
{
2222 = 2222;
},
{
3333 = 3333;
},
{
4444 = 444;
}
)

parsing NSMutableDictionary with required format

I have an objective C object 'Obj' with an
#property (strong, nonatomic) NSMutableDictionary *obj;
This gets populated with data from an api in following format.
{
0 = ( 0, "7.00", "8.59”, ”15.00”, ”16.59", "19.00", "20.59 );
1 = ( 1, "7.00", "8.59”, ”15.00”, ”16.59", "19.00", "20.59 );
2 = ( 2, "7.00", "8.59”, ”15.00”, ”16.59", "19.00", "20.59 );
3 = ( 3, "7.00", "8.59”, ”15.00”, ”16.59", "19.00", "20.59 );
4 = ( 4, "7.00", "8.59”, ”15.00”, ”16.59", "19.00", "20.59 );
5 = ( 5, "7.00", "8.59”, ”15.00”, ”16.59", "19.00", "20.59 );
6 = ( 6, "7.00", "8.59”, ”15.00”, ”16.59", "19.00", "20.59 );
}
I need to parse the data and send it back as an array in following format.
`{
[ 0, 7, 00, 8, 59 ],
[0, 15, 00, 16, 59] ,
[0, 19, 00, 20, 59] ,
[ 1, 7, 00, 8, 59 ],
[1, 15, 00, 16, 59] ,
[1, 19, 00, 20, 59],
……
……
[ 6, 7, 00, 8, 59 ],
[6, 15, 00, 16, 59] ,
[6, 19, 00, 20, 59]
}`
Where 0,1,2,3,4,5,6 are days and rest of the information is hours and mins. so for each slot, the format is
`[day, from_hour, from_min, to_hour, to_min],
[0, 7, 0, 8, 59],`
A day could have multiple slots or just one slot.
So far I manage to run a loop and separate each day's record as below.
NSMutableArray *elementArray =[[NSMutableArray alloc ]init];
NSMutableArray *results =[[NSMutableArray alloc ]init];
NSInteger starthour = 0 ;
NSInteger startmin = 0 ;
NSInteger endhour = 0 ;
NSInteger endmin = 0 ;
NSMutableArray *temp = [[NSMutableArray alloc]init];
NSString *string;
int i = 0;
for ( i = 0; i <=6; i ++){
string = [NSString stringWithFormat:#"%d",i];
elementArray =[Obj.obj valueForKey:string];
starthour = [[elementArray objectAtIndex:1]integerValue];
startmin =([[elementArray objectAtIndex:1]floatValue]-[[elementArray objectAtIndex:1]integerValue])*100;
endhour = [[elementArray objectAtIndex:2]integerValue];
endmin =([[elementArray objectAtIndex:2]floatValue]-[[elementArray objectAtIndex:2]integerValue])*100;
NSNumber *day = [NSNumber numberWithInteger:[string integerValue]];
NSNumber *starthour1 = [NSNumber numberWithInteger:(int)starthour];
NSNumber *startmin1 = [NSNumber numberWithInteger:(int)startmin];
NSNumber *endhour1 = [NSNumber numberWithInteger:(int)endhour];
NSNumber *endmin1 = [NSNumber numberWithInteger:(int)endmin];
[temp addObject:day];
[temp addObject:starthour1];
[temp addObject:startmin1];
[temp addObject:endhour1];
[temp addObject:endmin1];
[results addObject:temp];
}
This gives me access to each record. My thought process is saying I could solve this by going through each record and populating the required array as, 'i' being the day, then running a nest loop on each record and extracting hours and mins?
You don't say what your problem actually is, i.e. you started on a solution and stopped and turned to SO, why?
Let's see if we can help you along with some pseudo-code.
You have a dictionary of arrays. the keys represent day numbers as do the first element of each array. After the first array element the elements come in pairs, each is a string containing a textual representation of hours and minutes separated by a full stop. You want and array of arrays where each element has 5 members: day number, start hour, start min, end hour, end minute, all as numbers.
A basic algorithm to handle this is two nested loops. You need somewhere to store the result:
results <- new empty array
Now you need to iterate over your dictionary:
for every key in sourceDictionary
elementArray = sourceDictionary[key]
[This is the loop you've written, except you generated the keys and looked them up while here we extract the keys from the dictionary. If you wish to process the keys in a particular order then generating them in that order, or extracting and sorting them, will handle that.]
Now you'd better do some data validation, elementArray should have at least the day number and one pair of strings in it, test for that:
check elementArray count > 1 and odd else handle error
Now you need to process each pair of strings, first access them:
cursor <- 1 // element 0 is the repeated day number
while cursor < elementArray count do
startTime <- elementArray[cursor]
endTime <- elementArray[cursor+1]
cursor <- cursor + 2 // ready for next iteration
So now you have the day number, key, and the start and end times as string, startTime & endTime. Now you need to split your time strings at the full stop, returning an array of substrings:
startParts <- startTime split at "."
More checks, did you get two parts?
check startParts count is 2 else handle error
Now convert each substring to an integer:
startHours <- parse startParts[0] as integer
startMins <- parse startParts[1] as integer
And keep checking:
check startHours in [0, 23] and startMins in [0, 59] else handle error
You've now got the five values you want, add them to your results array:
results <- results append array of (key, startHours, startMins, endHours, endMins)
Now just convert that to Objective-C and fill in the details. The first loop could be a for in one, the second a for(init; test; increment) one. For splitting a string look at NSString's methods, one will fit the bill. For parsing there are multiple options including NSString methods.
HTH
I got it working with desired output, but code looks messy, could be made elegant.
` NSMutableArray *elementArray =[[NSMutableArray alloc ]init];
NSMutableArray *results =[[NSMutableArray alloc ]init];
NSInteger starthour = 0 ;
NSInteger startmin = 0 ;
NSInteger endhour = 0 ;
NSInteger endmin = 0 ;
NSNumber *starthour1 ;
NSNumber *startmin1 ;
NSNumber *endhour1 ;
NSNumber *endmin1 ;
NSMutableArray *temp = [[NSMutableArray alloc]init];
NSString *string;
int i = 0;
for ( i = 0; i <=6; i ++){
string = [NSString stringWithFormat:#"%d",i];
elementArray =[Obj.obj valueForKey:string];
starthour = [[elementArray objectAtIndex:1]integerValue];
startmin =([[elementArray objectAtIndex:1]floatValue]-[[elementArray objectAtIndex:1]integerValue])*100;
endhour = [[elementArray objectAtIndex:2]integerValue];
endmin =([[elementArray objectAtIndex:2]floatValue]-[[elementArray objectAtIndex:2]integerValue])*100;
NSNumber *day = [NSNumber numberWithInteger:[string integerValue]];
starthour1 = [NSNumber numberWithInteger:(int)starthour];
startmin1 = [NSNumber numberWithInteger:(int)startmin];
endhour1 = [NSNumber numberWithInteger:(int)endhour];
endmin1 = [NSNumber numberWithInteger:(int)endmin];
[temp addObject:day];
[temp addObject:starthour1];
[temp addObject:startmin1];
[temp addObject:endhour1];
[temp addObject:endmin1];
[results addObject:[temp copy]];
[temp removeAllObjects];
starthour = [[elementArray objectAtIndex:3]integerValue];
startmin =([[elementArray objectAtIndex:3]floatValue]-[[elementArray objectAtIndex:3]integerValue])*100;
endhour = [[elementArray objectAtIndex:4]integerValue];
endmin =([[elementArray objectAtIndex:4]floatValue]-[[elementArray objectAtIndex:4]integerValue])*100;
starthour1 = [NSNumber numberWithInteger:(int)starthour];
startmin1 = [NSNumber numberWithInteger:(int)startmin];
endhour1 = [NSNumber numberWithInteger:(int)endhour];
endmin1 = [NSNumber numberWithInteger:(int)endmin];
[temp addObject:day];
[temp addObject:starthour1];
[temp addObject:startmin1];
[temp addObject:endhour1];
[temp addObject:endmin1];
[results addObject:[temp copy]];
[temp removeAllObjects];
starthour = [[elementArray objectAtIndex:5]integerValue];
startmin =([[elementArray objectAtIndex:5]floatValue]-[[elementArray objectAtIndex:5]integerValue])*100;
endhour = [[elementArray objectAtIndex:6]integerValue];
endmin =([[elementArray objectAtIndex:6]floatValue]-[[elementArray objectAtIndex:6]integerValue])*100;
starthour1 = [NSNumber numberWithInteger:(int)starthour];
startmin1 = [NSNumber numberWithInteger:(int)startmin];
endhour1 = [NSNumber numberWithInteger:(int)endhour];
endmin1 = [NSNumber numberWithInteger:(int)endmin];
[temp addObject:day];
[temp addObject:starthour1];
[temp addObject:startmin1];
[temp addObject:endhour1];
[temp addObject:endmin1];
[results addObject:[temp copy]];
[temp removeAllObjects];
`
The output is what I wanted looks like below.
(
(
0,
7,
0,
8,
59
),
(
0,
15,
0,
16,
59
),
(
0,
19,
0,
20,
59
),
(
1,
7,
0,
8,
59
),
(
1,
15,
0,
16,
59
),
(
1,
22,
0,
23,
59
),
(
2,
7,
0,
8,
59
),
(
2,
15,
0,
16,
59
),
(
2,
19,
0,
20,
59
),
(
3,
7,
0,
8,
59
),
(
3,
15,
0,
16,
59
),
(
3,
22,
0,
23,
59
),
(
4,
7,
0,
8,
59
),
(
4,
15,
0,
16,
59
),
(
4,
19,
0,
20,
59
),
(
5,
7,
0,
8,
59
),
(
5,
15,
0,
16,
59
),
(
5,
22,
0,
23,
59
),
(
6,
7,
0,
8,
59
),
(
6,
15,
0,
16,
59
),
(
6,
19,
0,
20,
59
)
)

Sort an array of custom sub-objects in a one-to-many relationship by newest first

I'm trying to sort an array so that the newest ones are at the top.
The problem I have is that I'm sorting on a One to many relationship and using compare doesn't seem to sort it.
The array is a list of completed flights.
NSFetchRequest *fr = [[NSFetchRequest alloc] initWithEntityName:[self entityName]];
fr.predicate = [NSPredicate predicateWithFormat:#"(acceptedDate != nil || booked == %# || ANY legs.flight != nil) && ANY legs.departureDate <= %#", #YES, [NSDate date]];
NSArray *results = [context executeFetchRequest:fr error:nil];
//Check BOTH legs have completed
NSDate *now = [NSDate date];
NSMutableArray *filtered = [NSMutableArray array];
for (Quote *quote in results) {
if ([quote.legs count] > 1) {
BOOL completed = YES;
for (QuoteLeg *leg in quote.legs) {
if ([leg.departureDate compare:now] == NSOrderedDescending) {
completed = NO;
}
}
if (completed) {
[filtered addObject:quote];
}
}
else {
[filtered addObject:quote];
}
}
// Try to sort the array
[filtered sortedArrayWithOptions:NSSortStable usingComparator:^NSComparisonResult(Quote *quote1, Quote *quote2){
QuoteLeg *leg1 = [[quote1.legs allObjects] firstObject];
QuoteLeg *leg2 = [[quote2.legs allObjects] firstObject];
return [leg1.departureDate compare:leg2.departureDate];
}];
// Sort filtered by date
for (Quote *q in filtered) {
QuoteLeg *leg = [[q.legs allObjects] firstObject];
NSLog(#"date = %#", leg.departureDate);
}
This always outputs
date = 2015-01-20 11:00:00 +0000
date = 2015-01-23 12:00:00 +0000
date = 2015-01-29 12:00:00 +0000
date = 2015-01-30 10:40:00 +0000
date = 2015-01-30 10:40:00 +0000
date = 2015-01-29 09:00:00 +0000
date = 2015-01-26 10:00:00 +0000
I'm needing to ensure that the dates are newest first.
Is there something else I can do?
- (NSArray *)sortedArrayWithOptions:(NSSortOptions)opts usingComparator:(NSComparator)cmptr
methods return the results as an NSArray, it does not sort your NSMutableArray in place. Try doing this instead
filtered = [filtered sortedArrayWithOptions:NSSortStable usingComparator:^NSComparisonResult(Quote *quote1, Quote *quote2){
QuoteLeg *leg1 = [[quote1.legs allObjects] firstObject];
QuoteLeg *leg2 = [[quote2.legs allObjects] firstObject];
return [leg1.departureDate compare:leg2.departureDate];
}];
I think I have an answer. I tried wrapping a NSSortDescriptor around it without any key and the results seem to be in the order I require;
// Filtered is a NSMutableArray
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:nil ascending:NO
comparator:^NSComparisonResult(VICQuote *quote1, VICQuote *quote2){
VICQuoteLeg *leg1 = [[quote1.legs allObjects] firstObject];
VICQuoteLeg *leg2 = [[quote2.legs allObjects] firstObject];
return [leg1.departureDate compare:leg2.departureDate];
}];
[filtered sortUsingDescriptors:#[sortDescriptor]];
NSArray *finalResults = [NSArray arrayWithArray:filtered];
// Output them
for (VICQuote *q in finalResults) {
VICQuoteLeg *leg = [[q.legs allObjects] firstObject];
NSLog(#"date = %#", leg.departureDate);
}
Results:
date = 2015-01-31 10:35:00 +0000
date = 2015-01-30 09:40:00 +0000
date = 2015-01-29 12:00:00 +0000
date = 2015-01-29 09:00:00 +0000
date = 2015-01-28 11:00:00 +0000
date = 2015-01-23 12:00:00 +0000
date = 2015-01-20 11:00:00 +0000

DateFormatter not outputting wrong date

I am trying to do a date from string however it always makes the date in the month of January... Why?
Code:
NSMutableArray *dateArray = [NSMutableArray array];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"YYYYMMDD"];
[dateFormatter setTimeZone:[NSTimeZone timeZoneWithName:#"GMT"]];
for (id <NSFetchedResultsSectionInfo> sectionInfo in [fetchedResultsController sections]) {
NSLog(#"Adding date: %#", [sectionInfo name]);
NSDate *newDate = [dateFormatter dateFromString:[sectionInfo name]];
NSLog(#"Adding date 2: %#", newDate);
[dateArray addObject:newDate];
}
LOGS:
2012-03-01 15:14:48.124 MyApp[21793:fb03] Adding date: 20120827
2012-03-01 15:14:48.124 MyApp[21793:fb03] Adding date 2: 2012-01-27 00:00:00 +0000
2012-03-01 15:14:48.125 MyApp[21793:fb03] Adding date: 20120830
2012-03-01 15:14:48.125 MyApp[21793:fb03] Adding date 2: 2012-01-30 00:00:00 +0000
2012-03-01 15:14:48.125 MyApp[21793:fb03] Adding date: 20120831
2012-03-01 15:14:48.126 MyApp[21793:fb03] Adding date 2: 2012-01-31 00:00:00 +0000
2012-03-01 15:14:48.126 MyApp[21793:fb03] Adding date: 20120906
2012-03-01 15:14:48.127 MyApp[21793:fb03] Adding date 2: 2012-01-06 00:00:00 +0000
2012-03-01 15:14:48.127 MyApp[21793:fb03] Adding date: 20120907
2012-03-01 15:14:48.128 MyApp[21793:fb03] Adding date 2: 2012-01-07 00:00:00 +0000
2012-03-01 15:14:48.128 MyApp[21793:fb03] Adding date: 20120910
2012-03-01 15:14:48.128 MyApp[21793:fb03] Adding date 2: 2012-01-10 00:00:00 +0000
2012-03-01 15:14:48.129 MyApp[21793:fb03] Adding date: 20120913
2012-03-01 15:14:48.129 MyApp[21793:fb03] Adding date 2: 2012-01-13 00:00:00 +0000
The day of month specifier is dd, not DD. Also, you might want to use the yyyy format for years, as YYYY means the ISO 'Week of Year', and may be different from the actual year. So your final format should look like:
[dateFormatter setDateFormat:#"yyyyMMdd"];

parsing and format different rss pubdate

I'm creating a universal feed reader and i need to format the rss pubDate but the rss pubdate is always different, for example:
Wed, 25 May 2011 02:10:00 CEST
Wed, 25 May 2011 18:54:26 +00:00
Wed, 25 May 2011 08:13:22 +0000
Wed, 25 May 2011 14:21:54 GMT
26 May 2011 10:32:00 +0100
I tried to use this code:
NSString *dateString = #"Wed, 25 May 2011 18:54:26 +00:00";
NSDateFormatter *df = [[[NSDateFormatter alloc] init] autorelease];
[df setDateFormat:#"EEE, dd MMMM yyyy HH:mm:ss +00:00"];
NSLocale *enLocale = [[[NSLocale alloc] initWithLocaleIdentifier:#"en_US"] autorelease];
[df setLocale:enLocale];
NSDate *date = [df dateFromString:dateString];
NSLog(#"'%#' = %#", dateString, date);
NSDateFormatter* df2 = [[[NSDateFormatter alloc] init] autorelease];
[df2 setDateFormat:#"EEE, dd MMMM yyyy HH:mm:ss"];
NSString *dateString2 = [df2 stringFromDate:date];
This code, however, works only with one type of rss pubDate, how can fix this problem?? how can create a universal dateformatter??
pubDate is in a date format, so you do the same format in your code to reflect that of the pubDate format.
EEE, dd MMMM yyyy HH:mm:ss +00:00 is equal to puDate: Wed, 25 May 2011 18:54:26 +00:00
You just have to compensate for the date format stored in pubDate.