Showing posts with label bitcode Technologies. Show all posts
Showing posts with label bitcode Technologies. Show all posts

Sunday, 15 April 2012

Core Data


Core Data

In simplest terms, Core Data is an object graph that can be persisted to Disk. [...] Core Data can do a lot more for us. It serves as the entire model layer for us. It is not just the persistence on disk, but it is also all the objects in memory that we normally consider to be data objects.
—Marcus Zarra, Core Data
Core data that would be it is used to store data from your iPhone application into a sqlite file which is present in the document directory of your application. Core data is a framework that provides you the support to make your data objects persist in the memory.  As a programmer you are supposed to deal more with the objects and less with the sql queries, opening the db connection, closing the db connection etc. Core data makes you focus on that part better. You will be creating objects and core data will take care of storing the objects in the memory. You send a fetch request and core date will fetch those objects from the database to the main memory back again. This is how it works.
With the release of version 3.0, Apple has made their Core Data system available on the iPhone OS. Core Data has been available on the Macintosh platform for a number of years, and provides a high-level data abstraction framework that offers integrated design tools and runtime support to address complex data management needs unlike SQLite, the Core Data model is not strictly relational in nature.

if core data is used to store data for our application then why do we use SQlite,

Sqlite is a relation db, so you can use SQL to talk to a sqlite database. You can create tables, columns. You can create relationships between these tables etc. So you will be having a sqlite database file and a C language API to open the db connection, executing an SQL query and closing the db. This way you can persist the data from your application.
Core Data is not a relational database. Though you can go for sqlite as a store type where core data stores the data, its not a relational database. Rather we should not compare it with relation database. It’s an object graph persistence system. You can user core data to persist objects on the hard drive. Some operations are not possible with core data like Join Query, Merge query, Union query, inner query etc.


Core Data Architecture

In Core Data each and every entity is referred to as objects, objects that have relationship with them. Let’s say there are two entities Parent and Child having relationship with them then in this case Parent and Child will be referred as objects and in Core data and you can easily manipulate them. If your application is particularly well suited to the Relational Model, there may be advantages to having direct SQL query access to the data storage layer. Some of the basic classes that you must know in order to precede with core data are given below:



 Core Data Architecture


ManagedObject: Managed objects are the objects that are created by your application code to store data. A managed object can be thought of as a row or a record in a relational database table. For each new record to be added, a new managed object must be created to store the data. Similarly, retrieved data will be returned in the form of managed objects, one for each record matching the defined retrieval criteria. Managed objects are actually instances of the NSManagedObject class, or a subclass thereof. These objects are contained and maintained by the managed object context.
Persistance store coordinator: The persistent store coordinator is responsible for coordinating access to multiple persistent object stores. As an iPhone developer you will never directly interact with the persistence store coordinator and, in fact, will very rarely need to develop an application that requires more than one persistent object store. When multiple stores are required, the coordinator presents these stores to the upper layers of the Core Data stack as a single store.

Managed Object Context: Core Data based applications never interact directly with the persistent store. Instead, the application code interacts with the managed objects contained in the managed object context layer of the Core Data stack. The context maintains the status of the objects in relation to the underlying data store and manages the relationships between managed objects defined by the managed object model. All interactions with the underlying database are held temporarily in within the context until the context is instructed to save the changes, at which point the changes are passed down through the Core Data stack and written to the persistent store.

We will be following some steps to make the core data application so that we don’t mess up while using core data. We are going to work with the database having two entities Album and Song . We will have two tables Album and Song. Album will have two attributes name and year. Song will have one attribute name.

* Create a new project , select Empty Application ( Window based Application on XCode ). This time, check the checkbox saying, “Use core data”



Once you create project, you will see below files


You can see the CoreData framework and a CoreDataDemo.xcdatamodeld file have been added in the project. If you observer AppDelegate.h, three properties must have been added too.
@interface AppDelegate : UIResponder <UIApplicationDelegate>
{

}
@property (strong, nonatomic) UIWindow *window;

