Sunday, April 28, 2013

Lazy Image Loading

Tutorial request from Senthil.P

1. Create a new Xcode Project, Single View Application template and add a tableview. (http://iosmadesimple.blogspot.com/2012/10/adding-uitableview-tutorial.html)

2. Create a custom table view cell.
(http://iosmadesimple.blogspot.com/2012/10/uitableviewcell-using-interface-builder.html)

3. Download SDWebImage latest framework here. (https://github.com/rs/SDWebImage/wiki/Download-Complied-Framework)

Assuming everything's done, what's left for us to do is to include SDWebImage Library and use it in our project.


4. Right-click to your Project Navigator, Add Files to your project.

Add "SDWebImage.framework" from the one you downloaded from Step 3. Check "Copy items into destination group's folder (if needed)"



5. In our project's Build Phases, under Link Binary With Libraries, click the ( + ) button.

And add "ImageIO.framework."
6. In our Project's Build Settings, search for "Other Linker Flags," double-click the right area of the "Other Linker Flags," click ( + ) button and input -ObjC


7. In the source files where you need to use the library,
#import <SDWebImage/UIImageView+WebCache.h>

8. Add an image file that will be used as our "placeholder" image. This image will be shown while the image from the URL has not yet finished loading.


9. Add entries to your array that holds the important information like the URL of the images you want to load.
- (void)viewDidLoad
{
    [super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
    
    items = [[NSMutableArray alloc] init];
    [items addObject:@"http://i0.wp.com/hypebeast.com/image/2013/01/hot-toys-iron-man-3-mark-xlii-collectible-bust_1.jpg?w=1410"];
    [items addObject:@"http://t0.gstatic.com/images?q=tbn:ANd9GcT4PZc648WRoXzxEdLQA9zMGqBx93_um_HxvsjgYhoY3AvDtkzI"];
    [items addObject:@"http://i0.wp.com/hypebeast.com/image/2013/03/hot-toys-iron-man-3-iron-patriot-collectible-bust-2.jpg?w=930"];
    [items addObject:@"http://t3.gstatic.com/images?q=tbn:ANd9GcTf_6e7G9pIiw7ZlRRPfdq63NP-jRA6tmstL1ji-ZFEVnTkDjSp"];
    [items addObject:@"https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEinO2ufQwjCMHOhzFl6EcKEfs-4zkXEtX1FOQmAp7vUl3tCs0ome9KUOU_bAZdla02lwhdpOOyZMTl1S8vvvclt5HsyUpq9MJZl9GVzS8SWdwHJdZjO6ynYkdC3XB_TYZDdI_JGGpIs2Fk/s1600/iron-man-3.jpg"];
}

10. Edit our tableview's cellForRowAtIndexPath...
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    static NSString *CellIdentifier = @"MyImageCell";
    ImageCell *cell = (ImageCell *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    
    if (cell == nil) {
        NSArray* topLevelObjects = [[NSBundle mainBundle] loadNibNamed:@"ImageCell" owner:self options:nil];
        for (id currentObject in topLevelObjects) {
            if ([currentObject isKindOfClass:[UITableViewCell class]]) {
                cell = (ImageCell *)currentObject;
                break;
            }
        }
    }
    
    // Here we use the new provided setImageWithURL: method to load the web image
    [cell.imageView setImageWithURL:[NSURL URLWithString:[items objectAtIndex:indexPath.row]]  placeholderImage:[UIImage imageNamed:@"Hisoka.jpg"]];
    cell.imageSource.text = [items objectAtIndex:indexPath.row];
    
    return cell;
}

11. Hit Run!



There are still many ways to use SDWebImage Library, just check their API Documentation and other ways to use it in: (https://github.com/rs/SDWebImage)

Download Project here.


Tuesday, April 9, 2013

Adding/Deleting Rows Dynamically (UITableView)

To answer Mr. Ramanan R Rengaraj's question "How to add an add and delete button in nav bar to insert / delete rows dynamically."

Prerequisite:
1. UITableView (http://iosmadesimple.blogspot.com/2012/10/adding-uitableview-tutorial.html)
2. UINavigationController (http://iosmadesimple.blogspot.com/2012/08/navigation-based-project-doing-it.html)

This tutorial will be based mainly from the UITableView tutorial, I'm only going to tweak it a little so we can add and delete rows dynamically.

Let's start!

1. Create a new Xcode Project, and choose a Single View Application template. After creating a Single View Application Project, you will see that there is an AppDelegate and a ViewController class. We will not be using the ViewController class, you may choose to delete it from your project.



2. Create a New File, Objective-C class, subclass of UITableViewController. In my case, I named it MyTableViewController.

3. Click MyTableViewController.xib file, select the tableview.  Choose the "Grouped" Style under Table View. 
//You may choose to change the View size from Retina 4 Full Screen to Retina 3.5 Full Screen under Simulated Metrics.

Grouped Style Table View allows us to see the adding and deleting of rows dynamically.

4. Select the AppDelegate.h file, import MyTableViewController class. Add a MyTableViewController property and a UINavigationController property. Synthesize these properties in your AppDelegate.m file.

@property (strong, nonatomic) MyTableViewController *viewController;
@property (strongnonatomicUINavigationController *navController;

5. Go to AppDelegate.m file, under ApplicationDidFinishLaunchingWithOptions method, create and initialize your viewController property. Next, create and initialize your navController such that your navController's rootViewController is your viewController variable. Set window's rootViewController with your navController.

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    // Override point for customization after application launch.
    
    self.viewController = [[MyTableViewController alloc] initWithNibName:@"MyTableViewController" bundle:nil];
    self.navController = [[UINavigationController alloc] initWithRootViewController:self. viewController];
    self.window.rootViewControllerself.navController;
    [self.window makeKeyAndVisible];
    return YES;
}


6. Go to MyTableViewController.m file. Create an array variable (NSMutableArray) for the list of items we want to show in our tableView. I also have an int variable which will be useful for this tutorial.
NSMutableArray *items;
int num;


7. Under viewDidLoad of MyTableViewController, we will set the title and the items in our array, set the num of our int variable and create the two navigation buttons for add and delete.

 // Set Title
self.title = @"Items";

// Set initial values in our array
items = [[NSMutableArray allocinitWithObjects:@"Item No. 1"@"Item No. 2"@"Item No. 3"@"Item No. 4"@"Item No. 5"@"Item No. 6"nil];


// Set int variable, since our last item number is six, we will also set this int variable to six.
num = 6;

// create the two navigation buttons
    UIBarButtonItem *addButton = [[UIBarButtonItem alloc]
                                   initWithTitle:@"Add"
                                   style:UIBarButtonItemStyleBordered
                                   target: self
                                   action:@selector(addItemToArray)];
    self.navigationItem.rightBarButtonItemaddButton;
    
    UIBarButtonItem *delButton = [[UIBarButtonItem alloc]
                                  initWithTitle:@"Del"
                                  style: UIBarButtonItemStyleBordered
                                  target: self
                                  action:@selector(delItemToArray)];
    self.navigationItem.leftBarButtonItem delButton;


8. Implement the addItemToArray and delItemToArray methods in our MyTableViewController class.
//Add Item To Array
- (void)addItemToArray {
    num++;
    [items addObject:[NSString stringWithFormat:@"Item No. %d", num];
    [self.tableView reloadData];
}


//Delete Item To Array
- (void)delItemToArray {
    num--;
    [items removeLastObject];
    [self.tableView reloadData];
}

9. Lastly, let's update the codes in our TableView Data Source methods. 
//The codes in our Data Source methods are just the same with the codes on our previous UITableView tutorial.
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    // Return the number of sections.
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
    // Return the number of rows in the section.
    // Usually the number of items in your array (the one that holds your list)
    return [items count];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    //Where we configure the cell in each row

    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell;
    
    cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[UITableViewCell allocinitWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
    }
    // Configure the cell... setting the text of our cell's label
    cell.textLabel.text = [items objectAtIndex:indexPath.row];
    return cell;
}





10. Done! Hit Run!

//At first run, we'll see the initial values in our array.

//Hit Add button.


//Hit Delete Button.

Download Project Code 

Blocks From one Class to Another

One popular scenario in using blocks is when you need to update your view after a web service call is finished.