How to get specific item from NSArray? - ios

I have a sqlite database as columns groupno, sunday, monday, tuesday, wednesday, thursday, friday and saturday.
I have retrieved the data using the following code. But this code gives all data in a single column (for e.g. code skips all previous values in a column and displays final item at the end of the column). However what I need is data from a specific row.
I do not know how to access a single item from NSArray. I would be really grateful for any help.
Thanks.
NSArray *info = [dba getinfo];
for(Getinfo *p in info)
getinfo.text = [p sunday ];

Thanks everyone,
I was able to solve the problem by following code to select the specific item,
id schedule = [info objectAtIndex:0];
_displayinfo.text = [schedule sunday];
Thanks again

Related

Substring specific integer from string

I have google some related questions, but unfortunately didn't find answer.
I have string like 2016-07-22, i need to get an integer 07, evaluate it to 7 and save.
Of course, this is date, therefore it will change every time, so i cant suppose that year always will be 2016. I need to get string after 5th symbol up to 8th.
Is there any easy way to achieve that? Thanks.
If it's always that section of the string, you can use NSMakeRange(5, 2) and substringWithRange to pick out the month.
After you have "07", conversion is just a case of asking the string for its integerValue.
The "save" part depends entirely on where you want to save it.
Here is just one way (I can think of at least 3 other ways):
NSString *str = #"2016-07-22";
NSArray *elements = [str componentsSeparatedByString:#"-"];
NSAssert([elements count] == 3, #"Ahhh!");
NSInteger month = [elements[1] integerValue];

Core Data equivalent of SQL DATEPART

Given a table of books published, with a date_published column of typeNSAttributeType.DateAttributeType, I would like to know how many books were published by year like this:
Year | Books
-----+------
2013 | 76
2014 | 172
2015 | 155
In plain old SQL this is simple (although it varies slightly by RDBMS):
SELECT DATEPART(yyyy, date_published) AS "Year", COUNT(*) AS "Books"
FROM books
GROUP BY DATEPART(yyyy, date_published)
I'm new to Swift and iOS in general but everything I looked at suggested either pre-computing the year and storing that, or loading all the data and counting it myself. Neither of these approaches suited me as the year is in fact an accounting year (that can vary after storage) and the amount of data is potentially large.
Most approaches revolved around adding a custom attribute to my NSManagedObject. That seems like it's too late to me because the object would not have been loaded into memory at this stage. There were also discussions around NSFetchedResultsController with sectionNameKeyPath's, but again this feels like it's too late in the fetch process. I found NSExpression convoluted so I may well have missed something but it seems like I can't invoke a custom Swift function here. Really, at the end of the day, I expected to find built-in functions for things like DATEPART, DATEADD, DATEDIFF, and I was hoping somebody could point me in the right direction.
As a more concrete example consider the UK tax year which runs 6 April to 5 April. To calculate the tax year I would subtract 3 months and 6 days (to midnight on 5 April). So for a book published on 1 March 2012 I would do the subtraction which would give me 24 November 2011, including 29 days in February for the leap year. From this I simply extract the year part, 2011. So the UK tax year for 1 March 2012 is 2011. I could precompute 2011 and store that in a new column. But then if I move from the UK to Australia the fiscal year changes to July through June. More likely I have a company with a different accounting period than the fiscal year (very likely in the UK). That company then gets taken over by a US group that uses the calendar year, and everyone is happy, except my little app that thinks March 2012 is in 2011.
Here's some boilerplate to get going... with no attempt to group by year:
// The raw date for grouping by - no attempt to extract year
let date = NSExpressionDescription()
date.expression = NSExpression(format: "date_published")
date.name = "date"
date.expressionResultType = .DateAttributeType
// The number of books
let books = NSExpressionDescription()
books.expression = NSExpression(format: "count:(publication_title)")
books.name = "books"
books.expressionResultType = .Integer32AttributeType
// Put a fetch together
let fetch = NSFetchRequest(entityName:"Book")
fetch.resultType = .DictionaryResultType
fetch.propertiesToFetch = [date, books]
fetch.propertiesToGroupBy = [date]
// Execute now
var error: NSError?
if let results = context.executeFetchRequest(fetch,
error: &error) as Array<NSDictionary>? {
for row in results {
let date = row.valueForKey("date") as? NSDate
let books = row.valueForKey("books") as? Int
NSLog("%# %d", date!, books!)
}
} else {
NSLog("Fail!")
}
Thanks for any pointers!
As you're finding, this touches on something that's a weak spot in Core Data's API. It's common to explain that one shouldn't think of Core Data in terms of SQL because it uses a different approach. Dates are where this can be really annoying, because Core Data hides some SQLite capabilities. (They do this at least partly because Core Data isn't a SQLite wrapper, and can work with other, non-SQL storage systems).
The core problem is that Core Data's "Date" type corresponds to an NSDate, and NSDate in turn is just a floating-point number representing the number of seconds since a reference date. It doesn't include year, month, or day. Those values are not even fixed, because the instant in time represented by an NSDate might mean a different date in California as opposed to Japan, for example. The word "date" in these type names is unfortunately misleading.
This is why people generally recommend using extra fields, or at least different data types, for apps using Core Data that need to consider the actual date in some time zone as opposed to a precise moment in time regardless of zone. There isn't a good way to construct a Core Data query that operates on a "Date" field that does what you need. Dealing with this comes down to storing the data you actually need instead of something that just approximates what you need-- except that calling this type "Date" confuses the choice. You don't want a Core Data "Date" type here.
So let's consider one approach to getting the result you need while making SQLite do as much of the work as possible. Let's suppose you replace your date field with an integerDate field that represents the date as an integer (Core Data "Integer 64") using the format yyyyMMDD. Today would be stored as 20151223. In theory this could be done in one step with some NSExpression wizardry, but Core Data doesn't let you group by expressions, so that's out.
Step 1: Get all distinct year values
NSExpression *yearExpression = [NSExpression expressionWithFormat:#"divide:by:(%K,10000)", #"integerDate"];
NSExpressionDescription *yearExpDescription = [[NSExpressionDescription alloc] init];
yearExpDescription.name = #"year";
yearExpDescription.expression = yearExpression;
yearExpDescription.expressionResultType = NSInteger64AttributeType;
NSFetchRequest *distinctYearsRequest = [NSFetchRequest fetchRequestWithEntityName:#"Event"];
distinctYearsRequest.resultType = NSDictionaryResultType;
distinctYearsRequest.returnsDistinctResults = YES;
distinctYearsRequest.propertiesToFetch = #[ yearExpDescription ];
NSError *fetchError = nil;
NSArray *distinctYearsResult = [self.managedObjectContext executeFetchRequest:distinctYearsRequest error:&fetchError];
if (distinctYearsResult != nil) {
NSLog(#"Results by year: %#", distinctYearsResult);
}
NSArray *distinctYears = [distinctYearsResult valueForKey:#"year"];
In the above, yearExpression gets the year portion of integerDate by simple division. When the above completes, distinctYears contains all the years represented by integerDate.
Step 2: Loop through years, getting a count for each:
NSMutableDictionary *countByYear = [NSMutableDictionary dictionary];
for (NSNumber *year in distinctYears) {
NSFetchRequest *countForYearFetch = [NSFetchRequest fetchRequestWithEntityName:#"Event"];
countForYearFetch.resultType = NSDictionaryResultType;
countForYearFetch.propertiesToFetch = #[ yearExpDescription ];
NSExpression *targetYearExpression = [NSExpression expressionForConstantValue:year];
NSPredicate *yearPredicate = [NSComparisonPredicate predicateWithLeftExpression:yearExpression rightExpression:targetYearExpression modifier:NSDirectPredicateModifier type:NSEqualToPredicateOperatorType options:0];
countForYearFetch.predicate = yearPredicate;
NSError *fetchError = nil;
NSUInteger countForYear = [self.managedObjectContext countForFetchRequest:countForYearFetch error:&fetchError];
countByYear[year] = #(countForYear);
}
NSLog(#"Results by year: %#", countByYear);
This does a separate fetch for each year, but keeps the memory overhead low by only fetching the count of results instead of the actual data. When this finishes, countByYear has the number of entries by year, based on the integerDate field.
Having said all this, keep in mind that you do have the option of using SQLite directly instead of using Core Data. PLDatabase will give you an Objective-C style wrapper while still allowing raw SQL queries for everything SQLite can do.

Xcode Core Data in Tableview

my app is in the appstore and after updating to ios 8 and testing the app on my new iphone 6 the app doesnt work correctly.
ive already found the problem: i stored 3 dimensional arrays in nsuserdefaults and its giving me the error:mutating object sent to immutable....
so i can forget to store 3d arrays in nsuserdefaults, because i can`t really change those.
My idea was to store all the data in core data. GREAT!
But i gotta learn!
So....
I have got 5 attributes like you can see on the image:
when pushing an add-button all of the 5 attributes get saved by core data in the sqlite file.
The attribute "datum" of type date comes from a datepicker,so i can select a date. the other attributes are hours,minutes and some note - strings.
so, i want to look my tableview like this:
2014 <--- sectiontitle with year
-October <--- rows cell.text
-November <--- rows cell.text
2015 <--- sectiontitle with year
-January <--- rows cell.text
-May <--- rows cell.text
In this example i made entries for october+november in 2014 and january+may in 2015.
This means, this tableview is an overview to all the data,that i want to be filtered in the year and month.
what is the best approach to do this.
is there an easier way than: fetching the date, putting the dates into an array, setting dateformatter and find non-equal dates to get the years and the months?
because, when pushing a cell, for example october in section 0, a detailview opens and i want to display all entries i made in october in 2014.
What is your advice? Please help!!!
If user defaults is sufficient for your needs, I'd stick with it but convert the data to something mutable when you read it. You can convert an immutable property list to a mutable one using CFPropertyListCreateDeepCopy. As the name implies, it's a deep copy, and you can have it convert mutable containers and/or leaves to mutable equivalents.
If you read from user defaults into NSDictionary *userDefaultsData, convert with
NSDictionary *mutableData = CFPropertyListCreateDeepCopy(NULL, userDefaultsData, kCFPropertyListMutableContainers);
That will recursively copy the entire thing, converting NSDictionary to NSMutableDictionary and NSArray to NSMutableArray as it goes.
Thanks again Tom, you saved me from much work!!!
In appdelegate i changed...
stdPickerArray= [[NSMutableArray alloc] initWithArray:[def objectForKey:#"gesamtStdArray"]];
to...
stdPickerArray= [[NSMutableArray alloc] initWithArray:[def objectForKey:#"gesamtStdArray"]];
stdPickerArray = CFBridgingRelease(CFPropertyListCreateDeepCopy(NULL, (CFPropertyListRef)stdPickerArray, kCFPropertyListMutableContainers));
awesome!!!

Group UITableView by date without using coredata

I have an NSMutableArray with the latest 30 days records fetched from a DB.
Each record consists of a string and a creation date.
Now I want those records to feed an UITableView that will have a section for each different day and one cell per section simply showing how many records exist for each day.
Well, it's been hours of thinking and I'm not able yet to figure out how to do it. All the questions I've found on stackoverflow are related to core data, but I don't use it in my app.
Any help will be appreciated.
//after fetching data,write below code<br>
int cArray[30]; //create it as global array.cArray stores number of records that fall in particular date. if cArray[j]=10, it means for j'th date, there are 10 records.
// initialise all to zero.
for (int i=0; i<30; i++) {
cArray[i]=0;
}
NSArray *myArray;// my array stores your records.
[myArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
Record *rec = (Record*)obj;
cArray[(int)(rec.creationDate)]++;
}];
And later you can use cArray to show number of records that fall in a particular date.
Hope this helps.
I have implemented my data model similar to this case. I have an array of the NSDateComponents for each day and have a dictionary which keys is the date components that is stored in the array and values is the arrays that is store the data for each day. This approach is working pretty well for me.
You can group your data according to date. Then you can store grouped array on a dictionary and the key will be the date and this key will be your table header and the value will be the list of data at that date. I hope you got this approach.

Sorting an NSDictionary by Strings as days of the week

I have an NSDictionary as a TableViewDataSource. I want to show Sunday-Saturday as the keys, and for the value to be 0 or 1 if it's checked or unchecked. How do I go about sorting Sunday - Saturday since it's not a straight alphabetical order sort?
Or is there a better data structure I should be using for this? Thanks.
I would just use integers to represent the days of the week (ie. 0 - Sunday, 1 - Monday) and wrap them in NSNumber for easy sort. Then you can just map them back to the days of the week when you display them.

Resources