Twitch Twitch - 2 months ago 111
iOS Question

Using Swift 3 in XCode 8, how to control a UITableView subview

I'm very, very new to Swift/Xcode and just flapping around in the dark... I'm so lost. I've got a screen that loads, and inside of it is a View with two subviews: MKMapView and UITAbleView.

The map loads perfectly, but I cannot seem to correctly control the table and load it with data because the app crashes when I click on "Show Nearby Restaurants".

Here is the full debugging traceback I'm getting:

2016-10-10 10:28:59.516777 Restaurants[93314:1607613] bundleid: com.Example.Restaurants, enable_level: 0, persist_level: 0, propagate_with_activity: 0
2016-10-10 10:28:59.517100 Restaurants[93314:1607613] subsystem: com.apple.siri, category: Intents, enable_level: 1, persist_level: 1, default_ttl: 0, info_ttl: 0, debug_ttl: 0, generate_symptoms: 0, enable_oversize: 0, privacy_setting: 0, enable_private_data: 0
2016-10-10 10:28:59.524112 Restaurants[93314:1607821] subsystem: com.apple.UIKit, category: HIDEventFiltered, enable_level: 0, persist_level: 0, default_ttl: 0, info_ttl: 0, debug_ttl: 0, generate_symptoms: 0, enable_oversize: 1, privacy_setting: 2, enable_private_data: 0
2016-10-10 10:28:59.526181 Restaurants[93314:1607821] subsystem: com.apple.UIKit, category: HIDEventIncoming, enable_level: 0, persist_level: 0, default_ttl: 0, info_ttl: 0, debug_ttl: 0, generate_symptoms: 0, enable_oversize: 1, privacy_setting: 2, enable_private_data: 0
2016-10-10 10:28:59.535733 Restaurants[93314:1607818] subsystem: com.apple.BaseBoard, category: MachPort, enable_level: 1, persist_level: 0, default_ttl: 0, info_ttl: 0, debug_ttl: 0, generate_symptoms: 0, enable_oversize: 0, privacy_setting: 0, enable_private_data: 0
2016-10-10 10:28:59.548057 Restaurants[93314:1607613] subsystem: com.apple.UIKit, category: StatusBar, enable_level: 0, persist_level: 0, default_ttl: 0, info_ttl: 0, debug_ttl: 0, generate_symptoms: 0, enable_oversize: 1, privacy_setting: 2, enable_private_data: 0
2016-10-10 10:28:59.564 Restaurants[93314:1607613] Unknown class _TtC22Restaurant18RootViewController in Interface Builder file.
2016-10-10 10:28:59.662817 Restaurants[93314:1607818] subsystem: com.apple.libsqlite3, category: logging, enable_level: 0, persist_level: 0, default_ttl: 0, info_ttl: 0, debug_ttl: 0, generate_symptoms: 0, enable_oversize: 1, privacy_setting: 2, enable_private_data: 0
2016-10-10 10:28:59.676411 Restaurants[93314:1607823] subsystem: com.apple.network, category: , enable_level: 0, persist_level: 0, default_ttl: 0, info_ttl: 0, debug_ttl: 0, generate_symptoms: 0, enable_oversize: 0, privacy_setting: 2, enable_private_data: 0
2016-10-10 10:28:59.676674 Restaurants[93314:1607823] [] tcp_connection_create_with_endpoint_and_parameters 1 restaurants.example.com 80
2016-10-10 10:28:59.677043 Restaurants[93314:1607823] [] tcp_connection_start 1 starting
2016-10-10 10:28:59.677355 Restaurants[93314:1607823] [] nw_connection_create creating connection to restaurants.example.com:80
2016-10-10 10:28:59.677626 Restaurants[93314:1607823] [] tcp_connection_start starting tc_nwconn=0x7ff21100b610
2016-10-10 10:28:59.677833 Restaurants[93314:1607818] [] __nw_connection_start_block_invoke 1 starting
2016-10-10 10:28:59.678105 Restaurants[93314:1607818] [] nw_endpoint_handler_start [1 restaurants.example.com:80 initial path (null)]
2016-10-10 10:28:59.678293 Restaurants[93314:1607818] [] nw_connection_endpoint_report [1 restaurants.example.com:80 initial path (null)] reported event path:start
2016-10-10 10:28:59.678993 Restaurants[93314:1607818] [] nw_endpoint_handler_path_change [1 restaurants.example.com:80 waiting path (satisfied)]
2016-10-10 10:28:59.679235 Restaurants[93314:1607818] [] nw_connection_endpoint_report [1 restaurants.example.com:80 waiting path (satisfied)] reported event path:satisfied
2016-10-10 10:28:59.679788 Restaurants[93314:1607818] [] nw_connection_endpoint_report [1 restaurants.example.com:80 waiting path (satisfied)] skipping state update
2016-10-10 10:28:59.680194 Restaurants[93314:1607818] [] nw_endpoint_proxy_handler_should_use_proxy Looking up proxy for hostname: restaurants.example.com, ifindex: 0
2016-10-10 10:28:59.680805 Restaurants[93314:1607818] subsystem: com.apple.SystemConfiguration, category: SCPreferences, enable_level: 0, persist_level: 0, default_ttl: 0, info_ttl: 0, debug_ttl: 0, generate_symptoms: 0, enable_oversize: 0, privacy_setting: 2, enable_private_data: 0
2016-10-10 10:28:59.681819 Restaurants[93314:1607818] [] -[NWConcrete_nw_endpoint_resolver startWithHandler:] [1 restaurants.example.com:80 waiting resolver (satisfied)]
2016-10-10 10:28:59.682059 Restaurants[93314:1607818] [] nw_connection_endpoint_report [1 restaurants.example.com:80 in_progress resolver (satisfied)] reported event resolver:start_dns
2016-10-10 10:28:59.682582 Restaurants[93314:1607818] [] nw_resolver_create_dns_service_on_queue Starting host resolution restaurants.example.com:80, flags 0x4000d000
2016-10-10 10:28:59.687044 Restaurants[93314:1607613] subsystem: com.apple.BackBoardServices.fence, category: App, enable_level: 1, persist_level: 0, default_ttl: 0, info_ttl: 0, debug_ttl: 0, generate_symptoms: 0, enable_oversize: 0, privacy_setting: 0, enable_private_data: 0
2016-10-10 10:28:59.876823 Restaurants[93314:1607823] [] nw_resolver_host_resolve_callback flags=0x2 ifindex=0 error=NoError(0) hostname=us-east-1-a.route.herokuapp.com. addr=23.23.196.165:0 ttl=75
2016-10-10 10:28:59.877069 Restaurants[93314:1607823] [] nw_resolver_start_query_timer Starting 1s query timer to receive all address families for restaurants.example.com:80
2016-10-10 10:28:59.877302 Restaurants[93314:1607823] [] nw_resolver_start_crazy_eyeballs_timer Received IPv4 result first, performing crazy eyeballs: waiting 50ms on IPv6 for restaurants.example.com:80
2016-10-10 10:28:59.999464 Restaurants[93314:1607823] [] __nw_resolver_start_crazy_eyeballs_timer_block_invoke Crazy eyeballs timer fired: did not receive IPv6 in time, reporting only IPv4 result for restaurants.example.com:80
2016-10-10 10:28:59.999686 Restaurants[93314:1607823] [] nw_resolver_cancel_crazy_eyeballs_timer Cancelling crazy eyeballs timer for restaurants.example.com
2016-10-10 10:29:00.000005 Restaurants[93314:1607823] [] nw_endpoint_resolver_update [1 restaurants.example.com:80 in_progress resolver (satisfied)] resolver is in_progress
2016-10-10 10:29:00.000373 Restaurants[93314:1607823] [] nw_endpoint_resolver_update [1 restaurants.example.com:80 in_progress resolver (satisfied)] Adding endpoint handler for 23.23.196.165:80
2016-10-10 10:29:00.001412 Restaurants[93314:1607823] [] nw_endpoint_resolver_update [1 restaurants.example.com:80 in_progress resolver (satisfied)] Updated endpoint list is (23.23.196.165:80)
2016-10-10 10:29:00.001998 Restaurants[93314:1607823] [] nw_connection_endpoint_report [1 restaurants.example.com:80 in_progress resolver (satisfied)] reported event resolver:receive_dns
2016-10-10 10:29:00.002690 Restaurants[93314:1607823] [] nw_endpoint_resolver_start_next_child [1 restaurants.example.com:80 in_progress resolver (satisfied)] starting child endpoint 23.23.196.165:80
2016-10-10 10:29:00.003071 Restaurants[93314:1607823] [] nw_endpoint_resolver_start_next_child [1 restaurants.example.com:80 in_progress resolver (satisfied)] starting next child endpoint in 178ms
2016-10-10 10:29:00.003507 Restaurants[93314:1607823] [] nw_endpoint_handler_start [1.1 23.23.196.165:80 initial path (null)]
2016-10-10 10:29:00.003841 Restaurants[93314:1607823] [] nw_endpoint_resolver_receive_report [1 restaurants.example.com:80 in_progress resolver (satisfied)] received child report:[1.1 23.23.196.165:80 initial path (null)]
2016-10-10 10:29:00.004089 Restaurants[93314:1607823] [] nw_connection_endpoint_report [1.1 23.23.196.165:80 initial path (null)] reported event path:start
2016-10-10 10:29:00.004526 Restaurants[93314:1607823] [] nw_endpoint_handler_path_change [1.1 23.23.196.165:80 waiting path (satisfied)]
2016-10-10 10:29:00.004791 Restaurants[93314:1607823] [] nw_endpoint_resolver_receive_report [1 restaurants.example.com:80 in_progress resolver (satisfied)] received child report:[1.1 23.23.196.165:80 waiting path (satisfied)]
2016-10-10 10:29:00.005035 Restaurants[93314:1607823] [] nw_connection_endpoint_report [1.1 23.23.196.165:80 waiting path (satisfied)] reported event path:satisfied
2016-10-10 10:29:00.005323 Restaurants[93314:1607823] [] nw_endpoint_proxy_handler_should_use_proxy Looking up proxy for hostname: <nil>, ifindex: 0
2016-10-10 10:29:00.006192 Restaurants[93314:1607823] [] -[NWConcrete_nw_endpoint_flow startWithHandler:] [1.1 23.23.196.165:80 waiting socket-flow (satisfied)]
2016-10-10 10:29:00.006437 Restaurants[93314:1607823] [] nw_endpoint_flow_setup_socket [1.1 23.23.196.165:80 in_progress socket-flow (satisfied)] creating socket
2016-10-10 10:29:00.006818 Restaurants[93314:1607823] [] nw_endpoint_flow_attach_protocols [1.1 23.23.196.165:80 in_progress socket-flow (satisfied)]
2016-10-10 10:29:00.007388 Restaurants[93314:1607823] [] nw_endpoint_flow_attach_protocols [1.1 23.23.196.165:80 in_progress socket-flow (satisfied)] Attached flow protocol
2016-10-10 10:29:00.007722 Restaurants[93314:1607823] [] nw_endpoint_resolver_receive_report [1 restaurants.example.com:80 in_progress resolver (satisfied)] received child report:[1.1 23.23.196.165:80 in_progress socket-flow (satisfied)]
2016-10-10 10:29:00.008528 Restaurants[93314:1607823] [] nw_connection_endpoint_report [1.1 23.23.196.165:80 in_progress socket-flow (satisfied)] reported event flow:start_connect
2016-10-10 10:29:00.017739 Restaurants[93314:1607823] [] nw_resolver_host_resolve_callback flags=0x2 ifindex=0 error=NoSuchRecord(-65554) hostname=us-east-1-a.route.herokuapp.com. addr=::.0 ttl=77
2016-10-10 10:29:00.017976 Restaurants[93314:1607823] [] nw_resolver_cancel_query_timer Cancelling query timer for restaurants.example.com
2016-10-10 10:29:00.018285 Restaurants[93314:1607823] [] nw_endpoint_resolver_update [1 restaurants.example.com:80 in_progress resolver (satisfied)] resolver is complete
2016-10-10 10:29:00.018545 Restaurants[93314:1607823] [] nw_endpoint_resolver_update [1 restaurants.example.com:80 in_progress resolver (satisfied)] Keeping started endpoint 23.23.196.165:80
2016-10-10 10:29:00.018797 Restaurants[93314:1607823] [] nw_endpoint_resolver_update [1 restaurants.example.com:80 in_progress resolver (satisfied)] Updated endpoint list is (23.23.196.165:80)
2016-10-10 10:29:00.019050 Restaurants[93314:1607823] [] nw_connection_endpoint_report [1 restaurants.example.com:80 in_progress resolver (satisfied)] reported event resolver:receive_dns
2016-10-10 10:29:00.166619 Restaurants[93314:1607818] [] nw_socket_handle_socket_event Event mask: 0x800
2016-10-10 10:29:00.166833 Restaurants[93314:1607818] [] nw_socket_handle_socket_event Socket received CONNECTED event
2016-10-10 10:29:00.167079 Restaurants[93314:1607818] [] nw_socket_setup_notsent_lowat Set TCP_NOTSENT_LOWAT(16384)
2016-10-10 10:29:00.167332 Restaurants[93314:1607818] [] nw_endpoint_flow_protocol_connected [1.1 23.23.196.165:80 in_progress socket-flow (satisfied)] Output protocol connected
2016-10-10 10:29:00.167891 Restaurants[93314:1607818] [] nw_endpoint_flow_connected_path_change [1.1 23.23.196.165:80 ready socket-flow (satisfied)]
2016-10-10 10:29:00.168068 Restaurants[93314:1607818] [] nw_endpoint_flow_connected_path_change [1.1 23.23.196.165:80 ready socket-flow (satisfied)] Connected path is satisfied
2016-10-10 10:29:00.168271 Restaurants[93314:1607818] [] nw_endpoint_resolver_receive_report [1 restaurants.example.com:80 in_progress resolver (satisfied)] received child report:[1.1 23.23.196.165:80 ready socket-flow (satisfied)]
2016-10-10 10:29:00.168527 Restaurants[93314:1607818] [] nw_connection_endpoint_report [1.1 23.23.196.165:80 ready socket-flow (satisfied)] reported event flow:finish_connect
2016-10-10 10:29:00.168796 Restaurants[93314:1607818] [] nw_connection_endpoint_report [1 restaurants.example.com:80 ready resolver (satisfied)] reported event flow:finish_connect
2016-10-10 10:29:00.169019 Restaurants[93314:1607818] [] nw_endpoint_resolver_receive_report [1 restaurants.example.com:80 ready resolver (satisfied)] received child report:[1.1 23.23.196.165:80 ready socket-flow (satisfied)]
2016-10-10 10:29:00.169219 Restaurants[93314:1607818] [] nw_connection_endpoint_report [1.1 23.23.196.165:80 ready socket-flow (satisfied)] reported event flow:changed_viability
2016-10-10 10:29:00.169415 Restaurants[93314:1607818] [] nw_connection_endpoint_report [1 restaurants.example.com:80 ready resolver (satisfied)] reported event flow:changed_viability
2016-10-10 10:29:00.169714 Restaurants[93314:1607823] [] __tcp_connection_start_block_invoke 1 sending event TCP_CONNECTION_EVENT_CONNECTED in response to state ready and error (null)
2016-10-10 10:29:00.169913 Restaurants[93314:1607823] [] tcp_connection_event_notify 1 event: TCP_CONNECTION_EVENT_CONNECTED, reason: nw_connection event, should deliver: true
2016-10-10 10:29:00.170271 Restaurants[93314:1607823] [] tcp_connection_get_statistics DNS: 320ms/323ms since start, TCP: 160ms/490ms since start, TLS: 0ms/0ms since start
2016-10-10 10:29:27.664045 Restaurants[93314:1607613] subsystem: com.apple.UIKit, category: Touch, enable_level: 0, persist_level: 0, default_ttl: 1, info_ttl: 0, debug_ttl: 0, generate_symptoms: 0, enable_oversize: 1, privacy_setting: 2, enable_private_data: 0
2016-10-10 10:29:27.664832 Restaurants[93314:1607613] subsystem: com.apple.UIKit, category: Gesture, enable_level: 0, persist_level: 0, default_ttl: 1, info_ttl: 0, debug_ttl: 0, generate_symptoms: 0, enable_oversize: 1, privacy_setting: 2, enable_private_data: 0
2016-10-10 10:29:27.665446 Restaurants[93314:1607613] subsystem: com.apple.UIKit, category: GestureEnvironment, enable_level: 0, persist_level: 0, default_ttl: 1, info_ttl: 0, debug_ttl: 0, generate_symptoms: 0, enable_oversize: 1, privacy_setting: 2, enable_private_data: 0
2016-10-10 10:29:27.665830 Restaurants[93314:1607613] subsystem: com.apple.UIKit, category: GestureExclusion, enable_level: 0, persist_level: 0, default_ttl: 1, info_ttl: 0, debug_ttl: 0, generate_symptoms: 0, enable_oversize: 1, privacy_setting: 2, enable_private_data: 0
2016-10-10 10:29:27.846 Restaurants[93314:1607613] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '-[UITableViewController loadView] instantiated view controller with identifier "UIViewController-Wgc-6W-3v8" from storyboard "Main", but didn't get a UITableView.'
*** First throw call stack:
(
0 CoreFoundation 0x000000010819f34b __exceptionPreprocess + 171
1 libobjc.A.dylib 0x00000001078d821e objc_exception_throw + 48
2 CoreFoundation 0x0000000108208265 +[NSException raise:format:] + 197
3 UIKit 0x00000001089e383c -[UITableViewController loadView] + 638
4 UIKit 0x0000000108763c4c -[UIViewController loadViewIfRequired] + 201
5 UIKit 0x000000010876a4d6 -[UIViewController __viewWillAppear:] + 118
6 UIKit 0x0000000108795393 -[UINavigationController _startCustomTransition:] + 1290
7 UIKit 0x00000001087a6008 -[UINavigationController _startDeferredTransitionIfNeeded:] + 697
8 UIKit 0x00000001087a719b -[UINavigationController __viewWillLayoutSubviews] + 58
9 UIKit 0x000000010899e1b7 -[UILayoutContainerView layoutSubviews] + 223
10 UIKit 0x0000000108687344 -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 1237
11 QuartzCore 0x000000010fc9ecdc -[CALayer layoutSublayers] + 146
12 QuartzCore 0x000000010fc927a0 _ZN2CA5Layer16layout_if_neededEPNS_11TransactionE + 366
13 QuartzCore 0x000000010fc9261e _ZN2CA5Layer28layout_and_display_if_neededEPNS_11TransactionE + 24
14 QuartzCore 0x000000010fc2062c _ZN2CA7Context18commit_transactionEPNS_11TransactionE + 280
15 QuartzCore 0x000000010fc4d713 _ZN2CA11Transaction6commitEv + 475
16 UIKit 0x00000001085bc067 _UIApplicationFlushRunLoopCATransactionIfTooLate + 206
17 UIKit 0x0000000108dcbb30 __handleEventQueue + 5672
18 CoreFoundation 0x0000000108144311 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
19 CoreFoundation 0x000000010812959c __CFRunLoopDoSources0 + 556
20 CoreFoundation 0x0000000108128a86 __CFRunLoopRun + 918
21 CoreFoundation 0x0000000108128494 CFRunLoopRunSpecific + 420
22 GraphicsServices 0x000000010fb81a6f GSEventRunModal + 161
23 UIKit 0x00000001085c2f34 UIApplicationMain + 159
24 Restaurants 0x0000000106d157af main + 111
25 libdyld.dylib 0x000000010b5d468d start + 1
26 ??? 0x0000000000000001 0x0 + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb)


