Found nil while unwrapping an Optional value, Error - ios

I don't know where that optional is. please help! I really need this, I haven't used optional values in my code.
import UIKit
class ViewController: UIViewController {
//this is the outlet for the sliders RGB values
#IBOutlet weak var redSlider: UISlider!
#IBOutlet weak var greenSlider: UISlider!
#IBOutlet weak var blueSlider: UISlider!
//this are the outlets for the labels
#IBOutlet weak var redLabelValue: UILabel!
#IBOutlet weak var greenLabelValue: UILabel!
#IBOutlet weak var blueLabelValue: UILabel!
#IBOutlet weak var hexColor: UILabel!
func changeThumbImage() {
let redThumbImage = UIImage(named: "RedThumb#3x")
redSlider.setThumbImage(redThumbImage, forState: .Normal)
let greenThumbImage = UIImage(named: "GreenThumb#3x")
greenSlider.setThumbImage(greenThumbImage, forState: .Normal)
let blueThumbImage = UIImage(named: "BlueThumb#3x")
blueSlider.setThumbImage(blueThumbImage, forState: .Normal)
}
func colorValues() {
var roundedRed = UInt32(redSlider.value)
var roundedGreen = UInt32(greenSlider.value)
var roundedBlue = Int32(blueSlider.value)
//converts the slider value to a string
redLabelValue.text = String(stringInterpolationSegment: roundedRed)
greenLabelValue.text = String(stringInterpolationSegment: roundedGreen)
blueLabelValue.text = String(stringInterpolationSegment: roundedBlue)
}
func rgbValues() {
var redValue = Int(redSlider.value)
var greenValue = Int(greenSlider.value)
var blueValue = Int(blueSlider.value)
}
//VIEW DID LOAD
override func viewDidLoad() {
super.viewDidLoad()
updateBackgroundColor()
colorValues()
changeThumbImage()
redSlider = UISlider(frame: CGRect(x: 100,y: 100,width: 200,height: 25))
func getRandomColor() -> UIColor{
let uniformRed = UInt32(redSlider.value)
let uniformGreen = UInt32(greenSlider.value)
let uniformBlue = UInt32(blueSlider.value)
var randomRed:CGFloat = CGFloat(arc4random_uniform(uniformRed))
var randomGreen:CGFloat = CGFloat(arc4random_uniform(uniformGreen))
var randomBlue:CGFloat = CGFloat(arc4random_uniform(uniformBlue))
return UIColor(red: randomRed, green: randomGreen, blue: randomBlue, alpha: 1.0)
}
//view.backgroundColor = getRandomColor()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func updateBackgroundColor() {
colorValues()
//constant to set the value of the slider to a CGFloat
let redValue = CGFloat(redSlider.value/255)
let greenValue = CGFloat(greenSlider.value/255)
let blueValue = CGFloat(blueSlider.value/255)
//set the RGBA values
view.backgroundColor = UIColor(red: redValue, green: greenValue, blue: blueValue, alpha: 1)
//get the hexadecimal value from the RGB color values
let hexValue = String(format:"%02X", Int(redSlider.value)) + String(format:"%02X", Int(greenSlider.value)) + String(format:"%02X", Int(blueSlider.value))
hexColor.text = "#\(hexValue)"
}
//get rid of status bar
override func prefersStatusBarHidden() -> Bool {
return true
}
}

