• Skip to main content
  • Skip to primary sidebar

Ravi Shankar

Tweaking Apps

  • Swift
  • Tech Tips

Xcode

Attribute Unavailable: Estimated section warning before iOS 11.0

November 12, 2021 By Ravi Shankar

Xcode 13 (iOS 15) displays the following warning message for project having minimum deployment as iOS 10.

  • Attribute Unavailable: Estimated section header height before iOS 11.0
  • Attribute Unavailable: Estimated section footer height before iOS 11.0

This warning gets displayed for new UITableViewController added to the Storyboard file. You can get rid of the warning messages by adding 0 to Estimate Header and Estimate footer for Sections under Size Inspector

Filed Under: ios, Swift, Xcode Tagged With: iOS, Xcode Warning

Xcode – framework not found FIRAnalyticsConnector

June 22, 2021 By Ravi Shankar

Tried updating all pods in Xcode projects using pod update. Noticed the following messages in the log.

Removing FirebaseInstanceID
Generating Pods project
Integrating client project

After doing Xcode build, noticed the following error.

Framework not found FIRAnalyticsConnector

Looks like firebase pod has been updated and to remove the above error, navigate to Build Settings and search for “FIRAnalyticsConnector”

Open the “Other Linker Flags” setting and remove FIRAnalyticsConnector

Next received “Framework not found FirebaseInstanceID” as well. Repeat the above steps and remove FirebaseInstanceID from Other Linker flags settings. Also make sure to remove from Framework Search Paths (Debug & Release) as well.

Filed Under: Swift, Xcode

Errors were encountered while preparing your device

February 14, 2021 By Ravi Shankar

One of the common error that occurs in Xcode is “Error were encounted while preparing your device for development. Please check the Devices and Simulators Window.” I have noticed this error after Mac OS update or Xcode app update Trying the following

  1. Restart your device,
  2. Close Xcode and try re-running the Xcode project.

Sometimes after restarting the device you might see the following “iPhone is Busy: Making iPhone ready for development”. Give some time for the device after a restart, this might fix the problem.

If you have come across these during any other scenarios, please share them in the comments section. Thank you.

Filed Under: iPhone, Mac, Xcode Tagged With: Mac, Mac OS

iPhone is not available error message in Xcode

September 8, 2020 By Ravi Shankar

If you are receiving an error “iPhone is not available” when connecting Xcode with iPhone then check iOS version on your iPhone. Make sure it is compatible with the Xcode version.

iPhone is not available

The conflict in versions can be found under the Xcode – Window – Devices and Simulators. In my case the following error was mentioned.

Errors

“The current device configuration is unsupported. This iPhone 7 (Model 1660, 1778, 1779, 1780) is running iOS 13.6.1 (17G80), which is not supported by Xcode 11.7”

The fix was to upgrade iOS on my iPhone to iOS 13.7.

Filed Under: Xcode Tagged With: iphone

Tab Bar Controller with WebView

April 9, 2020 By Ravi Shankar

In this article, we will see step by step instruction on working of Tab Bar Controller, UIWebView and Activity Indicator by loading couple of web pages using UIWebView in two different Tabs.

Tab Bar Controller

Tab Bar Controller is used for organising list of View Controllers by having seperate tabs for each View Controller. Check out the Apple Documentation for more information.

UIWebView

When you want to allow users to browse website then you can use UIWebView to load those pages. These WebViews needs to be placed inside a container such as UIViewController. Check out Apple Documentation for more information on UIWebView.

Project Setup

Create a new project by selecting Single View Application as project template. You can also choose Tabbed Application but in this demo we will see how to embed a ViewController inside a Tab Bar Controller.

Enter the project details and select the language as Swift.

Embed View Controller inside Tab Bar Controller

Navigate to Main.storyboard in Project Navigator and select View Controller. Now to embed this View Controller inside a Tab bar Controller, click Editor -> Embed In -> Tab Bar Controller

The Interface builder should now display View Controller and Tab Bar Controller as shown below.

Add Second View Controller

Now let us see how to add another tab by setting relationship between second View Controller and Tab Bar Controller. Drag and drop UIViewController from Object library to Interface builder.

