Archive for the ‘Programming’ Category
Saving NSArray in iOS
This is quick and dirty post. It’s more of a bookmark for me, because I find toggling between C# and Objective C makes me terrible with Objective C if I am away from it for a month or so.
The Requirement
- Save a list of records on the iPhone quickly and retrieve them later as required.
The Approach
Use the NSKeyedArchiver to save and load arrays of data.
Syntax
Setting up a file name and path to save save
// need a path
- (NSString *) getPath
{
NSString* path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
return [path stringByAppendingPathComponent:@"MyFile.dat"];
}
Save the data
// save an array
- (void) saveSettingsData: (NSArray*)data
{
[NSKeyedArchiver archiveRootObject:data toFile:[self getPath]];
}
Load the data
// get that array back
- (NSArray *) loadSavedData
{
return [NSKeyedUnarchiver unarchiveObjectWithFile:[self getPath]];
}
That’s about it. I have used it for saving an array of dictionary objects and it works just fine. I have not tried it for array of custom entities. Will update here as I try that. If that doesn’t work I have go deeper into the ManageObjectContext and PersistentStoreCoordinator and of course blog about it.
UPDATE: Well that didn’t take long. Just confirmed that you can only persist NSArray objects containing other NSArray or NSDictionary objects. You cannot serialize an NSArray instance of custom Entities. So the next article on ManageObjectContext is now on.
Sorting an NSArray of NSDictionary objects, based on values in NSDictionary
How to use sortedArrayUsingFunction
Today I came across a requirement where I had to Sort an NSArray. Each element of the array had a NSDictionary which had only one element, which was a NSArray. Structure was like:
NSArray
—->NSDictionary
—->—->”somekey1″ – NSArray [val1, val2, val3... val-n]
—->NSDictionary
—->—->”somekey2″ – NSArray [val1, val2, val3... val-m]
—->NSDictionary
—->—->”somekey3″ – NSArray [val1, val2, val3... val-o]
:
:
—->NSDictionary
—->—->”somekey-x” – NSArray [val1, val2, val3... val-w]
(where n!=m!=o!=w)
I wanted this NSArray to be sorted so that the NSDictionary with the largest number of NSArray values in it should come on sorted.
After looking at the available options in Apple’s Documentation here I decided to define a selector (‘delegate’ for other .NET folks like me) and provide the selector to the sortedArrayUsingFunction method available for an NSArray.
The sorting function looks like this
NSInteger sortByArrayCount(id dictionary1, id dictionary2, void *reverse)
{
NSMutableDictionary *dict1 = (NSMutableDictionary *)dictionary1;
NSMutableDictionary *dict2 = (NSMutableDictionary *)dictionary2;
NSArray *arr1 = (NSArray *)[[dict1 objectEnumerator] nextObject];
NSArray *arr2 = (NSArray *)[[dict2 objectEnumerator] nextObject];
NSLog(@"Count of Array 1: %d, Array 2: %d", [arr1 count], [arr2 count]);
if(*(BOOL *)reverse == YES)
{
return ([arr2 count] > [arr1 count]);
}
else
{
return ([arr1 count] > [arr2 count]);
}
}
I think the code is quite self explanatory, we convert the values passed into the method. Then extract the first element in the dictionary as NSArray, finally I check if reverse==YES is passed or not this flag indicates whether you want a Descending sort or not. Finally do the comparison.
To sort an array you call it as follows:
NSArray *sortedArray; BOOL reverseSort = NO; sortedArray = [catList sortedArrayUsingFunction:sortByArrayCount context:&reverseSort];
Point to note here is once you have got the NSDictionary you could make the sorting condition on any of the values in the dictionary. For example string compare the Key of the two inputs.
The sortArrayByFunction method offers a lot of flexibility in terms of deciding how you want to sort. My case was a unique one.
Other options to explore are ofcourse using sortDescriptors if you wanted to sort based on string values in NSArray of NSDictionaries.
That’s about it for now. Have fun.
(Yay! to my first iOS article)
Entity Framework and MS Web Stack of Love – First Steps
Things they didn’t show you at MIX keynotes ![]()
Okay, so you saw the MIX keynotes and were really really impressed with what MVC, EF 4.1 Code First and Scaffolding could do for you and excitedly sat down to try and get your old lumbering enterprise app transformed using the Web Stack of Love. Couple of steps in and you start stumbling around. Visual Studio throws errors, things stop working and you are scratching your head as to where you went wrong! Well happened to me and I got lucky in finding the solutions quickly with help from the community. Here are the details.
Model First or Database First with EF 4.1
As mentioned above the first thing I tried to do was get my old lumbering enterprise app moved to the new MVC platform. Now when you have an enterprise platform you can’t throw it away with the accumulated data of last 5 years. So the easiest way is to go Database first, reverse engineer the database to generate your data model. Below are the steps you would follow
- Create an ASP.NET MVC Web Application using the new project template
- Create a generic Class library project
- Add ADO.NET Entity Data Model file (edmx) to the class library
- Generate model from DB Connection by connecting to the database. So far so good, no issues.
- Now you add reference to your database project to the web project, copy the connection string over from the class library’s app.config to web app’s web.config, and build it. Everything builds fine.
- You right click on the Controller folder and select Add Controller and the MVC tooling wizard comes up. You select your root entity name and ask it to generate the controller, Visual Studio whirrs for a while and bam! Error!
—————————
Microsoft Visual Studio
—————————
Unable to retrieve metadata for ‘Your.Data.Entity’. The type ‘Your.Data.Entity’ was not mapped. Check that the type has not been explicitly excluded by using the Ignore method or NotMappedAttribute data annotation. Verify that the type was defined as a class, is not primitive, nested or generic, and does not inherit from EntityObject.
—————————
OK
————————— - So what did you miss. Well EF is all code first so the old style generation of Entities (EF < v4) fail to work. If you read the last line of the error ‘… and does not inherit from EntityObject’ it gives you a hint.
- What now? Manually edit everything? That would defeat the whole purpose of O-R mapping right? Well solution was provided by Julie Lerman (MS MVP) in her blog here. I’ll summarize here.
- Go back to EDMX file and open the EDMX designer.
- Right click and select ‘Add Code Generation Item’.
- From the ‘Add New Wizard’ select ADO.NET DBContext Generator. You’ll see it gives a Model1.tt (t4 template) name. Change the name if you want to and select Add.
- You will see under in the class library a node gets added with the t4 template. When you expand the node you have the C# (or VB) classes for your entities.
- Now build and re-try scaffolding the Controller and things will go through smoothly.
Taming the SQL Compact 4.0 for Model First Development
Here is another workaround for people who want to do Model First Development. Since SQL Compact 4.0 was released out of band from Visual Studio and .NET 4.0 releases, somewhere in the tooling chain something broke. As a result, when you try to add a new Connection using Generate Database Wizard you don’t see SQL Compact 4.0. You see up to 3.5 only. So how do you get 4.0 goodness?
Refer to the selected answer from this stackoverflow.com thread
The answer is pretty to the point so I won’t repeat it here.
Trouble with Modernizer.js (ver 1.7.x only on VMs)
If you run your dev environment on a VM (like VM Ware on Mac), IE9 disables hardware rendering and the modernizer.js that ships by default keeps throwing exception ‘Microsoft JScript runtime error: Unexpected call to method or property access’. This happens for every page and become very irritating quickly.
Solution is to go to www.modernizer.com and download their latest library (2.0.6 at the time of writing this). Remove the 1.7.x reference from your web application and add 2.0.x version. Voila!
That’s about it for now. I’ll put down more of my experiences as I go forward with my EF adventures. When I started this article we had only 4.1 now we have 4.2 CTP out
. Fast! Very Fast!
Leave a Comment