我是一个新手程序员,正在尝试创建一个单一视图天气应用程序。我的目标是从HomeViewController编辑在WeeklyWeatherViewController中创建的dateLbl1。
我像这样写我的代码:
let WeeklyWeatherView = WeeklyWeatherViewController()
...
WeeklyWeatherView.dateLbl1.text = nextDayShort[0].uppercased()
但是标签得到"零"值。
致命错误:隐式解包可选值时意外发现 nil
(nextDayShort 不是零,我将 UILabel 连接到故事板(
在网络上搜索我的问题,并尝试调用ViewController为:
var swipePage: WeeklyWeatherViewController = UIStoryboard(name: "main", bundle: nil).instantiateViewControllerWithIdentifier("MyStoryboard")
我收到此错误:
线程 1:EXC_BAD_INSTRUCTION(代码 = EXC_I386_INVOP,子代码 = 0x0(
我读过有关在视图控制器之间传递数据的信息,但根本无法在我的代码中使用它们。如何解决此问题? 感谢您的任何帮助!
主视图控制器.swift
import UIKit
import Foundation
import CoreLocation
let DateView = DateViewController()
let WeatherView = WeatherViewController()
let WeeklyWeatherView = WeeklyWeatherViewController()
var currentHour : String?
var currentDay: String?
var nextDayShort = [String]()
var listCount = 0
class HomeViewController: UIViewController, CLLocationManagerDelegate {
@IBOutlet var backgroudView: UIView!
@IBOutlet weak var daysView: UIView!
@IBOutlet weak var timeView: UIView!
@IBOutlet weak var splashImage: UIImageView!
@IBOutlet weak var weatherView: UIView!
@IBOutlet weak var middleView: UIView!
@IBOutlet weak var rightView: UIView!
@IBOutlet weak var leftView: UIView!
@IBOutlet weak var middleHourBGView: UIView!
var locationManager: CLLocationManager?
override func viewDidAppear(_ animated: Bool) {
locationManager = CLLocationManager()
locationManager?.delegate = self
locationManager?.requestAlwaysAuthorization()
locationManager?.desiredAccuracy = kCLLocationAccuracyBest
locationManager?.startUpdatingLocation()
if CLLocationManager.locationServicesEnabled() {
switch CLLocationManager.authorizationStatus() {
case .restricted, .denied:
let alert = UIAlertController(title: "Locations servies are disabled!", message: "Please go to settings and allow location services or the application can't fetch weather data.", preferredStyle: .alert)
let settingsAction = UIAlertAction(title: "Settings", style: .default) { (_) -> Void in
guard let settingsUrl = URL(string: UIApplication.openSettingsURLString) else {
return
}
if UIApplication.shared.canOpenURL(settingsUrl) {
UIApplication.shared.open(URL(string: UIApplication.openSettingsURLString)!, options: [:], completionHandler: nil)
}
}
alert.addAction(settingsAction)
let cancelAction = UIAlertAction(title: "Cancel", style: .default, handler: nil)
alert.addAction(cancelAction)
self.present(alert, animated: true, completion: nil)
case .authorizedAlways, .authorizedWhenInUse:
print("Access")
@unknown default:
break
}
} else {
print("Location services are not enabled")
}
}
override func viewDidLoad() {
super.viewDidLoad()
styleUI()
}
private func styleUI(){
daysView.layer.cornerRadius = 10
daysView.layer.shadowOpacity = 0.5
daysView.layer.shadowOffset = .zero
daysView.layer.shadowRadius = 10
middleView.layer.cornerRadius = 25
middleHourBGView.layer.cornerRadius = 10
let now = Date()
let formatter = DateFormatter()
let hour = Calendar.current.component(.hour, from: Date())
formatter.timeZone = TimeZone.current
formatter.dateFormat = "MMMM dd,YYYY EEEE"
let dateString = formatter.string(from: now)
DateView.dateLbl?.text = dateString
currentHour = String(hour)
let formatter2 = DateFormatter()
for n in 1..<6 {
var dayComponent = DateComponents()
dayComponent.day = n
let theCalendar = Calendar.current
let nextDate = theCalendar.date(byAdding: dayComponent, to: Date())
formatter2.dateFormat = "EE"
let nextDaySh = formatter2.string(from: nextDate! as Date)
nextDayShort.append(nextDaySh)
}
DispatchQueue.main.async {
WeeklyWeatherView.dateLbl1.text = nextDayShort[0].uppercased()
WeeklyWeatherView.dateLbl2.text = nextDayShort[1].uppercased()
WeeklyWeatherView.dateLbl3.text = nextDayShort[2].uppercased()
WeeklyWeatherView.dateLbl4.text = nextDayShort[3].uppercased()
WeeklyWeatherView.dateLbl5.text = nextDayShort[4].uppercased()
}
if (hour > 5 && hour < 21) {
backgroudView.backgroundColor = #colorLiteral(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0)
timeView.backgroundColor = #colorLiteral(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0)
daysView.layer.shadowColor = #colorLiteral(red: 0.3333333433, green: 0.3333333433, blue: 0.3333333433, alpha: 1)
} else {
backgroudView.backgroundColor = #colorLiteral(red: 0.0862745098, green: 0.09411764706, blue: 0.3058823529, alpha: 1)
timeView.backgroundColor = #colorLiteral(red: 0.0862745098, green: 0.09411764706, blue: 0.3058823529, alpha: 1)
DateView.cityLbl.textColor = #colorLiteral(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0)
DateView.dateLbl.textColor = #colorLiteral(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0)
DateView.tempLbl.textColor = #colorLiteral(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0)
daysView.layer.shadowColor = #colorLiteral(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0)
WeatherView.leftHourLbl.textColor = #colorLiteral(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0)
WeatherView.leftTempLbl.textColor = #colorLiteral(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0)
WeatherView.rightHourLbl.textColor = #colorLiteral(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0)
WeatherView.rightTempLbl.textColor = #colorLiteral(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0)
WeatherView.middleTempLbl.textColor = #colorLiteral(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0)
}
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let location:CLLocationCoordinate2D = manager.location!.coordinate
weather.getWeather(lat: location.latitude, lon: location.longitude) { weather in
DispatchQueue.main.async {
DateView.cityLbl.text = weather.city.name
DateView.tempLbl.text = "(Int(round(weather.list[0].main.temp)) - 273)°"
WeeklyWeatherView.tempLbl1.text = "(Int(round(weather.list[1].main.temp)) - 273)°"
WeeklyWeatherView.tempLbl2.text = "(Int(round(weather.list[2].main.temp)) - 273)°"
WeeklyWeatherView.tempLbl3.text = "(Int(round(weather.list[3].main.temp)) - 273)°"
WeeklyWeatherView.tempLbl4.text = "(Int(round(weather.list[4].main.temp)) - 273)°"
WeeklyWeatherView.tempLbl5.text = "(Int(round(weather.list[5].main.temp)) - 273)°"
self.splashImage.isHidden = true
}
}
}
}
WeeklyWeatherViewController.swift
import UIKit
import Foundation
let storyBoardEdit = StoryboardEditor()
let weather = WeatherAPI()
class WeeklyWeatherViewController: UIView {
@IBOutlet weak var dateLbl1: UILabel!
@IBOutlet weak var dateLbl2: UILabel!
@IBOutlet weak var dateLbl3: UILabel!
@IBOutlet weak var dateLbl4: UILabel!
@IBOutlet weak var dateLbl5: UILabel!
@IBOutlet weak var tempLbl1: UILabel!
@IBOutlet weak var tempLbl2: UILabel!
@IBOutlet weak var tempLbl3: UILabel!
@IBOutlet weak var tempLbl4: UILabel!
@IBOutlet weak var tempLbl5: UILabel!
@IBOutlet weak var weatherImg1: UIImageView!
@IBOutlet weak var weatherImg2: UIImageView!
@IBOutlet weak var weatherImg3: UIImageView!
@IBOutlet weak var weatherImg4: UIImageView!
@IBOutlet weak var weatherImg5: UIImageView!
func fillUI(){
dateLbl1.text = nil
var dayId = [String]()
for x in 1..<6 {
dayId.append("03d")
let dayIdInt = Int(dayId[x-1])!
let imageIDName = storyBoardEdit.editWeatherIcons(dayIDInt: dayIdInt)
switch x {
case 1:
DispatchQueue.main.async {
self.weatherImg1.image = UIImage(named: imageIDName)
}
case 2:
DispatchQueue.main.async {
self.weatherImg2.image = UIImage(named: imageIDName)
}
case 3:
DispatchQueue.main.async {
self.weatherImg3.image = UIImage(named: imageIDName)
}
case 4:
DispatchQueue.main.async {
self.weatherImg4.image = UIImage(named: imageIDName)
}
case 5:
DispatchQueue.main.async {
self.weatherImg5.image = UIImage(named: imageIDName)
}
default:
break
}
}
}
}
是否更改:
- 在情节提要(或 Xib(中,将
weatherView
的类更新为WeeklyWeatherViewController
并重置出口。你应该这样得到它:
@IBOutlet weak var weatherView: WeeklyWeatherViewController!
- 删除以下行:
let WeeklyWeatherView = WeeklyWeatherViewController()
- 在您的
styleUI()
方法中,使用以下方法替换使用WeeklyWeatherView
的行:
DispatchQueue.main.async {
weeklyWeatherView.dateLbl1.text = nextDayShort[0].uppercased()
weeklyWeatherView.dateLbl2.text = nextDayShort[1].uppercased()
weeklyWeatherView.dateLbl3.text = nextDayShort[2].uppercased()
weeklyWeatherView.dateLbl4.text = nextDayShort[3].uppercased()
weeklyWeatherView.dateLbl5.text = nextDayShort[4].uppercased()
}
在你的 locationManager(( 函数中,使用WeeklyWeatherView
替换行:
weeklyWeatherView.tempLbl1.text = "Int(round(weather.list[1].main.temp)) - 273)º"
weeklyWeatherView.tempLbl2.text = "Int(round(weather.list[2].main.temp)) - 273)º"
weeklyWeatherView.tempLbl3.text = "Int(round(weather.list[3].main.temp)) - 273)º"
weeklyWeatherView.tempLbl4.text = "Int(round(weather.list[4].main.temp)) - 273)º"
weeklyWeatherView.tempLbl5.text = "Int(round(weather.list[5].main.temp)) - 273)º"
看到我在这两种情况下都使用新创建的插座,对吧?
问题是你初始化WeeklyWeatherViewController
的方式
let WeeklyWeatherView = WeeklyWeatherViewController()
此视图具有从中创建连接的关联 xib。现在,当您初始化WeeklyWeatherViewController
类时,您的 xib 视图尚未初始化。
您需要在WeeklyWeatherViewController
的init
方法中加载 nib 文件。
class WeeklyWeatherViewController: UIView {
override init(frame: CGRect) {
super.init(frame: frame)
let contentView = Bundle.main.loadNibNamed("your_nib", owner: self, options: nil)?.first as? UIView
addSubview(contentView!)
// set constraints for contentView.
}
convenience init() {
let defaultFrame = //provide your default frame
self.init(frame: defaultFrame)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
所以问题是当你有一个关联的xib文件时,简而言之,当你从外部提供你的视图时,你需要初始化该外部视图并将其附加到你的类。这样,您的视图仍将保留内存,您可以访问所有连接的IBOutlet
。