Control + Drag from Tab Bar Controller to UIViewController and select view controllers under Relationship Segue. This should add second tab bar item pointing the second View Controller.

Add UIWebView and Activity Indicator View

We are not using Auto Layout or Size Classes for this demo, so disable these features using the option available under File Inspector.

Drag and drop UIWebView from object libary to both the View Controllers. Make sure it is aligned centrally to View Controller and covers the entire View Controller area. Similarly add Activity Indicator View from object libary to top of UIWebView and align to the Centre both vertically and horizontally.

Edit Tab Bar Items

The Tab Bar Controller display two tab bar items which are linked to each View Controller. Add required images for each Tab bar items to the Images.xcassets (Download the images from GitHub project).
To provide a name and image for Tab Bar items, select the item in the corresponding View Controller and enter the details in Attributes Inspector. For the first View Controller, the name and image are set as shown below.

repeat the same for the second View Controller as well.

Link class with UIViewController

The project comes with a default ViewController.swift file which is mapped with the first View Controller. Let us give a proper name to this controller. Unfortnately Xcode Refactor option still does not work for Swift (Xcode version 6.4). Manually rename the file to WorldViewController.swift and also make the corresponding name change in Class.

class WorldController: UIViewController {

Add a second view controller class by right clicking the project, select New File option.

In the choose template screen, select Cocoa Touch Class and provide name as SportsViewController making it a subclass of UIViewController.

Create IBOutelts for UIWebView and Activity Indicator View

Using Assistant Editor, navigate to Main.storyboard in the second window. In the Identity Inspector, set the class name for both ViewControllers to WorldViewController and SportsViewController.

Drag and drop UIWebView from WorldViewController (Interface builder) to WorldViewController.swift to create IBOutlet. Do the same for Activity Indicator View as well.

@IBOutlet weak var webView: UIWebView!

@IBOutlet weak var activityIndicator: UIActivityIndicatorView!

Repeat the same exercise for SportsViewController and create corresponding IBOutlets.

Code Implementation

Navigate to WorldViewController.swift file and add the following code snippet in ViewDidLoad function.

let url = NSURL(string: "http://edition.cnn.com/world")
let urlRequest = NSURLRequest(URL: url!)
webView.loadRequest(urlRequest)

activityIndicator.startAnimating()
activityIndicator.hidesWhenStopped = true

The first three lines of the code create a NSURLRequest and the object is passed to UIWebView loadRequest function. The last two lines starts the Activity Indicator View and sets the property to hide the indicator when it is stopped animating.

We need to tell the Activity Indicator when the page has finished loading. This can be done by implementing UIWebViewDelegate’s webViewDidFinishLoad function.

Add the following piece of code to make the View Controller as a delegate for webView.

class WorldController: UIViewController, UIWebViewDelegate {

and in the viewDidLoad function add webView.delegate = self. This would ensure that the View Contorller can handle any WebView delegate related calls.

Now implement the webViewDidFinishLoad function and stop the animation of Activity Indicator View when the webview has finished loading the page.

//MARK:- WebView Delegate method

    func webViewDidFinishLoad(webView: UIWebView) {
        activityIndicator.stopAnimating()
    }

Repeat the above code implementation for SportsViewController excepy by chaning the URL string.

class SportsViewController: UIViewController, UIWebViewDelegate {
    @IBOutlet var webView: UIWebView!
    @IBOutlet var activityIndicator: UIActivityIndicatorView!

    override func viewDidLoad() {
        super.viewDidLoad()

        let url = NSURL(string: "http://edition.cnn.com/sport")
        let urlRequest = NSURLRequest(URL: url!)
        webView.loadRequest(urlRequest)

        activityIndicator.startAnimating()
        activityIndicator.hidesWhenStopped = true

        webView.delegate = self
    }

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

    //MARK:- UIWebView Delegate methods
    func webViewDidFinishLoad(webView: UIWebView) {
        activityIndicator.stopAnimating()
    }

}

When you finally build and run the project, you should see the follwing on iOS simulator.

Download the source code from here

Filed Under: Apple, ios, Programming, Xcode

CoreData tutorial in Swift 5 using NSFetchedResultsController

December 25, 2019 By Ravi Shankar 38 Comments

Let us see an example TaskManager app using CoreData written in Swift Programming language. This app provides the following functionality

