Menu

iOS app: From scratch to app store Part 3

09 October 2016

Custom TableViewCellHere is the link to the project we worked on in part two. We will build on this. The project was initially written in Swift 2.2 but I have updated it to swift 3. In part 2 we agreed will be building a custom cell to display each movie/tv shows. Here is a screen shot of what we want to achieve.
<img src="/content/images/2016/08/IMG_3366-1.PNG" alt="Alt Text" text-align:"center" style="width:200px;height:300px;">

At the top we have a label for the name of the movie/tv show. Right below the name is an image. Next is a label for the release date and finally a summary/synopsis. Also the cells is designed as cards with the edges curved a bit.

Click on MoviesTableViewCell.xib. This is where we will design the custom cell and support it with little code.
Select the cell, click on size inspector. For Row Height check custom, and give it a height of 350. Below RowHeight you will find Width and Height properties of the cell. Set width to 320 and height to 340. We will let the content of the cell determine the size of the cell but for now 350 gives us a size to work with in the interface. The editor area should like this now

Drag a view from the Object library onto the cell’s Content View. With the view selected, click on Pin and pin the view to all corners of the content view. top:5, bottom:5, leading:8, trailing:8.
<img src="/content/images/2016/10/pinCardView.png" alt="Alt Text" text-align:"center" style="width:500px;height:300px;">

Let’s call this view, “Card View”. To do this, click on identity inspector, just right below “Document” you will “Label”, enter “Card View” for the field.

Create an IBOutlet for the view. You do this by opening the assistant inspector and click > dragging (while holding control button) from card view to it’s class. Call the outlet cardView.

Notice the “Spring Wood” color of the background of the card in the screenshot. Lets apply the same color to our card view. We will do this in a UIView method called layoutSubviews. According to apple:

Subclasses can override this method as needed to perform more precise layout of their subviews. You should override this method only if the autoresizing and constraint-based behaviors of the subviews do not offer the behavior you want. You can use your implementation to set the frame rectangles of your subviews directly.

Though layoutSubviews sounds likes where we can only alter the layout/frame of our subviews, we can also take advantage of it to alter some other components of the subviews that doesn’t relate to the views frame.

The first line of code sets the background color of the card. To set color in iOS, we use the UIColor object which has an init methodinit(red: CGFloat, green: CGFloat, blue: CGFloat, alpha: CGFloat)
this takes opacity and RGB component values to create and return a color object

There is a tiny faint-colored border line around the card. We give the card a borderWith of 1 and set the color of the border to lightGray. We get the color using the UIColor object, adjust the opacity to 0.3.

The edges of the card is not sharp, it’s a little curved. To achieve this, we set the cornerRadius property of the layer. We set this to a fraction of the card width. We add some little effect by setting the shadowRadius, shadowOpacity and shadowOffset.

Now let get back to cell interface. Grab a label and place inside card view. Pin it 8 to the left and right and 4 to the top. With the label selected, go over the Utility Area, select Attributes inspector. Let’s change the font. Click on the bold “T” to the extreme end of font field.

Next we add two more label. One for year of release and one for summary.
Year of release label: Pin 4 to the image view, 8 both left and right of card view. Change font to Avenir, style: Book, size: 15.
Summary label: Apply same font for year of release. Pin 4 to Year of release label, 8 left and right. Pin to the bottom too.
With the summary label selected, go over to Size Inspector. scroll down to the constraints. Lets edit the bottom constraint. Click on edit on the "Bottom Space to:SuperView”.

<img src="/content/images/2016/10/Screenshot-2016-10-08-17.02.47.png" alt="Alt Text" text-align:"center" style="width:300px;height:300px;">
Change Constant to >=, and the value to 8.
This will allow card view to make space enough for the summary label content.

With the label still selected, go back to attribute inspector. Right below Alignment is Lines. UILabel has a property called “numberOfLines” which specifies the maximum number of lines to use for rendering text. We will set this to 0 since we don’t know the actual number of lines we will need for the summary text.
At this point, our cell should look like this

Lets go ahead and wire the elements to the class.
Click on Assistant editor. Make sure the MoviesTableViewCell file is the one displayed in the assistant editor. While holding down control on keyboard, click and drag from the first label to MoviesTableViewCell class. Call the outlet titleLabel. Do the same for the imageView (movieImageView), year of release label (releaseDateLabel) and summary label (summaryLabel).

Finally we can concentrate on code now. Go over to ListViewController. Our table will be displaying a list of movies so we can go ahead and delete the “names” array. We create an array called movies. This will be an array of dictionaries. Our table will display a list of two movies. Since we already have a picture of Messi and Ronaldo, let create a movie for the two stars.

let movies = [
["title":"CR7", "image":"ronaldo", "year":"2012", "summary":"Cristiano Ronaldo dos Santos Aveiro, ComM, GOIH (Portuguese pronunciation: [kɾiʃ'tjɐnu ʁuˈnaɫdu], born 5 February 1985) is a Portuguese professional footballer who plays for Spanish club Real Madrid and the Portugal national team. He is a forward and serves as captain for Portugal. In 2008, he won his first Ballon d'Or and FIFA World Player of the Year awards. He then won the FIFA Ballon d'Or in 2013 and 2014. In 2015, Ronaldo scored his 500th senior career goal for club and country."],
["title":"The Leo", "image":"messi", "year”:"1999", "summary":"Lionel Andrés \"Leo\" Messi (Spanish pronunciation: [ljoˈnel anˈdɾes ˈmesi] ( listen); born 24 June 1987) is an Argentine professional footballer who plays as a forward for Spanish club FC Barcelona and the Argentina national team. Often considered the best player in the world and rated by many in the sport as the greatest of all time, Messi is the only football player in history to win five FIFA Ballons d'Or, four of which he won consecutively, and the first player to win three European Golden Shoes.[note 2] With Barcelona he has won eight La Liga titles and four UEFA Champions League titles, as well as four Copas del Rey. Both a prolific goalscorer and a creative playmaker, Messi holds the records for most goals scored in La Liga, a La Liga season (50), a football season (82), and a calendar year (91), as well as those for most assists made in La Liga and the Copa América. He has scored over 500 senior career goals for club and country."]
]

For summary I just grabbed something from the Wikipedia.

The table view has no knowledge of the existence of our custom cell, we have to register the cell. We will do this in viewDidLoad. But first, go to main storyboard and create an outlet for tableView. Call it tableView.

We create the cell and forcefully cast it to type MoviesTableViewCell. This is fine since we are sure it is of that type. The movies array is an array of dictionaries. We can grab each dictionary/movie using indexPath.row each time cellForRowAt indexPath is called. This we did with the line of code

let movie = movies[indexPath.row]

We then set the cell contents by accessing the values of the dictionary using the keys. Finally we returned the cell.
Run the project now.

The first method asks the delegate for the estimated height of a row in a specified location. While the second asks the delegate for the height to use for a row in a specified location.
If we have a fixed size for our cell, we could return that size. Say we want our cell to be height 250, then we return 250. In this case we don't have a fixed size. We want the cell to take the size of it's content. UITableViewAutomaticDimension requests that UITableView use the default value for a given dimension.
Before we run the project, go main storyboard, and set the delegate for the table view. Same way we set the datasource in part one.