Sunday, December 4, 2016

How To: Create Custom Objects in iOS Apps

Hey guys. Another noobies tutorial!!!!! First, an intro. My latest app just been approved by Apple so I guess I will write about that (HA!! :P) The app is called QuikFlix. It is a movie database app. I made the app because I needed it. I was always trying to find old movies that I want to watch. For example, particularly, I wanted to find top/popular comedy movies in 2013. How do you go about finding that? Google works I guess. But navigating in browser really sucks. So I created QuikFlix with all the features that I WANT: Search movies by Genre, Year and Popularity. Plus, I added main casts list in there with movie synopsis. And you can easily see photo of the cast by tapping on their name. AND I also create a simple WishList so you can add movies you want to watch in this list. AND!!! I also added theme color. It is free app check it out here:

https://itunes.apple.com/by/app/quikflix/id1169970723?mt=8

I used TheMovieDB.com public API for this app. Their API is really good in my opinion. You can do a lot more actually (like have user accounts, rating ability).

Anyway intro finished, Lets begin tutorial. :D Here is what we're gonna make:



Cool huh? Btw, the more accurate title for this tutorial is "How to Subclass / Inherit an Object", but those words are intimidating aren't they? What does subclass means?

Well, it is simple, think of it like this - a factory produces a type of Computer Motherboard. You as a desktop PC seller, take this motherboard, add things on it, peripherals and what not, and voila you have your own desktop. Subclassing is much like this. The readily available objects in UIKit are like the computer motherboards in factory. You take that object, add stuff on it, make it do additional things and voila you have a "new" object.

To show you wonderful programmers how to subclass an object, we need to decide what to make first. Something easy but cool. We shall make a component for a calendar. A typical square with Day and Date, and we can tap on it to toggle the background color. With this object, we will make a month calendar. We will also try to make it support multi orientation so it appears nice in landscape or portrait.

First, create a single view application in XCode.

Next, right click on the Project Navigator panel and select New File... from menu. In the next window, select Cocoa Touch Class and click Next. Choose a name for it (in this case I name it "DayView") and select Class of UIView and click on Create button. You will see two files added to your Project - DayView.m and DayView.h.



Next, right click again the Project Navigator panel and choose New File... and this time, go to Resources in the left panel, and select View on the right panel. Click Next and name it DayView. You will see a DayView.xib file created in your project.

Now here is the important step to link between your Custom Class DayView.m/h and the DayView.xib you just created:

Click on DayView.xib's view and go to Object Inspector, and in Class textfield, type "DayView". Then press Return.


Next, add 2 UILabels on the DayView.xib. One will be used as the calendar "Header" where it will display Days (Sun, Mon, Tue, etc), and the other will be used to display the Date itself. Add the appropriate Constraints as you want. Here, I align the day label at the top left. and the date label at the bottom right. Then connect these 2 labels as IBOutlets in the DayView.h file.
You can add any object in here- for example, a UIImageView for background of the day cell, or another UIViews etc. Next, we need to write the init method for this DayView class. Enter the following code in DayView.m:



- (id)init
{
    self = [super init];
    if (self) {
        
        NSArray *arr =  [[NSBundle mainBundle] loadNibNamed:@"DayView" owner:self options:nil];
        self = [arr objectAtIndex:0];
        mode = 1;
        
    }
    return self;
}

What we do here is simple, we load the Xib file and return self in init method. So when the controller init this class, they will get the xib object as we have designed in storyboard. There is also a variable "mode" that I initialize here. "mode" is just an integer to be used to keep track of which day rect is being touched. If you require any more values/parameters to each "day", you can add them in the DayView.h file as properties, and synthesizing them in .m file. And then initialize their values in this init method.

Next, implement the touches delegate in this DayView and do the necessary changes when user tap on the day object. Here I simply toggle the background color Green<---->White.



-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    
    if (mode==1) {
        mode = 2;
        self.backgroundColor = [UIColor greenColor];
    } else {
        mode = 1;
        self.backgroundColor = [UIColor whiteColor];
    }
}

Now, in our main ViewController, we can already use our custom class by creating them in viewDidLoad.



    // create all dayviews
    for (int i = 0; i<35; i++) {
        
        DayView *dv = [[DayView alloc] init];
        dv.tag = 100+i;
        [self.view addSubview:dv];
        
    }

This code isn't complete. But this is how you create the custom class and add it to your view. You alloc and init it. Assign tag (so you can reuse it in other methods in the viewController), and add it to the view.

You also need to set the labels texts (can be accessed by using dv.dateLabel.text = @"12"; for example). I had to hardcode the total days in the month in this tutorial  project so you will get the idea how to use the custom object. You need to work out how to assign the date/days of the actual month by yourself.

The final part is to resize and reposition the DayView object:


-(void)viewDidLayoutSubviews {
    [super viewDidLayoutSubviews];
    
    // reposition and resize
    CGFloat wid = [[UIScreen mainScreen] bounds].size.width / 7.0;
    
    CGFloat xOffset = 0;
    CGFloat yOffset = 50;
    CGFloat dayHeight = 60;
    
    for (int i = 0; i<35; i++) {
        
        if ((i%7==0)&&(i!=0)) {
            xOffset = 0;
            yOffset += dayHeight;
        }
     
        DayView *dv = (DayView*)[self.view viewWithTag:i+100];
        dv.frame = CGRectMake(xOffset, yOffset, wid, dayHeight);
        xOffset += wid;
    }
    
}

viewDidLayoutSubviews is the View Delegates. This particular delegate gets called a lot, and it will get called when you rotate your device to landscape/portrait. It is a perfect place to resize/reposition your DayView objects.

That's all there is to it. Congrats now you have a month worth of calendar by using custom DayView object. Download the whole project by clicking icon below:


No comments:

Post a Comment