  • Allow users to enter new task
  • Update existing task
  • delete task

TaskManager using CoreData201407121030.jpg

You can download source code for this project from Github. If you are familiar with user interface then move on to the Core Data implementation in Swift section

Create a new File -> New -> Project and select template Single View Application

201407121032.jpg

Enter Product Name, Language as Swift and select “Use Core Data” for the new Project.

201407121037.jpg

User Interface Implementation

 

Add new TableViewController for managing tasks

 

Delete ViewController.swift and Add new view controller which will be used for displaying the list of tasks.

201407121059.jpg

Right click on the Project and select New File

201407121101.jpg

Choose the template as Cocoa Touch under iOS -> Source

201407121103.jpg

Enter name of the file as TaskManagerViewController with Subclass as UITableViewController and Language as Swift.

201407121104.jpg

Add new UITableViewController to the Storyboard

 

Navigate to Main.storyboard, delete the ViewController and add new TableViewController to the Storyboard

201407121108.jpg

Embed this TableViewController inside a navigation controller. You can do this by clicking Editor menu -> Embed In -> Navigation Controller.

201407121110.jpg

Navigate to Storyboard file and select Table View Controller. Click Identity Inspector and set the Class to the TaskManagerViewController.

Add button to the navigation bar

 

Users can navigate to new task screen by tapping the button on the TaskManager. Drag and drop the button bar item to the navigation bar.

201407121116.jpg

In the attributes inspector, set the identifier for button bar item as Add. Also enter title as “Task Manager” in the navigation bar.

Add View Controller for entering task detail

 

Now to enter task detail, let us add new View Controller. From the Objects library, drag and drop View Controller on to storyboard. Then drag and drop a navigation item to this View Controller. Add a Done bar button item for saving the changes, Cancel bar button item for dismissing the screen. Also provide a title for the screen as Task Detail.

201407121138.jpg

Then add a textfield to the View Controller to enter details about the task.

201407121540.jpg

Now to connect the Task Manager screen to Task Detail screen, select the Add button in Task Manager screen, hold the control button and make a connection to the Task Detail screen. Select type of Action Segue as Show.

201407121125.jpg201407121127.jpg

Select each View Controller and Click on the Resolve Auto Layout Issues option and pick Reset to Suggested Constraints. This would ensure that the controls alignment and display remains same in different screen sizes.

 

201407121557.jpg

Add View Controller Class

Right click on the Project, select New File from menu list.

201407130919.jpg

Select Cocoa Touch Class as template.

201407130920.jpg

Enter the Class name as TaskDetailViewController, Subclass of UIViewController and Language as Swift.

201407130921.jpg

Navigate to Storyboard file and select Task Detail View Controller. Click Identity Inspector and set the Class to the TaskDetailViiewController.

201407141329.jpg

Now let us add the function required for dismissing the View Controller. This gets called when user taps done and cancel buttons. Navigate to TaskDetailViewController.swift file and add the following functions.

    
   @IBAction func done(sender: AnyObject) {
        if task != nil {
            editTask()
        } else {
            createTask()
        }
        dismissViewController()
    }
    
    @IBAction func cancel(sender: AnyObject) {
         dismissViewController()
    }
    
    // MARK:- Dismiss ViewControllers
    
    func dismissViewController() {
        navigationController?.popViewController(animated: true)
    }

 

Connect the IBActions with the corresponding done and cancel buttons

201407130930.jpg

 

Try to compile and run the app on the Simulator. You should see the following Task Manager screen and tapping + sign should display the Task Detail screen with TextField, Cancel and Done button.

201407130933.jpg201407130935.jpg

 

When you tap the Cancel or Done button should take you to the Task Manager screen.

Create IBOutlet element for UITextField Element

Add the following piece of code after the Class TaskDetailViewController: UIViewController

@IBOutlet var txtDesc: UITextField!

Now use the connection inspector to connect the IBOutlet variable to the textfield on the User Interface.

Core Data Implementation

 

Click Show Project Navigator and select CoreData model file (ending with extension .xcdatamodelid)

201407121042.jpg

Click Add Entity option available at the bottom of Xcode Editor window.

201407121045.jpg

Then enter the name of the entity as Tasks.

201407121047.jpg

Click Add Attribute then enter name as desc and choose the type as String. This attribute will be used for storing the task detail information.

201407121049.jpg

Now to generate the CoreData mapping class, click Editor and select Create NSManagedObject Subclass.

201407121051.jpg

Select the data models and click Next

201407121052.jpg

Then select entities and in this example it is Tasks

201407121053.jpg

Make sure to select Language for NSManagedObject class as Swift. Click Create to the create new class.

201407121055.jpg

Click Yes to to configure an Objective-C birding header for the Swift class.

201407121056.jpg

This should create a new class called Tasks.swfit with variable for corresponding attribute defined in Entities

Write code to save new task details

Add the following line at the top of TaskDetailViewController class