@property (readonly, strong, nonatomic) NSManagedObjectContext *managedObjectContext;

@property (readonly, strong, nonatomic) NSManagedObjectModel *managedObjectModel;

@property (readonly, strong, nonatomic) NSPersistentStoreCoordinator *persistentStoreCoordinator;

- (void)saveContext;
- (NSURL *)applicationDocumentsDirectory;

@end

All three are ready only. If you go to AppDelegate.m, a getter method has been defined for all three properties. These getter methods setup the coredata database and all the required objects that are managedObjectContext, managedObjectModel and persistentStoreCoordinator.  You can go ahead and check the AppDelegate.m for these getter methods.
Next lets open the CoreDataDemo.xcdatamodel file. This file represents the database schema of the database. It opens in a GUI editor into the XCode only. We will be designing the database schema using this editor. It should look like below.


This displays the database schema in two different editor style. You can see an Editor style button at the bottom right.





                                               Style 1                                              Style 2


Style 1 is what it looks like in the above screenshot. We will be using this style to actually edit the database schema. We will be adding new Entities ( Tables ) , attributes (columns) to an Entity . We will be adding the relationships in two Entities etc.
Style 2 will displays the graphical representation of the schema. Once done designing the schema in the first style, you can verify that in the second style visually.
Style 2 looks like as the screen shot below.


Ok, lets switch to the style 1 and start designing the database schema. You will see left pane with three sections Entites, Fetch Requests and Configurations.
Click on “Add Entity” button at the bottom. This will add the entity. Name it Album. Then add the attributes to the Album table in the Attributes section on the right.






Same way, add Song Entity and add an attribute “name” in the Song table.


Next we need to add relationships in these two entities.  Select the Album entity and add a relation ship there. Give it a name albumToSong. Set the Destination as “Song”.



In the details view on the right side, we need to set some more properties. Check the “To-Many Relationship” checkmark. This how we can specify that Album to Song is one-to-many relationship. An Album can have multiple songs.

There are some other advanced options that you can set as well eg. You may set the Delete Rule to Cascade if you want.
Next add a relationship to the Song Entity. Name it  “songToAlbum”. You can simply make it the inverse of “albumToSong” by selecting it into the last drop down list. It should then look like below.


You can visually verify the design by changing the editor style to style 2. It should look like below.

That’s it, we are done with the design of the database schema. Its time to create the NSManagedObject classes for Album and Song entities.
Select these two entities and right click on resources section. Click on “Add New file” option. Navigate to CoreData section over there and select the NSManagedObject subclass. Click next and on the next page click create. This will add two classes to the project that are Album and Song.




The resources should have two more classes now.


If you check out the classes, every class has go the needed method. Like Album should have a methods like

-   (void)addAlbumToSongObject:(Song *)value;
-   (void)removeAlbumToSongObject:(Song *)value;
-   (void)addAlbumToSong:(NSSet *)values;
-   (void)removeAlbumToSong:(NSSet *)values;

Same goes for Song. All the required methods must have been added to the Song class as well. Now its time to go the AppDelegate and perform some operations like inserting objects to and reading objects from the database.
Go to AppDelegate.m and write a method insertData as below. insertData will insert some objects in to the database
                    