Well, first off, all of your outlets could potentially be nil at some point, so a good start would be adding ? to optionally unwrap them all. If you do this, it will just do nothing instead of crash in the case that the Optional is nil. Below I went through and added this to some of your code, but you may need to add a few more ? to other optionals I overlooked. Another way to do this is to use if-let unwrapping, which will reduce the amount of "?", but increase the amount of nesting.
func changeThumbImage() {
let redThumbImage = UIImage(named: "RedThumb#3x")
redSlider?.setThumbImage(redThumbImage, forState: .Normal)
let greenThumbImage = UIImage(named: "GreenThumb#3x")
greenSlider?.setThumbImage(greenThumbImage, forState: .Normal)
let blueThumbImage = UIImage(named: "BlueThumb#3x")
blueSlider?.setThumbImage(blueThumbImage, forState: .Normal)
}
////
func colorValues() {
var roundedRed = UInt32(redSlider.value)
var roundedGreen = UInt32(greenSlider.value)
var roundedBlue = Int32(blueSlider.value)
//converts the slider value to a string
redLabelValue?.text = String(stringInterpolationSegment: roundedRed)
greenLabelValue?.text = String(stringInterpolationSegment: roundedGreen)
blueLabelValue?.text = String(stringInterpolationSegment: roundedBlue)
}
Also use if-let here to safely unwrap the sliders...
#IBAction func updateBackgroundColor() {
colorValues()
if let red = redSlider, green = greenSlider, blue = blueSlider{
let redValue = CGFloat(red.value/255)
let greenValue = CGFloat(green.value/255)
let blueValue = CGFloat(blue.value/255)
//set the RGBA values
view.backgroundColor = UIColor(red: redValue, green: greenValue, blue: blueValue, alpha: 1)
//get the hexadecimal value from the RGB color values
let hexValue = String(format:"%02X", Int(redSlider.value)) + String(format:"%02X", Int(greenSlider.value)) + String(format:"%02X", Int(blueSlider.value))
hexColor?.text = "#\(hexValue)"
}
}

Related

UITableViewCell constraints not updated till I scroll tableview