  let managedObjectContext = (UIApplication.shared.delegate as! AppDelegate).managedObjectContext

The above line defines a variable to store the ManagedObjectContext. In order to save the task information entered in the UITextField, add the following code to TaskDetailViewController.swift. Then call this function in the @IBAction done.

   func createTask() {
        let entityDescripition = NSEntityDescription.entity(forEntityName: "Tasks", in: managedObjectContext)
        let task = Tasks(entity: entityDescripition!, insertInto: managedObjectContext)
        task.desc = txtDesc.text!
        do {
            try managedObjectContext.save()
        } catch _ {
        }
    }
@IBAction func done(sender: AnyObject) {
	createTask()
	dismissViewController()
}

 

The createTask function uses the Tasks Entity class and ManagedObjectContext class to save the information entered in the text field in to SQLite using CoreData.

Now if you try to run this app in Xcode simulator, you should be able to enter the details in textfield and save the task. But there is no way to see the saved tasks.

Write code to retrieve information from SQLite using NSFetchedResultsController

We will be using NSFetchedResultsController to retrieve and manage information returned from Core Data. Write the following code after the class declaration of TaskManagerViewController class

 let managedObjectContext = (UIApplication.shared.delegate as! AppDelegate).managedObjectContext
    
var fetchedResultController: NSFetchedResultsController = NSFetchedResultsController<NSFetchRequestResult>()
    

201407141923.jpg

 

You might see the above error message “Use of undeclared type ’NSFetchedResultsContoller”. This can be fixed by importing CoreData module and making your class a delegate of NSFetchedResultsControllerDelegate.

import CoreData

class TaskManagerViewController: UITableViewController, NSFetchedResultsControllerDelegate {

Then add the following function to populate fetchedResultController.

  
    func getFetchedResultController() -> NSFetchedResultsController<NSFetchRequestResult> {
        fetchedResultController = NSFetchedResultsController(fetchRequest: taskFetchRequest(),  managedObjectContext: managedObjectContext, sectionNameKeyPath: nil, cacheName: nil)
        return fetchedResultController
    }
      

 

Update the ViewDidLoad method of TableViewController to populate fetchedResultController variable and set the delegate to self and call the function to retrieve the results.

override func viewDidLoad() {
        super.viewDidLoad()

       fetchedResultController = getFetchedResultController()
        fetchedResultController.delegate = self
        do {
            try fetchedResultController.performFetch()
        } catch _ {
        }
    }

Implement the TableView related functions to display the data

Navigate to Main.storyoard then to TaskManagerViewController and set Identifier for Prototype Cells as “Cell”

201407142004.jpg

 

Add the following functions required for population of rows in tableView and to refresh the tableView when content is changed.

 

And for refreshing the tableview content add the following piece of code snippet.

  func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {          tableView.reloadData()
    }

Swift uses namespaces for classes, so the downcast of NSManagedObject class to Tasks class will work only when you append the module name with the class for Entity

  let task = fetchedResultController.object(at: indexPath as IndexPath) as! Tasks

Navigate to TaskManager.xcdatamodeld, select Tasks under Entities and using the Data Model Inspector append Module name i.e TaskManager with the class.

201407142038.jpg

 

 

Now you should be able to see the data added via TaskDetailScreen in the TaskManager Screen.

201407142059.jpg

Implementation of deleting rows from tableView and CoreData entity

 

Copy and paste the following code to provide the users with the option to delete the rows.

