Неправильная отрисовка экрана

ios

#1

Здравствуйте.
Пытаюсь написать приложение отображающим координаты GPS.
Но к несчастью при работе приложения на экране вылезают вот такие артефакты как на картинке.

Изучаю swift совсем недавно, даже не представляю в какую сторону копать для решения проблемы. =(

Алгоритм программы следующий: 1) Получаем координаты 2) форматируем 3) преобразуем в текст 4) присваиваем label.text = обработанный текст.

import UIKit

import CoreLocation

class ViewController: UIViewController, CLLocationManagerDelegate {

private let locationManager = CLLocationManager()

@IBOutlet var latitudeLabel: UILabel!
@IBOutlet var longitudeLabel: UILabel!

override func viewDidLoad() {
    super.viewDidLoad()
    
    locationManager.delegate = self
    locationManager.desiredAccuracy = kCLLocationAccuracyBest
    locationManager.requestWhenInUseAuthorization()
    
}  // closing "viewDidLoad"

func locationManager (_ manager:CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
    print("Authorization status changed to \(status.rawValue)")
    switch status {
    case .authorizedAlways, .authorizedWhenInUse:
        locationManager.startUpdatingLocation()
    default:
        locationManager.stopUpdatingLocation()
    } // closing "switch"
} // closing locationManager/ChangeAuthorization

func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {

// let alertController = UIAlertController (title: “Location Manager Error”, message: “Unknown Error”, preferredStyle: .alert)
// let okAction = UIAlertAction (title: “OK”, style: .cancel, handler: {acttion in })
// alertController.addAction (okAction)
// present (alertController, animated: true, completion: nil)
} // closing “locationManager/FailWithError”

func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
    if let newLocation = locations.last {
        let latitudeRawString = String(newLocation.coordinate.latitude) // getting latitude from GPS
        var latDeg = calculate(pos: latitudeRawString).degrees // converting to get DEGREES only
        var latMinutes = calculate(pos: latitudeRawString).minutes // converting to get MINUTES only
        var decimalSeconds = calculate(pos: latitudeRawString).seconds // converting to get SECONDS only
        if latDeg > 0 {
            latitudeLabel.text = printLabel(degrees: latDeg, minutes: latMinutes, seconds: decimalSeconds) + "N"
        } else {
            latDeg = 0 - latDeg
            latMinutes = 0 - latMinutes
            decimalSeconds = 0 - decimalSeconds
            latitudeLabel.text = printLabel(degrees: latDeg, minutes: latMinutes, seconds: decimalSeconds) + "S"
        //    latitudeLabel.text = String("\(latitudeRawString)")
        }
    
        let longitudeRawString = String(newLocation.coordinate.longitude) // getting longitude from GPS
        var lonDeg = calculate(pos: longitudeRawString).degrees // converting to get DEGREES only
        var lonMinutes = calculate(pos: longitudeRawString).minutes // converting to get MINUTES only
        var londecimalSeconds = calculate(pos: longitudeRawString).seconds // converting to get SECONDS only
        
        if lonDeg > 0 {
            longitudeLabel.text = printLabel(degrees: lonDeg, minutes: lonMinutes, seconds: londecimalSeconds) + "E"
            } else {
            lonDeg = 0 - lonDeg
            lonMinutes = 0 - lonMinutes
            londecimalSeconds = 0 - londecimalSeconds
            longitudeLabel.text = printLabel(degrees: lonDeg, minutes: lonMinutes, seconds: londecimalSeconds) + "W"
            //   longitudeLabel.text = String("\(longitudeRawString)")
            }
        }
} // closing "locationManger/didUpdateLocations"

func calculate (pos:String) -> (degrees:Int, minutes:Int, seconds:Int) {
    let remainMinutes = Double(pos)?.truncatingRemainder(dividingBy: 1)
    let degrees1 = Double(pos)! - (remainMinutes)!
    var minutes1 = remainMinutes! * 60
    var seconds1 = minutes1.truncatingRemainder(dividingBy: 1)
    minutes1 = minutes1 - seconds1
    seconds1 = seconds1 * 100
    let garbage = seconds1.truncatingRemainder(dividingBy: 1)
    seconds1 = round((seconds1 - garbage)/10)
    let degrees = Int(degrees1)
    let minutes = Int(minutes1)
    let seconds = Int(seconds1)

    return (degrees,minutes,seconds)
} // closing "calculate" function