Following is my code to update view height inside tableview cell
override func layoutSubviews() {
super.layoutSubviews()
layout()
}
fileprivate func layout() {
rootFlexContainer.frame.size.width = frame.width - 20
rootFlexContainer.flex.layout(mode: .adjustHeight)
if(rootFlexContainer.frame.height != 0) {
tagsHeight.constant = rootFlexContainer.frame.height
}
}
although this is not reflected till I scroll i.e is cell is recreated. How to update constraint inside TableViewCell of a view?
here is entire tableviewcell code
import UIKit
import FlexLayout
import SDWebImage
class StoreListTableViewCell: UITableViewCell {
#IBOutlet weak var menuLbl: UILabel!
#IBOutlet weak var menuView: UIView!
#IBOutlet weak var cellBgview: UIView!
#IBOutlet weak var storeImg: UIImageView!
#IBOutlet weak var storeLocation: UILabel!
#IBOutlet weak var storeTitle: UILabel!
#IBOutlet weak var cellContainer: UIView!
#IBOutlet weak var stackView: UIStackView!
#IBOutlet weak var tagsHeight: NSLayoutConstraint!
var storeImgStr = ""
var storeTitleStr = ""
var storeLocationStr = ""
var score : Double = 0.0
var tagsStr = ""
var isMenuAvailble = 0
var retailerTags: [String]?
var cashbackString = ""
fileprivate let rootFlexContainer = UIView()
#IBOutlet weak var tagsView: UIView!
#IBOutlet weak var ratingBtn: UIButton!
override func awakeFromNib() {
super.awakeFromNib()
self.layoutIfNeeded()
cellBgview.clipsToBounds = true
cellBgview.layer.cornerRadius = 5
cellContainer.layer.shadowColor = UIColor.lightGray.cgColor
cellContainer.layer.shadowOpacity = 0.5
cellContainer.layer.shadowRadius = 5.0
cellContainer.layer.shadowOffset = CGSize(width: 0, height: 2)
cellContainer.backgroundColor = UIColor.clear
cellContainer.layer.cornerRadius = 5.0
cellContainer.layer.borderColor = UIColor.white.cgColor
cellContainer.layer.borderWidth = 0.5
ratingBtn.layer.borderWidth = 1
ratingBtn.layer.cornerRadius = 5
tagsView.addSubview(rootFlexContainer)
//cellContainer.layer.shadowPath = UIBezierPath(rect: cellBgview.bounds).cgPath
}
func setSetupStoreUI() {
if isMenuAvailble == 1 {
menuView.isHidden = false
menuView.layer.cornerRadius = 10
} else {
menuView.isHidden = true
}
storeTitle.text = storeTitleStr
// storeTitle.sizeToFit()
storeLocation.text = storeLocationStr
//storeLocation.sizeToFit()
//.filter{ $0.name != " " }
//storeImg.sd_imageIndicator = SDWebImageActivityIndicator.gray
storeImg.backgroundColor = UIColor.hexStringToUIColor(hex: AppStrings.placeHolderColor)
if let url = URL(string: storeImgStr.encoded), !(storeImgStr.isEmpty) {
self.storeImg.sd_setImage(with: url)
}
menuLbl.text = AppLocalString.PREORDER_TEXT.localized()
menuLbl.font = FontStyle.ProximaNovaBold(size: 12)
storeTitle.font = FontStyle.ProximaNovaSemibold(size: 14)
storeLocation.font = FontStyle.ProximaNovaRegular(size: 12)
storeLocation.textColor = .gray
// ratingBtn.isHidden = (score == 0)
ratingBtn.setTitle(score == 0 ? "-" : String(format: "%.1f", score), for: .normal)
ratingBtn.backgroundColor = UIColor.hexStringToUIColor(hex: Utility.getRatingColor(rating: score))
ratingBtn.layer.borderColor = UIColor.hexStringToUIColor(hex: Utility.getRatingColor(rating: score)).cgColor
rootFlexContainer.subviews.forEach({ $0.removeFromSuperview() })
//tagsView.willRemoveSubview(rootFlexContainer)
//rootFlexContainer.frame = tagsView.frame
//tagsView.addSubview(rootFlexContainer)
rootFlexContainer.flex.direction(.row).wrap(.wrap).alignSelf(.auto).justifyContent(.start).paddingRight(2).define { (flex) in
for i in 0..<((retailerTags?.count ?? 0) > 3 ? 3 : (retailerTags?.count ?? 0)) {
let nameLabel = UIButton()
nameLabel.isUserInteractionEnabled = false
nameLabel.setTitle((retailerTags?[i] ?? "").trim(), for: .normal)
nameLabel.setTitleColor(.black, for: .normal)
nameLabel.titleLabel?.font = FontStyle.ProximaNovaRegular(size: 11)
nameLabel.contentEdgeInsets = UIEdgeInsets(top: 1.5, left: 4, bottom: 1.5, right:4)
nameLabel.layer.borderColor = UIColor.hexStringToUIColor(hex: AppStrings.grayBorderColor).cgColor
nameLabel.layer.cornerRadius = 8
nameLabel.layer.borderWidth = 1.0
nameLabel.sizeToFit()
flex.addItem(nameLabel).margin(2)
}
if cashbackString != "" {
let cashbackLabel = UIButton()
cashbackLabel.backgroundColor = UIColor.hexStringToUIColor(hex: AppStrings.orangeCashbackColor)
cashbackLabel.isUserInteractionEnabled = false
cashbackLabel.setTitle(cashbackString, for: .normal)
cashbackLabel.setTitleColor(.black, for: .normal)
cashbackLabel.titleLabel?.font = FontStyle.ProximaNovaRegular(size: 10)
cashbackLabel.contentEdgeInsets = UIEdgeInsets(top: 1.5, left: 5, bottom: 1.5, right: 5)
cashbackLabel.layer.cornerRadius = 5
cashbackLabel.layer.borderWidth = 0
cashbackLabel.sizeToFit()
flex.addItem(cashbackLabel).margin(2)
}
}
rootFlexContainer.flex.layout()
if retailerTags?.count ?? 0 == 0 {
tagsView.isHidden = true
} else {
tagsView.isHidden = false
}
}
override func layoutSubviews() {
super.layoutSubviews()
layout()
}
fileprivate func layout() {
rootFlexContainer.frame.size.width = frame.width - 20
rootFlexContainer.flex.layout(mode: .adjustHeight)
if(rootFlexContainer.frame.height != 0) {
tagsHeight.constant = rootFlexContainer.frame.height
}
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
Following is view hierarchy from stroryboard
A few observations -
1. Unnecessary layoutIfNeeded() call inside awakeFromNib()
override func awakeFromNib() {
super.awakeFromNib()
/*
self.layoutIfNeeded() // Not Necessary, Remove it.
*/
// No other changes to current implementation
}
2. Following should not be necessary, remove it.
/* Not necessary, Remove it.
override func layoutSubviews() {
super.layoutSubviews()
layout()
}
fileprivate func layout() {
rootFlexContainer.frame.size.width = frame.width - 20
rootFlexContainer.flex.layout(mode: .adjustHeight)
if(rootFlexContainer.frame.height != 0) {
tagsHeight.constant = rootFlexContainer.frame.height
}
}
*/
3. In the method, where you populate all the details, make following changes
func setSetupStoreUI() {
// No changes to current implementation
/* Remove this, we will update later
rootFlexContainer.flex.layout()
*/
if retailerTags?.count ?? 0 == 0 {
tagsView.isHidden = true
} else {
tagsView.isHidden = false
}
// Copied as is from `layout()`
rootFlexContainer.frame.size.width = frame.width - 20
rootFlexContainer.flex.layout(mode: .adjustHeight)
if (rootFlexContainer.frame.height != 0) {
tagsHeight.constant = rootFlexContainer.frame.height
}
// do a manual layout (on contentView, NOT self)
self.contentView.layoutIfNeeded()
}
You have to tell the table view controller that your cell height has changed.
Most common methods are protocol/delegate pattern or (swift preferred) closures.
For example...
In your cell class:
class MyTableViewCell: UITableViewCell {
// "callback" closure
var cellHeightChanged: (()->())?
// whatever happens that you need to change the cell height
func heightChanged() -> Void {
tagsHeight.constant = rootFlexContainer.frame.height
cellHeightChanged?()
}
}
Then, in your controller, in cellForRowAt:
cell.cellHeightChanged = {
tableView.performBatchUpdates(nil, completion: nil)
}

Swift - not detect the event of moving the Slider in Custom Cell

I am developing an application in swift 3 with the following interface:
I have to add some details about the legend. The legend consists of two views (firstView and secondView). Where a default "layout" is 0, until we click on it and that is when the detail of the cell is opened. Bells, a legend like this appears:
Currently the slider send events are as follows:
The interface consists of two views. The map that is the view of the bottom ("MainMapVC") that if we make a "swipe" to the right appears the legend of the map "LefSideViewController" formed by custom cells ("customCell").
I enclose the code of the three classes:
The "customCell":
import UIKit
protocol customCellDelegate {
func didTappedSwicht(cell: customCell)
func didMoveSlider(cell: customCell)
}
class customCell: UITableViewCell {
//MARK: OUTLETS VIEW 1
#IBOutlet weak var firstView: UIView!
#IBOutlet weak var firstViewLabel: UILabel!
#IBOutlet weak var swichtActiveLayer: UISwitch!
//MARK: OUTLETS VIEW 2
#IBOutlet weak var secondView: UIView!
#IBOutlet weak var secondViewLabel: UILabel!
#IBOutlet weak var secondHeightConstraint: NSLayoutConstraint!
#IBOutlet weak var idDeliveryResponse: UILabel!
#IBOutlet weak var minRangeDeliveryResponse: UILabel!
#IBOutlet weak var maxRangeDeliveryResponse: UILabel!
#IBOutlet weak var initialMinDeliveryResponse: UILabel!
#IBOutlet weak var initialMaxDeliveryResponse: UILabel!
#IBOutlet weak var sliderOpacity: UISlider!
// MARK: VARIABLES
var delegate: customCellDelegate!
override func awakeFromNib() {
super.awakeFromNib()
}
func setupWithModel(model: deliveriesLeftTableModel){
firstViewLabel.text = model.firstViewLabel
secondViewLabel.text = model.secondViewLabel
idDeliveryResponse.text = model.idDeliveryResponse
minRangeDeliveryResponse.text = model.minRangeDeliveryResponse
maxRangeDeliveryResponse.text = model.maxRangeDeliveryResponse
initialMinDeliveryResponse.text = model.initialMinDeliveryResponse
initialMaxDeliveryResponse.text = model.initialMaxDeliveryResponse
swichtActiveLayer.setOn(model.swichtActiveLayer, animated: true)
sliderOpacity.value = model.sliderOpacity
}
#IBAction func swichtValueChanged(_ sender: Any) {
delegate.didTappedSwicht(cell: self)
}
#IBAction func primaryActionTrigger(_ sender: Any){
print("primaryActionTrigger")
}
#IBAction func touchUpInside(_ sender: Any){
print("touchUpInside")
}
/*#IBAction func sliderValueChanged(_ sender: Any) {
delegate.didMoveSlider(cell: self)
}*/
var showsDetails = false {
didSet {
secondHeightConstraint.priority = showsDetails ? 250 : 900
}
}
}
 
