• Skip to main content
  • Skip to primary sidebar

Ravi Shankar

Tweaking Apps

  • About
  • Portfolio
  • Privacy Policy

Swift

Add annotations and Polyline to MapView in Swift

July 6, 2015 By Ravi Shankar 19 Comments

In this article, we will see the instructions for adding annotation to MapView, Draw Polylines and Zoom to a region in Swift. Let us see this by adding stations to a Map for Chennai subrban trains and connect these stations using Map Overlay.

Project Setup

 

Create a new project by selecting Single View Application as the project template.

Enter the required information such project name, organization identifier etc.. as shown in the below screenshot. Then save the project in your desired location.

Add MapKit View

 

Navigate to Project navigator and select Main.storyboard file.

We are not using the Auto Layout for this demo, hence disable Use Auto Layout and disable size classes using the options available as part of the File Inspector

Drag and drop MapKit View from object library to the View Controller and make sure to resize the MapView to full view. Add IBOutlet in the ViewController for the MapKit and connect it to the MapKit View in the Interface builder. Also add import MapKit to include MapKit framework for your project.

[code language=”swift”]@IBOutlet weak var mapView: MKMapView!
[/code]

Now if you do a build and run the project in iPhone 6 simulator, you should see the following on simulator.

Zoom to specified region

 

Add the follwing piece of code in ViewController.swift file. And call this function from ViewController’s viewDidLoad function.

[code language=”swift”]//MARK:- Zoom to region

func zoomToRegion() {

let location = CLLocationCoordinate2D(latitude: 13.03297, longitude: 80.26518)

let region = MKCoordinateRegionMakeWithDistance(location, 5000.0, 7000.0)

mapView.setRegion(region, animated: true)
}
[/code]

 

CLLocationCoordinate2D is created by specifying latitude and longitude of the zoom location. Then using MKCoordinateRegionMakeWithDistance set the distance around the speicifed location. Then this region will set as the region for the MapView. Build and run the project should show Map zooming to the speicifed region as shown below.

 

Add plist file to project.

 

All the station details such as title, latitude and longitude are stored in a plist file. You can download the plist from gitHub. Right click on the Project folder (Project navigator) and select “Add Files to <Project name>” option. And select Copy items if needed option while adding the file.

The sample data structure of the plist file is shown below

 

Add place holder class Station

Create a new model class for holding the station data. This class should conform to MKAnnotation and NSObject protocol.

[code language=”swift”]import MapKit

class Station: NSObject, MKAnnotation {
var title: String?
var subtitle: String?
var latitude: Double
var longitude:Double

var coordinate: CLLocationCoordinate2D {
return CLLocationCoordinate2D(latitude: latitude, longitude: longitude)
}

init(latitude: Double, longitude: Double) {
self.latitude = latitude
self.longitude = longitude
}
}[/code]

 

This class has properties for title, subtitle, latitude, longitude and coordinate. Any mappoint should have coordinate for the adding it to the map. This property is mandatory and it is defined in MKAnnotation protocol. The initializer in the class accepts the latitide and longitude details as they are needed for creating the coordinates.

Add annotation to MapKit

We need to iterate through the plist file and create annotation for each stations. Add the following function to ViewController.swift which does the same.

[code language=”swift”]//MARK:- Annotations

func getMapAnnotations() -&gt; [Station] {
var annotations:Array = [Station]()

//load plist file
var stations: NSArray?
if let path = NSBundle.mainBundle().pathForResource("stations", ofType: "plist") {
stations = NSArray(contentsOfFile: path)
}

//iterate and create annotations
if let items = stations {
for item in items {
let lat = item.valueForKey("lat") as! Double
let long = item.valueForKey("long")as! Double
let annotation = Station(latitude: lat, longitude: long)
annotation.title = item.valueForKey("title") as? String
annotations.append(annotation)
}
}

return annotations
}
[/code]

Add the following piece of code in viewDidLoad function.

[code language=”swift”]let annotations = getMapAnnotations()
// Add mappoints to Map
mapView.addAnnotations(annotations)[/code]

Now if you build and run the project, you should see the map with annotations. And on tapping any mappoint should display the title for that station.

Add Polyline to MapView