-(void)insertData
{
    Album * alb1 = [NSEntityDescription insertNewObjectForEntityForName:@"Album" inManagedObjectContext:self.managedObjectContext];
    alb1.name = @"Rockstar";
    alb1.year = [NSNumber numberWithInt:2011];
   
    Song * s1 = [NSEntityDescription insertNewObjectForEntityForName:@"Song" inManagedObjectContext:self.managedObjectContext];
    s1.name = @"Sadda haq";
   
    Song * s2 = [NSEntityDescription insertNewObjectForEntityForName:@"Song" inManagedObjectContext:self.managedObjectContext];
    s2.name = @"Jo Bhi Main";
   
    Album * alb2 = [NSEntityDescription insertNewObjectForEntityForName:@"Album" inManagedObjectContext:self.managedObjectContext];
    alb2.name = @"Nirvana";
    alb2.year = [NSNumber numberWithInt:1988];
   
    Song * s3 = [NSEntityDescription insertNewObjectForEntityForName:@"Song" inManagedObjectContext:self.managedObjectContext];
    s3.name = @"Come as You are";
   
    Song * s4 = [NSEntityDescription insertNewObjectForEntityForName:@"Song" inManagedObjectContext:self.managedObjectContext];
    s4.name = @"The man who sold The World";
   
    [alb1 addAlbumToSongObject:s1];
    [alb1 addAlbumToSongObject:s2];
    [alb2 addAlbumToSongObject:s3];
    [alb2 addAlbumToSongObject:s4];
   
    [self.managedObjectContext save:nil];
   
}


In the above method, we are creating two Album objects alb1 and alb2. There are four Song objects s1,s2,s3 and  s4. After that we add song objects to the corresponding album objects. Finally we save the context. Till this line all objects are created in the context. In order to save the objects into database, you need to call save method on the context object.  Lets call this method from didFinishLaunching as below.

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];

    [self insertData];
   
    self.window.backgroundColor = [UIColor whiteColor];
    [self.window makeKeyAndVisible];
    return YES;
}


Run the App and it will insert the data into the database. Next we write a readData method that will read the data from the database.

-(void)readData
{
    NSFetchRequest * req = [[NSFetchRequest alloc]init];

    [req setEntity:[NSEntityDescription entityForName:@"Album" inManagedObjectContext:self.managedObjectContext]];
   
    NSArray * result = [self.managedObjectContext executeFetchRequest:req error:nil];
   
    for (Album * alb in result)
    {
        NSLog(@"Album Name : %@",alb.name);
        NSLog(@"Album Year : %@",alb.year);
       
        for( Song * sng in alb.albumToSong )
        {
            NSLog(@"    Song Name : %@",sng.name);
        }
    }     
}

NSFetchRequest : This class is used to create query objects.
We create fetch request, then set the Entity to Album. This is going to be simple “ select * from Album” query. After that we execute the fetch request on the context object. Context executes the fetch request and returns the result. The result of the query is going to be an array of Album objects. So we catch it in an array called “result”. After that we iterate through the “result” array and print the Album objects. When we get an album object we can access the “albumToSong” property of it to access all the song objects for this album. This property is of type NSSet because an album can have multiple songs as per the one-to-many relationship. We then iterate over all the songs for an album and print those as well.  Lets give a call to the readData method from didFinishLaunching and comment the insertData call.

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];

    // [self insertData];
   
    [self readData];
   
    self.window.backgroundColor = [UIColor whiteColor];
    [self.window makeKeyAndVisible];
    return YES;
}


Run the App and you should see the below output on the Console.




Tuesday, 6 December 2011

Custom Number pad on iPad

Hello all , recently in one project I had to build a number pad keyboard which will allow user to enter just the number and that's it . On iPad unlike iPhone the UIKeyboardTypeNumberPad does not work . Even if you use this , it brings up the default keyboard . On iPad there is a pretty amount of space , so Apple might not have considered this UIKeyboardTypeNumberPad keyboard as the requirement on iPad . Well second thing about the default keyboard is that it is too big , cause I just want to enter numbers nothing else . So here we go and create our custom number pad to enter the numbers in a text field. To get an idea how it will look , just check out the image below.

Note : This number pad is very specific to iPad , as we will be using UIPopOverController designed for iPad only.

 


Two things we are going to do here .
1) We don't want the default keyboard to pop up when user hits the text field .
2) We want our number pad not to pop up from the bottom of the screen but just right below the text field in a popover .


Lets start with it . Create an iPad project , you can select the view based Application , then next select the iPad from the device list. Name it "CustomNumericKeyboard" . You should see below files in your project .