The "LefSideViewController" is:
import UIKit
protocol customCellDelegate {
func didTappedSwicht(cell: customCell)
func didMoveSlider(cell: customCell)
}
class customCell: UITableViewCell {
//MARK: OUTLETS VIEW 1
#IBOutlet weak var firstView: UIView!
#IBOutlet weak var firstViewLabel: UILabel!
#IBOutlet weak var swichtActiveLayer: UISwitch!
//MARK: OUTLETS VIEW 2
#IBOutlet weak var secondView: UIView!
#IBOutlet weak var secondViewLabel: UILabel!
#IBOutlet weak var secondHeightConstraint: NSLayoutConstraint!
#IBOutlet weak var idDeliveryResponse: UILabel!
#IBOutlet weak var minRangeDeliveryResponse: UILabel!
#IBOutlet weak var maxRangeDeliveryResponse: UILabel!
#IBOutlet weak var initialMinDeliveryResponse: UILabel!
#IBOutlet weak var initialMaxDeliveryResponse: UILabel!
#IBOutlet weak var sliderOpacity: UISlider!
// MARK: VARIABLES
var delegate: customCellDelegate!
override func awakeFromNib() {
super.awakeFromNib()
}
func setupWithModel(model: deliveriesLeftTableModel){
firstViewLabel.text = model.firstViewLabel
secondViewLabel.text = model.secondViewLabel
idDeliveryResponse.text = model.idDeliveryResponse
minRangeDeliveryResponse.text = model.minRangeDeliveryResponse
maxRangeDeliveryResponse.text = model.maxRangeDeliveryResponse
initialMinDeliveryResponse.text = model.initialMinDeliveryResponse
initialMaxDeliveryResponse.text = model.initialMaxDeliveryResponse
swichtActiveLayer.setOn(model.swichtActiveLayer, animated: true)
sliderOpacity.value = model.sliderOpacity
}
#IBAction func swichtValueChanged(_ sender: Any) {
delegate.didTappedSwicht(cell: self)
}
#IBAction func sliderValueChanged(_ sender: Any) {
delegate.didMoveSlider(cell: self)
}
var showsDetails = false {
didSet {
secondHeightConstraint.priority = showsDetails ? 250 : 900
}
}
}
And the last one "MainMapVC":
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] = [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
menu_vc.delegate = self
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.0.160: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)---------")
}
}
}
}
}
//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)
}
}
extension MainMapVC: LeftSideDelegate {
func sendShapeDelivery(deliveryPos : Int){
if feedModelDeliveries[deliveryPos].swichtActiveLayer == true {
if true {
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.0.160: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 = self.mapView
}else{
let tileLayer: GMSURLTileLayer = allDeliveries[deliveryPos]
tileLayer.opacity = 0.5
tileLayer.map = self.mapView
}
}else{
let tileLayer: GMSURLTileLayer = allDeliveries[deliveryPos]
tileLayer.opacity = 0
tileLayer.map = self.mapView
}
}
}
The application communicates with protocols and delegates. For example, when we click on the swicht of the legend, the class "customCell" is able to detect the event "swichtValueChanged" and send it to a "didTappedSwicht" delegate of "LeftSideViewController", but when we move the slider the "customCell" class is not Able to detect the event "sliderValueChanged" and takes the event to close the view (because the legend on the left is closed with a swipe on the left).
How can I make it to detect the event of the slider and not to close the view?
Thank you
You should bind your Slider with two Events "Primary Action Triggered" and "Touch Up Inside"
Here I attached Image for your reference
and remove left swipe and right swipe gesture on this method
Method Description and code
1 "Primary Action Triggered"
When You click on slider the method will call "Primary Action Triggered"
Note : Disable your gesture
(UISwipeGestureRecognizerDirection.right and UISwipeGestureRecognizerDirection.left)
2 Touch Up Inside
Note : Enable your gesture both gesture
(UISwipeGestureRecognizerDirection.right and UISwipeGestureRecognizerDirection.left)