 override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
        let managedObject:NSManagedObject = fetchedResultController.object(at: indexPath as IndexPath) as! NSManagedObject
        managedObjectContext.delete(managedObject)
        do {
            try managedObjectContext.save()
        } catch _ {
        }
    }

201407142116.jpg

Implementation of editing task details

Now let us see how to edit a task in the TaskManager screen. We will re-use the same TaskDetail screen for editing the task information. First let create segue from UITableViewCell to TaskDetailViewController. You can do this by holding the Control key and drag and drop the connection to TaskDetailViewController.

201407142127.jpg

 

Make sure to set the Segue identifier as edit using Attributes Inspector

201407142128.jpg

 

Add the following piece of code in TaskManagerViewController to populate the task detail for the edited row.

      override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if segue.identifier == "edit" {
            let cell = sender as! UITableViewCell
            let indexPath = tableView.indexPath(for: cell)
            let taskController:TaskDetailViewController = segue.destination as! TaskDetailViewController
            let task:Tasks = fetchedResultController.object(at: indexPath!) as! Tasks
            taskController.task = task
        }
    }
    

 

Navigate to TaskDetailViewController and variable which used to pass the task details across the ViewControllers

var task: Task? = nil

In viewDidLoad fund, populate the textField with the task details for edit operation i.e task is not nil

 override func viewDidLoad() {
        super.viewDidLoad()
     if task != nil {
            txtDesc.text = task?.desc
        }
    }

 

Then add a new function to save the edited task. Also modify the done function to handle create and edit task functionality

func editTask() {
       task?.desc = txtDesc.text!
        do {
            try managedObjectContext.save()
        } catch _ {
        }
    }
@IBAction func done(sender: AnyObject) {
        if task != nil {
            editTask()
        } else {
            createTask()
        }
        dismissViewController()
    }

 

Now when you run the app in Xcode simulator, you should be able to edit the task.

The final piece of code left is to add background colour to the navigation bar for both the controllers. Click AppDelegate.swift file and add the following function. Then call this function from the didFinishLaunchingWithOptions.

    func setupAppearance() {
        let navigationBarAppearance = UINavigationBar.appearance()
        navigationBarAppearance.barTintColor = UIColor(red: 51.0/255.0, green: 104.0/255.0, blue: 121.0/255.0, alpha: 1.0)
        navigationBarAppearance.tintColor = UIColor.white
        navigationBarAppearance.titleTextAttributes = [NSAttributedString.Key.foregroundColor:UIColor.white]
    }

 

Running the app on the iOS simulator should change the appearance for the navigation bar.

201407142233.jpg

 

Hope you found this beginner tutorial useful. Please use the comments section to share your thoughts and suggestion

Download the source code for this tutorial from GitHub

Filed Under: Develop, ios, iPhone, Programming, Swift, Xcode Tagged With: CoreData, delegation, NSFetchedResultContoller, Swift, Tutorials, UITableView, User Interface, Xcode

Storyboard, Scene and Segue

November 22, 2019 By Ravi Shankar Leave a Comment

Storyboard in iOS is helps you to design the user interface of your App. A storyboard can contain one or more Scenes (View Controllers) and the connection or relationship between two scenes are known as Segue. This is how a typical storyboard with Scenes and Segue look.

The above example storyboard contains two scenes, first and second. These scenes are connected to each other by a Show Segue. Now let us see more about the Storyboard and Segues

Initial ViewController

App needs to know the ViewControler that will be displayed as the initial screen. You can set any controller as the initial scene using the option available as part of the Attributes Inspector

 

The storyboard will display an arrow in front of the Initial View Controller as shown in below screenshot. You can also drag and drop this arrow to the change the Initial View Controller.

Types of Segues

A segue is a relationship set between two view controllers. This can be done by pressing Control then drag and drop from one View Controller to anlther. Listed below are the different types of segues

  • Show 
  • Show Detail
  • Present Modally
  • PopOver Presentation
  • Custom

Check out this excellent Stackoverflow answer on types of Segues

Unwind Segues

Only the Show segue has a back button in the navigation bar of the child controller which takes you back to the Parent controller. For rest of the segues, we can use unwind segues to dismiss the child controller. Unwind segue can be created by first adding a IBAction with parameter type as UIStoryboardSegue to the parent Vuew Controller.