Drag and drop the below files in the project . You will find these in the sample code attached at the bottom.
1) NumericKBViewController.h
1) NumericKBViewController.m
1) NumericKBViewController.xib

Now your resources pane should look like this .




Next import the "NumericKBViewController.h" at the top of your "CustomNumericKeyboardViewController.h" . Now your class file should look like below .
#import <UIKit/UIKit.h>
#import "NumericKBViewController.h"

@interface CustomNumericKeyboardViewController : UIViewController
{

}
@property(nonatomic,retain) IBOutlet MTextField * textField;

@end

Note down that I have created a custom UITextField class for this purpose , so I am creating an outlet with MTextField object instead of UITextField. MTextField class resides in the "NumericKBViewController.h" that we have added just now to our project. I will shortly highlight why I did this. Next add a text field on the xib file . At this moment don't try to connect the outlet that we have created . Before that you have to set the class for the text field as "MTextField" . How to do that ? check the screen shot below .









Select the text field , go to the right detail pane on the right side . In the third tab ( Identity inspector ) , it will show you the class name as UITextField . Just make it as MTextField . Once you set that , you can connect the IBOutlet that we have created in the class header with this text field on the xib.


In the viewDidLoad method of the view controller , add the below lines of code.


- (void)viewDidLoad
{
    [super viewDidLoad];
    [self.textField addTarget:self action:@selector(textFieldTouched:) forControlEvents:UIControlEventTouchDown];
   
}


Next add a method just after this


- (void)textFieldTouched:(id)sender {
       
    MPopOverController * popOver = [MPopOverController kbPopOverControllerForTextField:self.textField];
    [popOver presentPopoverFromRect:textField.frame inView:self.view permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];
   
}


And thats it , build and run your project , you should see a nice text field . Click on it and it will bring up the custom number pad which is far much easier and friendlier to enter the number compared to the default keyboard .


Download the Project Code here .


Try to understand the code , its actually quite easy. If you don't, let me explain that to you.


Below are some classes used.


MTextField
text field and few more views have the property called as inputView . This view is nothing but actually the keyboard view in case of the text field . So the thing we did is we are overriding the -(UIView*)inputView getter for the property inputView. Here we return a transparent empty UIView object. Now if users taps the textfield , a transparent view will popup from the bottom instead of the keyboard . Id you want to test this go to this method and try changing the backgroundColor of the view that we return over here and you will see what happens.


NumbericKBViewController
Its a view controller which actually displays our number pad . It actually holds the reference of the text field for which we are displaying this view controller . For more info , you can check out the IBOutlets and IBActions on how it manages the number entry part .


MPopOverController
Well Its simply a UIPopOverController subclass customized to suit our need . I will be using this custom number pad at lots of places in my project , so just wanted to make it a concrete independent utility that I can use with few lines of code at any place . And thats how even the demo project attached above uses it.


Well thats all for now . I hope this post will help you understand How to create Custom Keyboard , PopOverController to make things easy and really beautiful on iPad Apps . Keep checking for more posts soon . For any queries feel free to main me on bharat.jagtap@bitcode.in … Thank You !!





Friday, 10 June 2011

Displaying UITableView


The most important component in a mobile is table, your music player contains a list of songs which you touch they begin to play well the component which holds all those songs is your table. In this blog i will demonstrate you on how to display names in the table from an array. Here's a glimpse of our final output




Step 1: Open Xcode and create a window based application and add a class file, only this time it wont be a view controller class it would be a UITableViewController subclass.





Now save this UITableViewController subclass file with an appropriate name.

Step 2: Go to the .h file of your tableview controller class, i have named my file as MyTableViewController, declare an object of NSArray class which will hold the names of the countries which we want to display in our table, here's the code for that

@interface MyTableViewController: UITableViewController {
 NSArray *table_content;
}
@end

Step 3: Now go to the .m file of MyTableViewController and add objects to the array called table_content in the init method

