我正在使用Swift 3开发一个应用程序。我必须在两个视图控制器之间传递一个值(使用协议和委托)。我收到错误:
致命错误:在打开可选项时意外发现nil 值。
因为delegate
变量的值为nil
。
代理人定义为var delegate: LeftSideDelegate!
,我将其称为delegate.sendShapeDelivery()
。
它被称为didTappedSwicht
的位置的函数是另一种协议的方法(它不必影响它?)。
有谁知道为什么会出现这个错误?
import UIKit
protocol LeftSideDelegate {
func sendShapeDelivery(deliveryPos: Int)
}
class LeftSideViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, customCellDelegate {
var selectedIndex = -1
var feedModelDeliveries: [deliveriesLeftTableModel] = [deliveriesLeftTableModel]()
var delegate: LeftSideDelegate!
@IBOutlet weak var tableSideLeft: UITableView!
@IBAction func opacityDelivery(_ sender: UISlider) {
print(sender.value)
}
//var delegate = OptionDelegate()?
override func viewDidLoad() {
super.viewDidLoad()
//tableSideLeft.isEditing = true
fillDataDeliveries()
}
func fillDataDeliveries() {
for i in 0...snapShotsLegend.legendEntries[0].deliverables.count - 1 {
let newModel = deliveriesLeftTableModel()
newModel.firstViewLabel = snapShotsLegend.legendEntries[0].deliverables[i].type
newModel.secondViewLabel = "Option " + snapShotsLegend.legendEntries[0].deliverables[i].type
newModel.idDeliveryResponse = snapShotsLegend.legendEntries[0].deliverables[i].options[0].id
newModel.initialMaxDeliveryResponse = String(snapShotsLegend.legendEntries[0].deliverables[i].options[0].initial_max_value)
newModel.initialMinDeliveryResponse = String(snapShotsLegend.legendEntries[0].deliverables[i].options[0].initial_min_value)
newModel.maxRangeDeliveryResponse = String(snapShotsLegend.legendEntries[0].deliverables[i].options[0].max_range)
newModel.minRangeDeliveryResponse = String(snapShotsLegend.legendEntries[0].deliverables[i].options[0].min_range)
feedModelDeliveries.append(newModel)
}
tableSideLeft.delegate = self
tableSideLeft.dataSource = self
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return snapShotsLegend.legendEntries[0].deliverables.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cellIdentifier = "Cell"
let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as! customCell
cell.setupWithModel(model: feedModelDeliveries[indexPath.row])
cell.delegate = self as customCellDelegate
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if (selectedIndex == indexPath.row) {
return 300
} else {
return 60
}
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if (selectedIndex == indexPath.row) {
selectedIndex = -1
} else {
selectedIndex = indexPath.row
}
self.tableSideLeft.beginUpdates()
self.tableSideLeft.reloadRows(at: [indexPath], with: UITableViewRowAnimation.automatic)
self.tableSideLeft.endUpdates()
}
//MARK: FUNCTIONS ALLOWS REORDERING OF CELLS
func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool {
return true
}
func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
let item = snapShotsLegend.legendEntries[0].deliverables[sourceIndexPath.row]
snapShotsLegend.legendEntries[0].deliverables.remove(at: sourceIndexPath.row)
snapShotsLegend.legendEntries[0].deliverables.insert(item, at: destinationIndexPath.row)
}
func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCellEditingStyle {
return UITableViewCellEditingStyle.none
}
func didTappedSwicht(cell: customCell) {
let indexPath = tableSideLeft.indexPath(for: cell)
feedModelDeliveries[(indexPath?.row)!].swichtActiveLayer = cell.swichtActiveLayer.isOn
if cell.swichtActiveLayer.isOn {
print("SHOW DELIVERY TO MAP, LAYER -> \( snapShotsLegend.legendEntries[0].deliverables[(indexPath?.row)!].url_layer)")
// MARK: SWICHT ON (NOT EXIST DELIVERABLE / EXIST DELIVERABLE)
if feedModelDeliveries[(indexPath?.row)!].tileLayer == nil {
delegate.sendShapeDelivery(deliveryPos: (indexPath?.row)!)
// MARK: SWICHT OFF
} else {
print("Exist deliverable -> not call WMS")
}
} else {
print("HIDE DELIVERY TO MAP, LAYER -> \( snapShotsLegend.legendEntries[0].deliverables[(indexPath?.row)!].url_layer)")
}
}
func didMoveSlider(cell: customCell) {
let indexPath = tableSideLeft.indexPath(for: cell)
feedModelDeliveries[(indexPath?.row)!].sliderOpacity = cell.sliderOpacity.value
}
}
我调用协议(at ende)函数的代码是:
import UIKit
import GoogleMaps
import MapKit
import ObjectMapper
//MARK: GLOBAL VARIABLES
let showLegend = UserDefaults.standard
let showLegendInformation = "showLegend"
var fields:WFSModel = WFSModel()
var allFields:[Field] = [Field]()
var total_parcels:[Parcel] = [Parcel]()
var poligons: [GMSPolygon] = []
var holes: [GMSMutablePath] = []
var snapShotsLegend : SnapshotsLegendModel = SnapshotsLegendModel()
var allDeliveries: [GMSURLTileLayer] = []
class MainMapVC: UIViewController, UISearchBarDelegate, CLLocationManagerDelegate, GMSMapViewDelegate {
//OUTLETS:
@IBOutlet weak var dragLegend: NSLayoutConstraint!
@IBOutlet weak var iconDragLegend: UIImageView!
@IBOutlet weak var mapView: GMSMapView!
@IBOutlet weak var timer: UIActivityIndicatorView!
@IBOutlet weak var dragLengendView: UIView!
@IBOutlet weak var iconBarLegend: UIBarButtonItem!
//MARK: VARIABLES
let layer: WMSTileOverlay
var window: UIWindow?
var centerContainer: MMDrawerController?
var url = ""
let locationManager = CLLocationManager()
var coordenatesCellSelected: [Double] = [Double]()
var hole = GMSMutablePath()
var wfs:WFSModel = WFSModel()
var rect = GMSMutablePath()
let start = NSDate();
var polygonSelect = GMSPath()
var posSelecteTable:Int = 0
var menu_vc: LeftSideViewController!
//MARK:VIEWS
override func viewWillAppear(_ animated: Bool) {
super.viewDidLoad()
if coordenatesCellSelected.count != 0 {
let bounds = GMSCoordinateBounds(path: poligons[posSelecteTable].path!)
self.mapView!.animate(with: GMSCameraUpdate.fit(bounds, withPadding: 15.0))
poligons[posSelecteTable].fillColor = UIColor(red: 8/256, green: 246/255, blue: 191/255, alpha: 0.9)
poligons[posSelecteTable].strokeColor = .blue
poligons[posSelecteTable].strokeWidth = 2
poligons[posSelecteTable].map = mapView
}
if showLegend.bool(forKey: showLegendInformation) == true {
//self.dragLengendView.isHidden = false
self.iconBarLegend.isEnabled = true
}
}
override func viewDidLoad() {
super.viewDidLoad()
menu_vc = self.storyboard?.instantiateViewController(withIdentifier: "LeftSideViewController") as! LeftSideViewController
self.timer.startAnimating()
locationManager.delegate = self
locationManager.requestWhenInUseAuthorization()
mapView.isMyLocationEnabled = true
mapView.settings.myLocationButton = true
url = ""
let swipeRight = UISwipeGestureRecognizer(target: self, action: #selector(self.respondToGesture))
swipeRight.direction = UISwipeGestureRecognizerDirection.right
let swipeLeft = UISwipeGestureRecognizer(target: self, action: #selector(self.respondToGesture))
swipeRight.direction = UISwipeGestureRecognizerDirection.left
self.view.addGestureRecognizer(swipeRight)
self.view.addGestureRecognizer(swipeLeft)
if showLegend.bool(forKey: showLegendInformation) == false {
self.iconBarLegend.tintColor = UIColor.clear
self.iconBarLegend.isEnabled = false
}
if !allFields.isEmpty{
drawFields()
}
if allFields.isEmpty{
self.getCardfromGeoserver()
}
self.mapView.mapType = .satellite
}
@IBAction func menu_action(_ sender: UIBarButtonItem) {
if AppDelegate.menu_bool{
show_menu_left()
}else{
close_menu_left()
}
}
func show_menu_left(){
UIView.animate(withDuration: 0.6) { ()->Void in
self.menu_vc.view.frame = CGRect(x: 0, y: 60, width: UIScreen.main.bounds.size.width, height: UIScreen.main.bounds.size.height)
self.menu_vc.view.backgroundColor = UIColor.black.withAlphaComponent(0.6)
self.addChildViewController(self.menu_vc)
self.view.addSubview(self.menu_vc.view)
AppDelegate.menu_bool = false
}
}
func close_menu_left(){
UIView.animate(withDuration: 0.6, animations: { ()->Void in
self.menu_vc.view.frame = CGRect(x: -UIScreen.main.bounds.size.width, y: 60, width: -UIScreen.main.bounds.size.width, height: UIScreen.main.bounds.size.height)
}) { (finished) in
self.menu_vc.view.removeFromSuperview()
}
AppDelegate.menu_bool = true
}
func respondToGesture(gesture: UISwipeGestureRecognizer){
switch gesture.direction{
case UISwipeGestureRecognizerDirection.right:
show_menu_left()
case UISwipeGestureRecognizerDirection.left:
close_on_swipe()
default:
break
}
}
func close_on_swipe(){
if AppDelegate.menu_bool{
show_menu_left()
}else{
close_menu_left()
}
}
//MARK: FUNCITIONS
required init?(coder aDecoder: NSCoder) {
self.layer = WMSTileOverlay(urlArg: url)
super.init(coder: aDecoder)
}
func getCardfromGeoserver() {
mapView.clear()
//mapView.camera = GMSCameraPosition(target: CLLocationCoordinate2D(latitude: 40.4256572451179, longitude: -3.18201821297407), zoom: 5.5, bearing: 0, viewingAngle: 0)
//MAP POSITION WITH DIFERENTS LAYERS
mapView.camera = GMSCameraPosition(target: CLLocationCoordinate2D(latitude: 39.59955969890008, longitude: -0.6421281303940684), zoom: 18.0, bearing: 0, viewingAngle: 0)
let WFS_JSON = "http://192.168.5.57:8080/geoserver/LordWor/wfs?service=WFS&version=1.0.0&request=GetFeature&typeName=LordWor:hemav-fincas&maxFeatures=1721&outputFormat=json"
if allFields.isEmpty {
let mapsFacade = MapsFacade()
mapsFacade.coordinatesWFS(url: WFS_JSON,
callbackFuncionOK: coordinatesWFSOK,
callbackFunctionERROR: coordinatesWFSOKERROR)
}
}
func coordinatesWFSOK( WFS_Response: WFSModel) {
let fields = WFS_Response.copyFieldswfs()
wfs = WFS_Response
for feature in 1...(wfs.features.count) {
//MARK: INSERT DATA FIELDS
DataBaseManagement.shared.addFields(inputPropertyIDFarming : wfs.features[feature - 1].properties.propertyIDFarming,
inputPropertyProducer : wfs.features[feature - 1].properties.propertyProducer,
inputPropertyVariety : wfs.features[feature - 1].properties.propertyVariety,
inputPropertyLand : wfs.features[feature - 1].properties.propertyLand)
for parcel in 1...(wfs.features[feature - 1].geometry.coordinates.count) {
if wfs.features[feature - 1].geometry.coordinates[parcel - 1].count == 1{//MARK: Without Hole
for poligon in 1...(wfs.features[feature - 1 ].geometry.coordinates[parcel - 1].count) {
//MARK: INSERT DATA FIELDS
DataBaseManagement.shared.addParcels(inputId_field: feature, inputCoordinatesJSON: String(describing: wfs.features[feature - 1].geometry.coordinates[0][0]))
}
}else{
for id in 1...(wfs.features[feature - 1].geometry.coordinates[parcel - 1].count) {//MARK: With Hole
if id == 1{
//MARK: INSERT COOERDENATES PARCEL
DataBaseManagement.shared.addParcels(inputId_field: feature, inputCoordinatesJSON: String(describing: wfs.features[feature - 1].geometry.coordinates[0][0]))
}else{
//MARK: this row contains all points for create a hole
//DataBaseManagement.shared.addHoles(inputId_hole: parcel, inputCoordinatesJSON: String(describing: wfs.features[feature - 1].geometry.coordinates[0][id - 1]))
//print("-------FIN PARCELA HOLE \(id - 1)---------")
}
/*for poligon in 0...(wfs.features[feature].geometry.coordinates[coordinate][id].count - 1 ) {
if id == 0{//First polygon is all field without holes
let longitude:Double = wfs.features[feature].geometry.coordinates[coordinate][id][poligon][0]
let latitude:Double = wfs.features[feature].geometry.coordinates[coordinate][id][poligon][1]
rect.add(CLLocationCoordinate2D(latitude: latitude, longitude: longitude))
}else{
//let insertHole = DataBaseManagement.shared.addParcels(inputId_field: poligon, inputCoordinatesJSON: String(describing: wfs.features[feature].geometry.coordinates))
let longitude:Double = wfs.features[feature].geometry.coordinates[coordinate][id][poligon][0]
let latitude:Double = wfs.features[feature].geometry.coordinates[coordinate][id][poligon][1]
hole.add(CLLocationCoordinate2D(latitude: latitude, longitude: longitude))
holes.append(hole)
}
}*/
}
}
}
}
//MARK: Get all group of Parcels
if allFields.count == 0 {
allFields = DataBaseManagement.shared.showAllFields()
total_parcels = DataBaseManagement.shared.showAllParcels()
}
drawFields()
}
func deleteAllParcels(){
for i in 0...total_parcels.count - 1 {
DataBaseManagement.shared.deleteAllParcels(inputId: i)
}
}
func deleteAllFields(){
for i in 0...allFields.count - 1 {
DataBaseManagement.shared.deleteAllFields(inputId: i)
}
}
func drawFields(){
//MARK: Field All Array wiht all (properrties for field and yours parcels)
for i in 0...allFields.count - 1{
let arr = try! JSONSerialization.jsonObject(with: total_parcels[i]._json_Parcel.data(using: .utf8)!, options: []) as! [[Double]]
allFields[i]._parcel.append(total_parcels[i]._json_Parcel);
//MARK: SAVE LATITUDE AND LONGITUDE IN ARRAY
for j in 0...arr.count - 1{
let longitude = arr[j][0]//latitud
let latitude = arr[j][1]//longitud
rect.add(CLLocationCoordinate2D(latitude: latitude, longitude: longitude))
}
//MARK: DRAW ON THE MAP
let polygon = GMSPolygon()
polygon.path = rect
poligons.append(polygon)
rect = GMSMutablePath()
polygon.fillColor = UIColor(red: 8/256, green: 246/255, blue: 191/255, alpha: 0.3)
polygon.strokeColor = .blue
polygon.strokeWidth = 2
polygon.map = mapView
}
let end = NSDate()
self.timer.stopAnimating()
print("TIME CHARGE 'MAIN MAP'")
print(start)
print(end)
}
let urlSnapshot = "..."
func getDeliverablesForField(){
let deliverablesFacade = DeliverablesFacade()
deliverablesFacade.snapshots(url: urlSnapshot,
callbackFuncionOK: snapshotsOK,
callbackFunctionERROR: snapshotsERROR)
}
func snapshotsOK( snapshotsResponse: SnapshotsLegendModel) {
snapShotsLegend = snapshotsResponse.copySnapshots()
print("end recover fields")
}
func snapshotsERROR(_ httpCode: Int,nsError: NSError) {
if httpCode == -1 {
print(nsError)
print(httpCode)
}else{
print(nsError)
print(httpCode)
}
}
var onlyOnetime = 0
func mapView(_ mapView: GMSMapView, didTapAt coordinate: CLLocationCoordinate2D) {
for polygon in poligons{
if (GMSGeometryContainsLocation(CLLocationCoordinate2D(latitude: coordinate.latitude, longitude: coordinate.longitude), polygon.path!, true)) {
onlyOnetime = onlyOnetime + 1
if onlyOnetime == 1{
getDeliverablesForField()
showLegend.setValue(true, forKey: showLegendInformation)
let bounds = GMSCoordinateBounds(path: polygon.path!)
self.mapView!.animate(with: GMSCameraUpdate.fit(bounds, withPadding: 15.0))
self.iconBarLegend.isEnabled = true
self.iconBarLegend.tintColor = UIColor.black
}
polygon.fillColor = UIColor(red: 8/256, green: 246/255, blue: 191/255, alpha: 0.9)
polygon.strokeColor = .blue
polygon.strokeWidth = 2
polygon.map = mapView
//self.viewDidLoad()
}
else{
polygon.fillColor = UIColor(red: 8/256, green: 246/255, blue: 191/255, alpha: 0.3)
polygon.strokeColor = .blue
polygon.strokeWidth = 2
polygon.map = mapView
}
}
}
func coordinatesWFSOKERROR(_ httpCode: Int,nsError: NSError) {
if httpCode == -1 {
print(nsError)
print(httpCode)
}else{
print(nsError)
print(httpCode)
}
}
@IBAction func goToAdvancedSearch(_ sender: Any) {
let advancedSearch: AdvancedSearchVC = UIStoryboard(name: "AdvancedSearch", bundle: nil).instantiateViewController(withIdentifier: "AdvancedSearchVC") as! AdvancedSearchVC
self.navigationController?.pushViewController(advancedSearch, animated: false)
}
}
扩展名MainMapVC:LeftSideDelegate {
func sendShapeDelivery(deliveryPos : Int){
print("Not exist deliverable -> call WMS")
let nameDelivery = snapShotsLegend.legendEntries[0].deliverables[deliveryPos].url_layer
let urls: GMSTileURLConstructor = { (x: UInt, y: UInt, zoom: UInt) -> URL in
let bbox = self.layer.bboxFromXYZ(x, y: y, z: zoom)
let urlKN = "http://192.168.5.57:8080/geoserver/LordWor/wms?SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&FORMAT=image%2Fpng&TRANSPARENT=true&tiled=true&STYLES=line&layers=LordWor:\(nameDelivery)&styles=&WIDTH=256&HEIGHT=256&SRS=EPSG:3857&BBOX=\(bbox.left),\(bbox.bottom),\(bbox.right),\(bbox.top)"
print("PETICION WMS DEL LALER: \(nameDelivery)")
return URL(string: urlKN)!
}
let tileLayer: GMSURLTileLayer = GMSURLTileLayer(urlConstructor: urls)
allDeliveries.append(tileLayer)
tileLayer.opacity = 0.5
tileLayer.map = mapView
}
}
答案 0 :(得分:0)
出现错误是因为delegate
为nil
。我在初始化它的代码中看不到。您应该传递其他viewController
并将其设置为delegate
。
此外,宣布像这样的代表更安全:
weak var delegate: LeftSideDelegate?
(weak
部分是为了防止内存保留周期)
然后像这样使用它:
if let delegate = delegate {
delegate.sendShapeDelivery(deliveryPos: (indexPath?.row)!)
}
这样应用程序不会崩溃。
答案 1 :(得分:0)
内部类MainMapVC,在行
之后menu_vc = self.storyboard?.instantiateViewController(withIdentifier: "LeftSideViewController") as! LeftSideViewController
您必须设置其委托,如下所示:
menu_vc.delegate = self