   //MARK:- Unwind Segue
    @IBAction func cancel(segue:UIStoryboardSegue {
        // do nothing
    }

Add a button to the child view controller press Control then drag and drop the button to the Exit button available at the top of the ViewController. Now select the Action Segue which was added to the parent view controller.

Transfering data between ViewControllers

One of the common question that gets asked is “how to transfer data between two view controllers“. Create a property in the child view controller and set the value for this property in the prepareForSegue function of the parent view controller.

//MARK:- ViewController Transition

     override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if  segue.identifier  ==   "detail"   {
            let  childViewController  =  segue.destination  as! SecondViewController
            childViewController.studentName  =  nameTextField.text
        }
    }

In the above prepareForSegue function, we check whether segue identifier is equal to detail. The identifier name can be provided under the Storyboard Segue in Attributes Inspector. Then we set the value for studentName property of the SecondViewController. By this way, you can transfer data between the View Controllers,

In the SecondViewController, you should be able access this property value and perform the required action. The below viewDidLoad code snippet access the property value and displays it in a label.

class SecondViewController: UIViewController {

    var studentName:String?
    @IBOutlet var displayName:UILabel!

    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
        if let name = studentName {
            displayName.text = name
        }
    }
}

Non Segue Transition

Another alternate way to transition between the View Controllers is to use instantiateViewController withIdentifier function of storyboard

//MARK:- Non Segue
  @IBAction func nonSegueCall(sender: AnyObject) {
        let childViewContoller  =
            storyboard?.instantiateViewController(withIdentifier: "SecondViewController") as! SecondViewController
        childViewContoller . studentName  =  nameTextField.text
        present( childViewContoller ,  animated: true ,  completion: nil)
    }

The above code snippet provides the same behaviour as prepareForSegue function. This function can be called on tap of a button and this requires an identifier to specified for the View Controller.

Download sample code from here.

Filed Under: ios, Xcode Tagged With: prepareForSegue, Scene, Segue, Storyboard

Get your current address in Swift (Swift 5)

November 7, 2019 By Ravi Shankar 22 Comments

In this Swift tutorial, we will see the steps required for using CoreLocation framework and retrieve the latitude and longitude of the location. Then use the CLGeocoder to reverse geocode the latitude and longitude details. This is a very basic tutorial that retrieves the location details on tap of a button and displays the information on the screen.

Updated :- The source has now been to updated to show the address details in TextFields.

Click File -> New and select Project sub menu list.

201407251656.jpg

In the Choose a template screen, select Single View Application and click Next button.

201407251657.jpg

Enter the product name as WhereAmI and select the language as Swift then click Next. Select a folder and create the new project and that folder.

201407251658.jpg

Navigate to ViewController.swift file and add a new function with name as findMyLocation after viewDidLoad function.

@IBAction func findMyLocation(sender: AnyObject) {

}

Navigate to Main.storyboard file, drag and drop Button from the Object Library on to the View Controller. Using the attributes inspector, change the name of the button to “Where Am I?”. If you need then change the background and text colour for the button. Then centre align the button both vertically and horizontally. Use the Resolve Auto Layout Option and pick Reset to Suggested Constraints.

201407251707.jpg

Navigate to Connections Inspector and connect the button to the findMyLocation action under Received Actions (Touch Up Inside event).

201407251711.jpg

Click the Project under Project Navigator and navigate to Build Phases. Click the + sign under Link Binary With Libraries and pick CoreLocation.framework from the list.

Add CoreLocation framework to Swift project201407251718.jpg

CoreLocation in Swift

Now navigate back to ViewController.swift file, add import CoreLocation after UIKit. Then we need to assign the current class as the delegate for CLLocationManagerDelegate. This is required because we will be using couple of delegate methods from CLLocationManager.