func printLabel (degrees:Int, minutes:Int, seconds:Int) -> String {
    let degrees = degrees
    let minutes = minutes
    let seconds = seconds

    if degrees < 10 {
    let degreesString = String("0" + "\(degrees)")
    if minutes < 10 {
    let minutesString = String("0" + "\(minutes)")
    let text = String("\(degreesString)" + "\u{00B0}" + "\(minutesString)" + "'" + "\(seconds)")
        return text
    } else {
        let text = String("\(degreesString)" + "\u{00B0}" + "\(minutes)" + "'" + "\(seconds)")
        return text
    }
    } else {
        if minutes < 10 {
        let minutesString = String("0" + "\(minutes)")
        let text = String("\(degrees)" + "\u{00B0}" + "\(minutesString)" + "'" + "\(seconds)")
            return text
        } else {
            let text = String("\(degrees)" + "\u{00B0}" + "\(minutes)" + "'" + "\(seconds)")
            return text
        }
    }
} // closing "printLabel" function

}

#2

Покажи код, что ты делаешь?


#3

Прикрепил :roll_eyes:


#4

Есть подозрение что выполняется не в главном потоке.
Попробуй строки где идет присвоение значений сделать:

DispatchQueue.main.async {
latitudeLabel.text = printLabel(degrees: latDeg, minutes: latMinutes, seconds: decimalSeconds) + “S”
}

и соответственно

	DispatchQueue.main.async {
		longitudeLabel.text = printLabel(degrees: lonDeg, minutes: lonMinutes, seconds: londecimalSeconds) + "W"
	}

#5

попробуй очищать поле текст у лейбла перед каждым обновлением


#6

Это точно нет. Смысла в этом нет.


#7

Это первое что я попробовал =( Не прокатило =(
Но в любом случае спасибо за совет =)


#8

Не помогло =( Но в любом случае спасибо =(


#9

есть ссылка на Git, попробовать собрать проект?


#10

Я совсем начинающий программист, с гитом еще не разобрался.
Вот ссылка на архив. https://cloud.mail.ru/public/5fTZ/3DLEE4iib

Просто даже представить не могу в какую сторону двигаться. Ведь по логике при присвоении значения в UILabel старое значение должно перезаписываться, а у меня они накладываются друг на друга.
Может можно как-то экран очищать перед каждым обновлением координат? (Это типа как команда CLS (clear screen) в Бэйсике :rofl:


#11
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
    if let newLocation = locations.last {
        let latitudeRawString = String(newLocation.coordinate.latitude) // getting latitude from GPS
        var latDeg = calculate(pos: latitudeRawString).degrees // converting to get DEGREES only
        var latMinutes = calculate(pos: latitudeRawString).minutes // converting to get MINUTES only
        var decimalSeconds = calculate(pos: latitudeRawString).seconds // converting to get SECONDS only
        if latDeg > 0 {
			DispatchQueue.main.async {
				self.latitudeLabel.text = self.printLabel(degrees: latDeg, minutes: latMinutes, seconds: decimalSeconds) + "N"
			}
        } else {
            latDeg = 0 - latDeg
            latMinutes = 0 - latMinutes
            decimalSeconds = 0 - decimalSeconds
			DispatchQueue.main.async {
				self.latitudeLabel.text = self.printLabel(degrees: latDeg, minutes: latMinutes, seconds: decimalSeconds) + "S"
			}
        }
    
        let longitudeRawString = String(newLocation.coordinate.longitude) // getting longitude from GPS
        var lonDeg = calculate(pos: longitudeRawString).degrees // converting to get DEGREES only
        var lonMinutes = calculate(pos: longitudeRawString).minutes // converting to get MINUTES only
        var londecimalSeconds = calculate(pos: longitudeRawString).seconds // converting to get SECONDS only
        
        if lonDeg > 0 {
			DispatchQueue.main.async {
				self.longitudeLabel.text = self.printLabel(degrees: lonDeg, minutes: lonMinutes, seconds: londecimalSeconds) + "E"
			}
            } else {
            lonDeg = 0 - lonDeg
            lonMinutes = 0 - lonMinutes
            londecimalSeconds = 0 - londecimalSeconds
			DispatchQueue.main.async {
				self.longitudeLabel.text = self.printLabel(degrees: lonDeg, minutes: lonMinutes, seconds: londecimalSeconds) + "W"
            }
		}
        }
}

#12

вся работа с интерфейсом должна происходить в главном потоке


#13

Владимир, спасибо за ваш ответ. Но я сделал как вы говорили, и вот сейчас скопировал к себе код который вы прислали, но к сожалению ничего не поменялось. Координаты так и отображаются друг поверх друга. =(


#14

Если честно, даже не знаю что у вас не так.
Проверил у себя на устройстве ваш проект, ничего не накладывается. Все отрисовывается как надо. Даже без использования потоков.


#15

Если стоять на месте и не двигаться, то все норм, до тех пор пока координаты не меняются. Но как только вы двигаетесь и меняется местоположение, то вылазит такая ерунда.
Я запускал как на эмуляторе, так и на SE.


#16

Я проверял смену текста через DispatchQueue.main.asyncAfter(), не знаю на сколько корректно это было.
Попробую завтра проверить через ходьбу.