Here is my code that controls the view "NearbyDataViewController.swift":

import UIKit
import Alamofire
import SwiftyJSON
import MapKit
import CoreLocation

class NearbyDataViewController: UITableViewController, CLLocationManagerDelegate {

@IBOutlet weak var nearbyMap: MKMapView!
@IBOutlet weak var nearbyTable: UITableView!

// json from server
var nearbyRestaurantsJSON:JSON = []

// constant for holding the user's location
let locationManager = CLLocationManager()


override func viewDidLoad(){
super.viewDidLoad()

//
// Set table view
//
self.nearbyTable.delegate = self
self.nearbyTable.dataSource = self
self.nearbyTable.allowsSelection = true

///////////////////
// Load Map //
///////////////////

self.locationManager.delegate = self
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest
self.locationManager.requestWhenInUseAuthorization()
self.locationManager.startUpdatingLocation()
self.nearbyMap.showsUserLocation = true

///////////////////
// Query Server //
///////////////////


//
// Request data for nearby restaurants
//
let latText = String(format: "%f", (self.locationManager.location?.coordinate.latitude)!)
let lonText = String(format: "%f", (self.locationManager.location?.coordinate.longitude)!)
print("XXXXXXXXX USER LOCATION XXXXXXXXX: " + latText + ", " + lonText)


let server_url:String = "http://www.example.com/&lat=" + latText + "&lon=" + lonText

Alamofire.request(server_url).responseJSON { response in

// load resposne into into SwiftyJSON to parse JSON
let json = JSON(response.result.value)

// show response
self.nearbyRestaurantsJSON = json["objects"]
debugPrint(self.nearbyRestaurantsJSON)


// load the table
DispatchQueue.main.async {
self.nearbyTable.reloadData()
return
}

}
}

//
// Enable the location manager
//

func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let location = locations.last
let center = CLLocationCoordinate2D(latitude: location!.coordinate.latitude, longitude: location!.coordinate.longitude)
let region = MKCoordinateRegion(center: center, span: MKCoordinateSpan(latitudeDelta: 0.005, longitudeDelta: 0.005))
self.nearbyMap.setRegion(region, animated: true)
self.locationManager.stopUpdatingLocation()
}