ScrollView + PageControl doesn't scroll

I have that code:
import UIKit
class ProjectsViewController: UIViewController, UIScrollViewDelegate {
#IBOutlet weak var pageControlBookChapters: UIPageControl!
#IBOutlet weak var scrollViewBookChapters: UIScrollView!
#IBOutlet weak var contentsImageView: UIImageView!
#IBOutlet weak var contentsTextLabel: UILabel!
#IBOutlet weak var contentsLabel: UILabel!
#IBOutlet weak var projectName: UILabel!
#IBOutlet weak var projectImageView: UIImageView!
var page = 0
let arrImages : [String] = ["Captura1.jpg", "captura 2.jpg", "captura 3.jpg", "captura 4.jpg", "captura 5.jpg"];
override func viewDidLoad() {
super.viewDidLoad()
self.createHelpView()
pageControlBookChapters.backgroundColor = UIColor.clearColor()
pageControlBookChapters.pageIndicatorTintColor = UIColor.lightGrayColor()
pageControlBookChapters.currentPageIndicatorTintColor = UIColor(red: 251/255, green: 108/255, blue: 108/255, alpha: 1.0)
pageControlBookChapters.tintAdjustmentMode = UIViewTintAdjustmentMode.Dimmed
pageControlBookChapters.numberOfPages = arrImages.count
pageControlBookChapters.currentPage = 0
scrollViewBookChapters.scrollEnabled = true
scrollViewBookChapters.alwaysBounceHorizontal = true
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func createHelpView() {
var x = 50
for var i=0; i<arrImages.count; i++ {
var imgView = UIImageView(frame: CGRectMake(CGFloat(x), 50, CGFloat(scrollViewBookChapters.frame.width-100), CGFloat(scrollViewBookChapters.frame.height-150)))
imgView.autoresizingMask = UIViewAutoresizing.FlexibleBottomMargin
imgView.backgroundColor = UIColor.clearColor()
imgView.image = UIImage(named: arrImages[i])
imgView.contentMode = UIViewContentMode.ScaleAspectFit
scrollViewBookChapters.addSubview(imgView)
x = x + Int(scrollViewBookChapters.frame.width)
}
scrollViewBookChapters.contentSize = CGSizeMake(CGFloat(arrImages.count)*self.view.frame.width, 0)
}
func scrollViewDidScroll(scrollView: UIScrollView) {
var pageWidth = CGFloat(scrollViewBookChapters.frame.width)
var fractionalPage = scrollViewBookChapters.contentOffset.x / pageWidth
page = lround(CDouble(fractionalPage))
pageControlBookChapters.currentPage = page
}
}
Which correctly creates the scrollview and dots of the pagecontrol, but when I try to scroll it, it doesn't move, just shows the line to scroll, but even if I click on the dot button it doesn't do anything. Is something wrong there? I have even declared the scrollEnabled and bounces horizontally to force it, but nothing happens.
I have already checked the contentSize and seems to work properly.

Swift UIView custom view won't update after ViewController action

I want the stepper in the View Controller to update the color in my custom UIView every time it is clicked. I'm not sure if the problem is due to the instance of the class or that the values of the variables (redd1, greenn1, and bluee1) are not being changed.
This is my first file:
class ViewController: UIViewController {
var colors = UIView1();
#IBOutlet var redStepper: UIStepper!
#IBOutlet var greenStepper: UIStepper!
#IBOutlet var blueStepper: UIStepper!
#IBAction func redChange(sender: UIStepper)
{
redValue.text = Int(sender.value).description;
colors.redd1 = Double(sender.value);
//self.view.setNeedsDisplay()
}
#IBAction func greenChange(sender: UIStepper)
{
greenValue.text = Int(sender.value).description;
colors.greenn1 = Double(sender.value);
//self.view.setNeedsDisplay()
}
#IBAction func blueChange(sender: UIStepper)
{
blueValue.text = Int(sender.value).description;
colors.bluee1 = Double(sender.value);
//self.view.setNeedsDisplay()
}
}
This is my second file:
class UIView1: UIView {
var redd1 = 0.0;
var greenn1 = 0.0;
var bluee1 = 0.0;
override init(frame: CGRect)
{
super.init(frame: frame)
}
required init?(coder aDecoder: NSCoder)
{
super.init(coder: aDecoder)
}
override func drawRect(rect: CGRect)
{
let circle = UIView(frame: CGRect(x: -75.0, y: -40.0, width: 200.0, height: 200.0))
circle.layer.cornerRadius = 50.0;
let startingColor = UIColor(red: (CGFloat(redd1))/255, green: (CGFloat(greenn1))/255, blue: (CGFloat(bluee1))/255, alpha: 1.0)
circle.backgroundColor = startingColor;
addSubview(circle);
}
}
drawRect is only called when the view is being added, so in your example, drawRect is called once, and not after changing the stepper.
Instead, change your stepper file to:
#IBOutlet var redStepper: UIStepper!
#IBOutlet var greenStepper: UIStepper!
#IBOutlet var blueStepper: UIStepper!
#IBAction func redChange(sender: UIStepper) {
redValue.text = Int(sender.value).description;
colors.redd1 = Double(sender.value);
updateColor()
}
#IBAction func greenChange(sender: UIStepper) {
greenValue.text = Int(sender.value).description;
colors.greenn1 = Double(sender.value);
updateColor()
}
#IBAction func blueChange(sender: UIStepper) {
blueValue.text = Int(sender.value).description;
colors.bluee1 = Double(sender.value);
updateColor()
}
And then add the updateColor function to your UIView1 class:
class UIView1: UIView {
var redd1 = 0.0;
var greenn1 = 0.0;
var bluee1 = 0.0;
func updateColor() {
let circle = UIView(frame: CGRect(x: -75.0, y: -40.0, width: 200.0, height: 200.0))
circle.layer.cornerRadius = 50.0;
let startingColor = UIColor(red: (CGFloat(redd1))/255, green: (CGFloat(greenn1))/255, blue: (CGFloat(bluee1))/255, alpha: 1.0)
circle.backgroundColor = startingColor;
addSubview(circle);
}
}