In order add Polyline overlay to map, we need to implement function defined in MKMapViewDelegate protocol. Add MkMapViewDelegate in the class declaration after UIViewController.

[code language=”swift”]class ViewController: UIViewController, MKMapViewDelegate {[/code]

Then make sure to set the delegate property of the mapview to self so that the ViewController can implement and handle the MKMapViewDelegate functions. Add the following piece of code in viewDidLoad function after the annotations.

[code language=”swift”]
mapView.delegate = self
// Connect all the mappoints using Poly line.

var points: [CLLocationCoordinate2D] = [CLLocationCoordinate2D]()

for annotation in annotations {
points.append(annotation.coordinate)
}
var polyline = MKPolyline(coordinates: &amp;points, count: points.count)
mapView.addOverlay(polyline)
[/code]

create a array of CLLocationCoordinate2D by iterating through annotations. Then create an instance of MKPolyline class by passing array of CLLocationCoordinate2D and count of coordinates. Finally add this polyline to mapView overlay.

Implement the rendererForOverlay MKMapViewDelegate function and return an insatnce of MKPolylineRenderer class

[code language=”swift”]
//MARK:- MapViewDelegate methods

func mapView(mapView: MKMapView!, rendererForOverlay overlay: MKOverlay!) -&gt; MKOverlayRenderer! {
if overlay is MKPolyline {
var polylineRenderer = MKPolylineRenderer(overlay: overlay)
polylineRenderer.strokeColor = UIColor.blueColor()
polylineRenderer.lineWidth = 5
return polylineRenderer
}

return nil
}
[/code]

 

Now build and run the app should display the Polyline on the Map.

Download the source code from here

Filed Under: Programming, Swift, Xcode

TableView Demo in Swift

June 10, 2015 By Ravi Shankar 1 Comment

In this tutorial, we will see some of the common UITableView operations such as Adding, Updating, Deleting and Moving records using Swift.

Let us start with a TableView placed over a ViewController instead of using UITableViewController. By this way you will learn lot more about the functionality of UITableView. Add a new file and select Cocoa Touch Class as a template for the new file.

In “Choose options for your new file” screen, enter the class name as TableViewDemoController with subclass as UIViewController. Then save the new file under your preferred location.

User Interface

Navigate to Main.stotyboard then drag and drop a ViewController from Object Libray to Storyboard. Select the ViewController and click Show Identity Inspection and enter the class name as “TableViewDemoController”

Drag and drop Table View from object library to the View Controlller and make sure Table View is aligned properly. Now place a Table View Cell from object library on top of the TableView.

Set the identifier for Prototype cell to “CellIdentifier” using Show Identity Inspector.

Now select the tableview in the Document Outline pane and click Connection Inspector under Utilies pane. Connect the dataSource and delegate Outlets to the TableViewDemoController (yellow color circle on top View Controller)

Display Data

In this demo, we will be seeing how to display list of Socia Media icons. Here are the steps to load those icons in TableView.

First create a Struct that would act as a place holder for holding the name and image file name. Right click on the Project, select New File. In template screen, choose Swift file and provide name as SocialMedia and save the file.

Edit SocialMedia.swift and add the following code snippet. Apart name and imageName property, this also has computed property that returms UIImage based upon the image file name.

[code language=”swift”]import UIKit

struct SocialMedia {

var name:String
var imageName:String
var image: UIImage {
get {
return UIImage(named: imageName)!
}
}
}[/code]

Now Drag and drop social icon images from folder to Xcode project (download images from gitHub repoistory). Navigate TableViewDemoController.swift and add the following code snippet.

[code language=”swift”]var data:[SocialMedia] = [SocialMedia]()

//MARK:- Populate data

func loadData() -> [SocialMedia] {

data.append(SocialMedia(name:"Evernote",imageName:"evernote"))
data.append(SocialMedia(name:"Facebook",imageName:"facebook"))
data.append(SocialMedia(name:"GitHub",imageName:"github"))
data.append(SocialMedia(name:"Google",imageName:"google"))
data.append(SocialMedia(name:"LinkedIn",imageName:"linkedin"))
data.append(SocialMedia(name:"Paypal",imageName:"paypal"))
data.append(SocialMedia(name:"Pinterest",imageName:"pinterest"))
data.append(SocialMedia(name:"Twitter",imageName:"twitter"))
data.append(SocialMedia(name:"Vimeo",imageName:"vimeo"))
data.append(SocialMedia(name:"youtube",imageName:"YouTube"))

return data
}
[/code]

We have declared an array called data which will hold all the SocialMedia icon related information. The function loadData is used for adding all the social media images. Now call this function in the viewDidLoad method.

[code language=”swift”]override func viewDidLoad() {
super.viewDidLoad()
// call loaddata
loadData()
}
[/code]

In order display data, ViewController needs to conform UITableViewDataSource protocol. Add UITableViewDataSource
to the class declaration next to UIViewController.

[code language=”swift”]class TableViewDemoController: UIViewController, UITableViewDataSource {
[/code]

Then implement the following methods in TableViewDemoController class, these required methods when a class conforms to UITableViewDataSource protocol.

[code language=”swift”]//MARK:- UITableViewDataSource methods

func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return data.count
}

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

var cell = tableView.dequeueReusableCellWithIdentifier("CellIdentifier") as! UITableViewCell

let mediaIcon = data[indexPath.row] as SocialMedia

cell.textLabel?.text = mediaIcon.name
cell.imageView?.image = mediaIcon.image

return cell
}
[/code]