- (id)initWithStyle:(UITableViewStyle)style {
    if (self = [super initWithStyle:style]) {
table_content = [[NSArray alloc]initWithObjects:@"India",@"Germany",@"USA",@"South Africa",@"China",@"Japan",nil]; 
    }
    return self;
}

Step 4: since you have took a UITableViewController subclass then in this case you will be provided by the datasource and delegate methods by the tableviewcontroller subclass in your source code file here's how those method looks like




Let me give you an small explanation on those datasource protocol methods of the UITableViewController class

UITableViewDataSourceProtocol: The UITableViewDataSource protocol is adopted by an object that mediates the application’™s data model for a UITableView object. The data source provides the table-view object with the information it needs to construct and modify a table view. As a representative of the data model, the data source supplies minimal information about the table view’s appearance. The table-view object’s delegate—an object adopting the UITableViewDelegate protocol—provides that information. The required methods of the protocol provide the cells to be displayed by the table-view as well as inform the UITableView object about the number of sections and the number of rows in each section. The data source may implement optional methods to configure various aspects of the table view and to insert, delete, and reorder rows. Many methods take NSIndexPath objects as parameters. UITableView declares a category on NSIndexPath that enables you to get the represented row index (row property) and section index (section property), and to construct an index path from a given row index and section index (indexPathForRow:inSection: class method). (The first index in each index path identifies the section and the next identifies the row.)

UITableViewDelegate: The delegate of a UITableView object must adopt the UITableViewDelegate protocol. Optional methods of the protocol allow the delegate to manage selections, configure section headings and footers, help to delete and reorder cells, and perform other actions. Many methods of UITableViewDelegate take NSIndexPath objects as parameters and return values. UITableView declares a category on NSIndexPath that enables you to get the represented row index (row property) and section index (section property), and to construct an index path from a given row index and section index (indexPathForRow:inSection: method). Because rows are located within their sections, you usually must evaluate the section index number before you can identify the row by its index number.

a) numberOfSectionsInTableView:  - Specifies the total number of sections in a table view.

b)tableView: numberOfRowsInSection: - how many rows would be present in a table.

c)tableView: cellForRowAtIndexPath: - set the text for table.

d)tableView: didSelectRowAtIndexPath: - performs some action when the user selects any row of the table. 

These are the important methods which will be provided by the UITableViewController subclass by default in your source code file.

Step 5: now we will set the row and text of our table with the help of the functions tableView numberOfRowsInSection and tableView cellForRowAtIndexPath.

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return [table_content count];
}

The above function tells how many rows will my table have, We have used the count method of the array, as we want the rows of the table as per my array count.

Now the next function is tableView cellForRowAtIndexPath and the only one line of code that you have to write in it is 

cell.textLabel.text = [table_content objectAtIndex:indexPath.row];

Step 6: Now go to the app delegate .m file and add the view to the window like this

#import "SimpleTableAppDelegate.h"
#import " MyTableViewController.h"
@implementation SimpleTableAppDelegate
@synthesize window;

- (void)applicationDidFinishLaunching:(UIApplication *)application {    

    // Override point for customization after application launch
 MyTableViewController *mtvc = [[MyTableViewController  alloc]initWithStyle:UITableViewStyleGrouped];
        [window addSubview:mtvc.view];
        [window makeKeyAndVisible];
}

Step 7: Build and run the application you will see the following output


Final output


Display Selected Text: Lets say you want to display the selected text of the Table into an alert view then in that case you can use the tableView didSelectRowAtIndexPath function. Here's the code to do that


- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *str = [NSString stringWithFormat:@"%@",[table_content objectAtIndex:indexPath.row]]; //typecasting
UIAlertView *alertbox = [[UIAlertView alloc]initWithTitle:@"Table Demo" message:str delegate:nil cancelButtonTitle:@"Cancel" otherButtonTitles:@"OK",nil];
 [alertbox show];
}


Now when you run the application and select any of the rows of the table you will get the output just like the below images