I can't create the map programmatically - black screen

#1

Hi there

On page 97 Creating a View Programmatically

I deleted the map view.
I entered the following code in MapViewController.swift

importMapKit

var mapView: MKMapView!
override func loadView() {
    mapView = MKMapView()   
    view = mapView 

Once I run the app I get a black screen where the map should be? What’s going wrong?

Thanks!

#2

Select Main.storyboard in the Project Navigator. What’s listed in the table of contents for the “Map Scene”? To reveal the table of contents, you may have to click on a square icon with a black line on the left of the square, which is located on the bottom left of your storyboard. When the table of contents is visible, click on all the disclosure triangles for the Map Scene.

#3

Thanks for the reply

Under the map scene there is

Map Scene
Map > Map (with star beside it, this is the 'Tab bar item’
First Responder
Exit

Just like it looks in the book

#4

Okay, that looks fine. Next, check your connections in the Connections Inspector (right pane). Select the Tab Bar Controller Scene in the storyboard’s table of contents. What do you see in the Connections Inspector?

Are you running your app while your wifi on your Mac is on and connected to a network? Have you tried using a different network?

#5

So, for the Tab Bar Scene you can see the the map does not have the circle beside it in the Connections Inspector - maybe this is the problem?

Also Wi-Fi is connected and I’ve tried it on different networks. Thanks for the speedy reply btw!

p

#6

The Connections Inspector looks fine, too–there’s only one circle for all the views that the TabBarController handles.

I’m out of ideas.

#7

Can you post the code for both the ConversionViewController and the MapViewController? I want to see the entire file for each one. You are going to have to learn how to post code, so search google or this forum for instructions.

#8

Thanks! Here is ConversionViewController.swift (hope the way I’m posting it is OK??)

//  ConversionViewController.swift
//  WorldTrotter_BNR_iOS_Programming


import UIKit

class ConversionViewController: UIViewController, UITextFieldDelegate {


func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {

    let existingTextHasDecimalSeperator = textField.text?.rangeOfString(".")
    let replacementTextHasDecimalSeperator = string.rangeOfString(".")
    
    if existingTextHasDecimalSeperator != nil &&
        replacementTextHasDecimalSeperator != nil {
            return false
    }
    else {
        return true
    }
}

@IBOutlet var celsiusLabel: UILabel!

var fahrenheitValue: Double? {
    didSet {
        updateCelsiusLabel()
    }
}

var celsiusValue: Double? {
    if let value = fahrenheitValue {
        return (value - 32) * (5/9)
    }
    else {
        return nil
}
    
}

    func updateCelsiusLabel() {
    if let value = celsiusValue {
        celsiusLabel.text = numberFormatter.stringFromNumber(value)
    }
    else {
        celsiusLabel.text = "???"
}
}




@IBOutlet var textField: UITextField!


@IBAction func fahrenheitFieldEditingChanged(textField: UITextField) {
    
    if let text = textField.text, value = Double(text) {
        fahrenheitValue = value
    }
    else {
        fahrenheitValue = nil
    }

}

@IBAction func dismissKeyboard(sender: AnyObject) {
    textField.resignFirstResponder()
}


let numberFormatter:NSNumberFormatter = {
    let nf = NSNumberFormatter()
    nf.numberStyle = .DecimalStyle
    nf.minimumFractionDigits = 0
    nf.maximumFractionDigits = 1
    return nf
}()

override func viewDidLoad() {

    print("MapViewController loaded its view.")
}

}
#9

And here is MapView Controller

//  MapViewController.swift
//  WorldTrotter_BNR_iOS_Programming

import UIKit
import MapKit


// Define a UIViewController subclass named MapViewController

class MapViewController: UIViewController {

var mapView: MKMapView!

override func loadView() {
    // create a map view
    mapView = MKMapView()
    
    //        set it as *the* view of this view controller
    view = mapView
    
    let segmentedControl
    = UISegmentedControl(items: ["Standard", "Hybrid", "Satellite"])
    segmentedControl.backgroundColor
        = UIColor.whiteColor().colorWithAlphaComponent(0.5)
    segmentedControl.selectedSegmentIndex = 0
    
    segmentedControl.translatesAutoresizingMaskIntoConstraints = false
    view.addSubview(segmentedControl)
    
    let topConstraint = segmentedControl.topAnchor.constraintEqualToAnchor(view.topAnchor)
    let leadingConstraint = segmentedControl.leadingAnchor.constraintEqualToAnchor(view.leadingAnchor)
    let trailingConstraint = segmentedControl.trailingAnchor.constraintEqualToAnchor(view.trailingAnchor)
    
    topConstraint.active = true
    leadingConstraint.active = true
    trailingConstraint.active = true
}


override func viewDidLoad() {
    //        Always call the super implementation of viewDidLoad
    super.viewDidLoad()
    
    print("MapViewController loaded its view.")
}

}
#10

Were you ever able to see the MapView, like at the end of Chapter 5? I can duplicate the black screen you are seeing by:

  1. Selecting Main.storyboard

  2. In the storyboard’s table of contents, under the Map Scene selecting the MapViewController(yellow icon with Map next to it).

  3. Selecting the Identity Inspector in the right pane, and under the heading Custom Class clicking on the down arrow to reveal the drop down list, and selecting UIViewController.

If I run the app after doing that, then click on the Map icon in the TabBar, I see a black screen. The reason that occurs is because you need to associate the MapViewController class in your code with the generic UIViewController you dragged onto the storyboard. The way you do that is by revealing the drop down list in step 3 and choosing the name of the class in your code, i.e. MapViewController. Once you change the class to MapViewController, the loadView() function in your MapViewController class will get called when you click on the Map icon in the TabBar for the first time.

The instructions for opening up the Identity Inspector and selecting the proper class name from the drop down list are in the middle of p.91.

Maybe on your first try you deleted the whole MapViewController instead of just the view? Then, after you reassembled your storyboard, you never changed the class of the new generic UIViewController to MapViewController?

Some hints on code organization:

  1. Function definitions and outlet declarations should to be indented. They should not be at the same indent level as class MapViewController.

  2. All your outlets should appear at the very top of the class definition–not scattered throughout your code.

#11

Wow, thanks so much! You’re 100% correct!

I kinda lost heart with this and forget to check the forum over Christmas, but you’re explanation hit the nail on the head.

Will get back to it! Thanks!