Finally we need to create IBOutlet for tableView and connect with tableView control in Storyboard.

[code language=”swift”]@IBOutlet var tableView: UITableView!
[/code]

Now you should be able to build and run the project. This should show list all Social Media icons as shown below

Customize UITableView

In order the customize the tableview, the TableViewDemoController class needs to conform to UITableViewDelegate protocol. Let us say you want to increase the height of tableview rows. Then implement the function heightForRowAtIndexPath to return the height for each row.

[code language=”swift”]func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return 60.0
}
[/code]

Build and run the project should show the difference in height.

Add and Update row

Navigate to Main.storyboard and add a new View Controller to Interface builder. This View Controller will be used for capturing name of the icon when adding a new row.

This View Controller has a text field to accept the name of the Social Media icon, Done button to save the entered informatiom and Cancel button to cancel the operation. Make sure to create Unwind segue for Done and Cancel button by Control drag and drop each button to Exit icon on the View Controller. Also provide the identifer for the Unwind segue as addAction and cancelAction.

Navigate to TableViewDemoController and add Bar Button Item to the left hand side. Set the Identifier of Bar Button Item to Add.

Now Control + Drag from the Add button to DetailViewController and select Segue as Push with identifier as “addAction”. Similarly to allow users to edit the existing row, Control + Drag TableView prototype cell to DetailViewController and set identifier for the Push segue as “editAction”.

Add a new Cocoa Touch Class file to the existing project with Sub class as UIViewController and name of the file as DetailViewController. Set this file as the class name in the Identity Inspector of DetailViewController in Interface builder.

Update the DetailViewController.swift and replace the existing code with the following lines of code.

[code language=”swift”]import UIKit

class DetailViewController: UIViewController {

var socialMedia: SocialMedia?
var index:Int?

@IBOutlet var textFeild:UITextField?

override func viewDidLoad() {
super.viewDidLoad()

if let name = socialMedia?.name {
textFeild?.text = name
}
}

// MARK:- PrepareForSegue
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
let name = textFeild?.text
if segue.identifier == "addAction" {
if var socialMedia = socialMedia {
self.socialMedia?.name = name!
} else {
socialMedia = SocialMedia(name:name!,imageName:"unknown")
}
}
}

override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}

}[/code]

 

We have declared two variables socialMedia and index which will be populated when user taps an esitsing row in the TableView. Also you should find a IBOutlet for UITextField, make sure to connect this with TextField in the Interface Builder.

In the viewDidLoad function, if the user is editing an existing row then the textfield is updated with that value. The prepareForSegue method is called when the user taps Done or Cancel button. And based on the action, a new social media icon is added or an existing row is updated.

Navigate back to TableViewDemoController and implement the following function that will be called on cancel or done operation in DetailViewController.

[code language=”swift”]//MARK:- Cancel and Done