class ViewController: UIViewController, CLLocationManagerDelegate {

Define a constant for CLLocationManager after the class declaration.

let locationManager = CLLocationManager()

Navigate to IBAction function findMyLocation and add the following code

locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.requestWhenInUseAuthorization()
locationManager.startUpdatingLocation()

The above lines sets the class as delegate for locationManager, specifies the location accuracy and starts receiving location updates from CoreLocation. In order to get the location updates we need to implement the delegate functions of CLLocationManager, didUpdateLocations and didFailWithError

func locationManager(manager: CLLocationManager!, didUpdateLocations locations: [AnyObject]!) {
}

func locationManager(manager: CLLocationManager!, didFailWithError error: NSError!) {
}

didUpdateLocations function is triggered when new location updates are available. Similarly didFailWithError is called when there is a problem receiving the location updates. Let us first start implementing the simpler one i.e didFailWithError function. When there is an error, we are going to log the message to the console.

func locationManager(manager: CLLocationManager!, didFailWithError error: NSError!) {
	println("Error while updating location " + error.localizedDescription)
}

Then update didUpdateLocations function with the following code, also add a new function for printing the location details.

func locationManager(manager: CLLocationManager!, didUpdateLocations locations: [AnyObject]!) {
CLGeocoder().reverseGeocodeLocation(manager.location, completionHandler: {(placemarks, error)->Void in
		if error {
			println("Reverse geocoder failed with error" + error.localizedDescription)
			return
		}

		if placemarks.count > 0 {
			let pm = placemarks[0] as CLPlacemark
			self.displayLocationInfo(pm)
		} else {
			println("Problem with the data received from geocoder")
		}
	})
}

func displayLocationInfo(placemark: CLPlacemark) {
	if placemark != nil {
		//stop updating location to save battery life
		locationManager.stopUpdatingLocation()
		println(placemark.locality ? placemark.locality : "")
		println(placemark.postalCode ? placemark.postalCode : "")
		println(placemark.administrativeArea ? placemark.administrativeArea : "")
		println(placemark.country ? placemark.country : "")
	}
}

in the didUpdateLocations function, we pass the location co-ordinates to

 CLGeocoder().reverseGeocodeLocation

. Then check for error and process the location array (placemarks). Then for displaying the location details, we pass the placemark detail to displayLocationInfo function.

Add key to Info.plist for request permission to User’s location

In order to use the user’s location you need to request permission from the user by adding the keys “NSLocationWhenInUseUsageDescription” or “NSLocationAlwaysUsageDescription” to your Info.plist file, with the value blank or optionally a message included in the prompt to the user. One of those two key is required in iOS 8 to ask for your location.

Testing Location in Simulator

It is not possible to test current location with simulator. So we need to define a custom location or use the location already defined for debug purpose. When an app tries to access the location services on a simulator it displays the following popup.

Current Location Simulator Xcode 6

Here is a workaround to test the app using Xcode 11. Run the app on the a Simulator and tap “Find My Location” button. Nothing will happen as the app has not been given permission to use Location Services on Simulator.

201407251956.jpg

Click Debug menu then Location and select Apple from the sub menu list. Still nothing happens with the app and no messages are written to the console.

201407251957.jpg

Now click Hardware menu and select Home from menu list.

201407251959.jpg

Tap the Settings icon on Simulator -> Privacy -> Location -> Tap , select Always to allow the app to access the location.

201407252003.jpg201407252005.jpg

Now you should see Apple address details in the Console Output.

201407252008.jpg

You can also try out other location using the Simulate Location option.

Simulate location in Xcode 6 simulator

Hopefully the testing should be lot easier after issue with “Allow to use Current Location” is fixed.

Source from GitHub

Filed Under: Apple, Develop, ios, Programming, Xcode Tagged With: Apple, CoreLocation, Swift, Xcode

  1. Pages:
  2. 1
  3. 2
  4. 3
  5. 4
  6. 5
  7. 6
  8. 7
  9. 8
  10. »
Next Page »

Primary Sidebar

TwitterLinkedin

Recent Posts

  • How to block keywords in Jio broadband
  • How to disable opening an app automatically at login in Mac
  • How to set preferred Wifi network on Mac
  • Attribute Unavailable: Estimated section warning before iOS 11.0
  • How to recover Firefox password from Time Machine backup

Pages

  • About
  • Privacy Policy
  • Terms and Conditions

Copyright 2022 © rshankar.com

Terms and Conditions - Privacy Policy