Cannot convert value of type 'Float' to expected argument 'CGFloat'

I have searched for an answer to this for a while now.
I am an absolute noob when it comes to coding in general, but i figured i'd try my hand at it.
I am trying to write some code to change a color of a view using 3(three) sliders (R,G,B).
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var colorView: UIView!
#IBOutlet weak var redSlider: UISlider!
#IBAction func redValueChanged(sender: UISlider) {
var red = CGFloat(sender.value)
displayColors()
}
#IBOutlet weak var greenSlider: UISlider!
#IBAction func greenValueChanged(sender: UISlider) {
var green = CGFloat(sender.value)
displayColors()
}
#IBOutlet weak var blueSlider: UISlider!
#IBAction func blueValueChanged(sender: UISlider) {
var blue = CGFloat(sender.value)
displayColors()
}
func displayColors(){
let red = CGFloat(redSlider.value)
let blue = CGFloat(blueSlider.value)
let green = CGFloat(greenSlider.value)
let color = UIColor(
red: red,
green: green,
blue: blue,
alpha: 1.0)
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
colorView.backgroundColor = UIColor(red: redSlider.value, green: greenSlider.value, blue: blueSlider.value, alpha: 1.0)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
However, i get an error on the following line:
colorView.backgroundColor = UIColor(red: redSlider.value, green: greenSlider.value, blue: blueSlider.value, alpha: 1.0)
The error is:
Cannot convert value of type 'Float' to expected argument type
'CGFloat'
I know that there is a very simple solution, however, since I'm such a noob, i can't come up with the solution.
Any help would be appreciated.
CGFloat and Float are technically different types. The Swift programming language does not do any numeric type conversion / coercion. As such, you must explicitly convert from Float to CGFloat using one of the constructors on CGFloat.
colorView.backgroundColor = UIColor(red: CGFloat(redSlider.value), green: CGFloat(greenSlider.value), blue: CGFloat(blueSlider.value), alpha: 1.0)
You can read more about Numeric Type Conversion in The Swift Programming Language.
You get this error since xxxSlider.value is of type Float, whereas UIColor initialiser calls for type CGFloat for all four arguments.
You can redeem this error by changing the line into:
colorView.backgroundColor = UIColor(red: CGFloat(redSlider.value), green: CGFloat(greenSlider.value), blue: CGFloat(blueSlider.value), alpha: 1.0)
However, to achieve the goal of your program, there are more issues that needs to be addressed. I'll go through these below.
First of all, you have one #IBAction as well as one #IBOutlet connected to each slider. With former (action), the latter is really not needed. Hence, remove the #IBOutlet connections (code as well as connections)
#IBOutlet weak var redSlider: UISlider! // remove (also remove connection)
#IBOutlet weak var greenSlider: UISlider! // ...
#IBOutlet weak var blueSlider: UISlider! // ...
Now, in your #IBAction:s, you define a local variable that is never used
var red = CGFloat(sender.value) // in #IBAction func redValueChanged(...
var green = CGFloat(sender.value) // ...
var blue = CGFloat(sender.value) // ...
In their current form, you don't need these, so remove these also.
Instead, in the scope of the class (see full program below), declare three class variables to hold the current value of each slide (note: these are not to be defined within a class method/action/function). Moreover, let these be of type CGFloat rather than Float, as initialiser of UIColor that we use to change background colour takes arguments of type CGFloat:
var redValue: CGFloat = 0.5 // 0.5: middle slider (init)
var greenValue: CGFloat = 0.5
var blueValue: CGFloat = 0.5
In your #IBAction closures, change these class variables by the sender.value (which holds slider value). After update of variable value, call your displayColors() method (that we will look at shortly).
// Actions
#IBAction func redValueChanged(sender: UISlider) {
redValue = CGFloat(sender.value)
displayColors()
}
#IBAction func greenValueChanged(sender: UISlider) {
greenValue = CGFloat(sender.value)
displayColors()
}
#IBAction func blueValueChanged(sender: UISlider) {
blueValue = CGFloat(sender.value)
displayColors()
}
Your displayColors() can be simplified simply to:
func displayColors() {
colorView.backgroundColor = UIColor(red: redValue, green: greenValue, blue: blueValue, alpha: 1.0)
}
Finally, not that the overridden method viewDidLoad() is only called once when the ViewController is loaded, so in this case, you can see this as an initialiser for your ViewController. The only thing we want to do here is set the default colour: RGB(0.5, 0.5, 0.5) = gray.
override func viewDidLoad() {
super.viewDidLoad()
// Initial BG color (viewDidLoad() loads only once when ViewController view loads)
colorView.backgroundColor = UIColor(red: redValue, green: greenValue, blue: blueValue, alpha: 1.0)
}
And we're done!
Wrapping it up, your ViewController class should now look like the following
import UIKit
class ViewController: UIViewController {
// Properties
var redValue: CGFloat = 0.5
var greenValue: CGFloat = 0.5
var blueValue: CGFloat = 0.5
#IBOutlet weak var colorView: UIView!
// Actions
#IBAction func redValueChanged(sender: UISlider) {
redValue = CGFloat(sender.value)
displayColors()
}
#IBAction func greenValueChanged(sender: UISlider) {
greenValue = CGFloat(sender.value)
displayColors()
}
#IBAction func blueValueChanged(sender: UISlider) {
blueValue = CGFloat(sender.value)
displayColors()
}
func displayColors() {
colorView.backgroundColor = UIColor(red: redValue, green: greenValue, blue: blueValue, alpha: 1.0)
}
override func viewDidLoad() {
super.viewDidLoad()
// Initial BG color (viewDidLoad() loads only once when ViewController view loads)
colorView.backgroundColor = UIColor(red: redValue, green: greenValue, blue: blueValue, alpha: 1.0)
}
}
Running your app produces the following behaviour:
In my app using Swift 4, I am using this to convert Float to CGFloat:
let slider = sender as? UISlider
let val = CGFloat((slider?.value)!)
And then using the variable val as needed, which in my case is for hue, saturation and brightness, e.g.
coolButton.saturation = val

Resources