func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
print("Errors: " + error.localizedDescription)
}

//
// Table Data Parse
//
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}

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

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)

// change the label text to the restaurant name
cell.textLabel?.text = nearbyRestaurantsJSON[indexPath.row]["rest_name"].string

// get length of inspection reports and find most recent
var insp_dates = [Date?]()
let dateformatter = DateFormatter()
dateformatter.dateFormat = "yyyy-MM-dd"

for (_, subJson):(String, JSON) in (nearbyRestaurantsJSON[indexPath.row]["onlinereports"]) {
// convert string to date
let date_string = subJson["insp_date"].string
let dt = dateformatter.date(from: date_string!)
insp_dates.append(dt)
}

let dt = insp_dates.sorted{ (firstThing, secondThing) -> Bool in
firstThing! > secondThing!
}.first

let dt_str = dateformatter.string(from: dt!!)

// match the date to the json object
for (_, subJson):(String, JSON) in (nearbyRestaurantsJSON[indexPath.row]["onlinereports"]) {
if subJson["insp_date"].string == dt_str {
if Double(subJson["insp_score"].string!)! + 1 < 37.0 {
cell.imageView?.image = UIImage(named: "thumbs_down")
}
else {
cell.imageView?.image = UIImage(named: "thumbs_up")
}
}
}

return cell
}



}


My storyboard layout:
enter image description here

Delegates/Outlets for the root view (NearbyDataViewController):
enter image description here

Delegates/Outlets for nearbyMap:
enter image description here

Delegates/Outlets for nearbyTable:
enter image description here

Answer

NearbyDataViewController is subclassed from UITableViewController, which requires it's root view to be UITableView, which is obviously not, since you have MKMapView there as well.

So you should:

  1. Subclass from plain UIViewController,
  2. Set delegate and dataSource manually:

enter image description here

  1. Declare that you implement UITableViewDelegate and UITableViewDataSource (and of course implement their methods, as you did).

class NearbyDataViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, CLLocationManagerDelegate