@IBAction func cancel(segue:UIStoryboardSegue) {
// do nothing
}

@IBAction func done(segue:UIStoryboardSegue) {

let detailViewController = segue.sourceViewController as! DetailViewController
let socialMedia = detailViewController.socialMedia
if let selectedIndex = detailViewController.index {
data[selectedIndex] = socialMedia!
} else {
data.append(socialMedia!)
}
tableView.reloadData()
}[/code]

 

Delete and Move row

Delete operation can be added by implementing the following function in TableViewDemoController.

[code language=”swift”]func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
switch editingStyle {
case .Delete:
// remove the deleted item from the model
data.removeAtIndex(indexPath.row)
// remove the deleted item from the `UITableView`
self.tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
default:
return
}
}[/code]

This would allow users to swipe and delete a row in TableView. The function checks whether the editing style is Delete, then the row is removed from the array as well from the TableView display.

In order to allow users to move the rows, the tableView editing property needs to be set to true. Add another Bar Button Item, this time to the right of TableViewDemoController and provide the caption as Edit. Then connect this button with the following IBAction function.

[code language=”swift”]//MARK:- Editing toggle

@IBAction func startEditing(sender: UIBarButtonItem) {
tableView.editing = !tableView.editing
}
[/code]

This button acts as a toggle switch to enable or disable tableview edit operation. Now add the following function required for Move operation.

[code language=”swift”]//MARK:- TableViewCell Move row methods
func tableView(tableView: UITableView, canMoveRowAtIndexPath indexPath: NSIndexPath) -> Bool {
return true
}

func tableView(tableView: UITableView,
moveRowAtIndexPath sourceIndexPath: NSIndexPath,
toIndexPath destinationIndexPath: NSIndexPath) {
let val = data.removeAtIndex(sourceIndexPath.row)
data.insert(val, atIndex: destinationIndexPath.row)
}
[/code]

Function canMoveRowAtIndexPath needs to return true and in moveRowAtIndexPath function, the tableView row data gets removed from the original index and inserted in to the new position.

Now the user can tap and hold the move option then drag and drop it to the desired position. When the tableview editing is set to true, it also provides delete button apart from the move operation.

Download the source code from here.

Social Media icons credit to Sebastiano Guerriero

Filed Under: Swift, UITableView Tagged With: Swift, UITableView, Xcode

Swift Interview Questions

March 7, 2015 By Ravi Shankar Leave a Comment

Listed below are some of topics to be familiar before attending an iOS//Swift interviews. These are very trivial questions but in future this space will updated with more scenario based questions

  • What are the different app states?
  • What is JSON?
  • What do you mean by REST?
  • Difference between class and struct?
  • What are Optionals?
  • Difference between Optional Chaining and Optional Binding?
  • why do we have to use UICollectionViewFlowLayout?
  • Difference between frame and bounds?
  • What is NSCoder class used for? 
  • What is NSOperationQueue and when should we use it?
  • What are extensions? Explain the difference between extension and subclassing?
  • Difference between delegates and NSNotifications?
  • What are protocols in Swift?
  • What is interpolation?
  • Explain type inference in Swift?
  • Difference between Auto Layout and Adaptive Layout?
  • Is possible to use an Objective-C framework in Swift? 
  • Explain the different life cycle of UIViewController?
  • Difference between xib’s and Storyboards.
  • Explain MVC?
  • What is MVVM?
  • what is an app bundle?
  • Write a sample code for Singleton design pattern?
  • What is difference between Unit tests and UI Test in Xcode?
  • Can you make updates to UI from a background thread? 
  • Difference between let and var keywords in Swift?
  • What are generics? Can you write generics example code?
  • Difference between designated and convenience initialiser?

Filed Under: Interview Questions, ios, Swift

  1. Pages:
  2. «
  3. 1
  4. 2
« Previous Page

Primary Sidebar

TwitterLinkedin

Recent Posts

  • How to know the size of the folders in iCloud
  • Errors were encountered while preparing your device
  • We have blocked all requests from this device – Firebase Phone Authentication
  • iPhone is not available error message in Xcode
  • Clear CocoaPods cache, re-download and reinstall all pods

Copyright 2021 © rshankar.com