从你提供的代码片段来看,错误发生在这一行:
private lazy var cameraFeedService = CameraFeedService(previewView: previewView)
这里的 previewView
在调用时可能为 nil
。因为 lazy var
的初始化会在第一次访问时进行,而此时 previewView
可能还未被实例化或连接。因此,尝试将 previewView
传递给 CameraFeedService
会导致“意外发现 nil”错误。
解决方案
要解决这个问题,你可以采用以下几种方法:
确保 IBOutlet 正确连接:
- 确保在 Interface Builder 中将
previewView
的 IBOutlet 连接到了相应的 UIView。如果未连接,运行时访问该 IBOutlet 时就会返回 nil。
- 确保在 Interface Builder 中将
推迟初始化:
- 将 cameraFeedService 的初始化移动到 viewDidLoad 方法中,在该方法中,可以确保所有的 UI 元素都已经加载和连接完成。
private var cameraFeedService: CameraFeedService?
override func viewDidLoad() {
super.viewDidLoad()
cameraFeedService = CameraFeedService(previewView: previewView)
// 其他初始化代码...
}
- 检查视图生命周期:
- 确保在视图完全加载后再使用任何 IBOutlet。这通常意味着在
viewDidLoad()
或之后的方法(如viewWillAppear()
)中使用它们。
- 确保在视图完全加载后再使用任何 IBOutlet。这通常意味着在
更新后的示例代码
以下是更新后的 ViewController 示例,以避免强制解包带来的问题:
import UIKit
import AVFoundation
import MediaPipeTasksVision
import IroadSport
class ViewController: UIViewController {
@IBOutlet weak var previewView: UIView!
@IBOutlet weak var cameraUnavailableLabel: UILabel!
@IBOutlet weak var resumeButton: UIButton!
private var isSessionRunning = false
private var isObserving = false
private let backgroundQueue = DispatchQueue(label: "com.google.mediapipe.cameraController.backgroundQueue")
// 将 cameraFeedService 声明为可选变量,并移除 lazy 修饰符
private var cameraFeedService: CameraFeedService?
private let poseLandmarkerServiceQueue = DispatchQueue(
label: "com.google.mediapipe.cameraController.poseLandmarkerServiceQueue",
attributes: .concurrent)
private var _poseLandmarkerService: PoseLandmarkerService?
private var poseLandmarkerService: PoseLandmarkerService? {
get {
poseLandmarkerServiceQueue.sync {
return self._poseLandmarkerService
}
}
set {
poseLandmarkerServiceQueue.async(flags: .barrier) {
self._poseLandmarkerService = newValue
}
}
}
override func viewDidLoad() {
super.viewDidLoad()
// 在这里安全地初始化 cameraFeedService
if let previewView = previewView {
cameraFeedService = CameraFeedService(previewView: previewView)
} else {
print("Error: previewView is nil")
// 处理视图未准备好的情况,例如显示错误消息等。
}
// 其他初始化操作...
}
}
通过这种方式,你可以确保只有在所有界面元素准备好之后才会尝试创建 cameraFeedService
实例,从而避免由于 optional 为 nil 导致的崩溃。如果还有其他问题,请继续提问!
内容由零声教学AI助手提供,问题来源于学员提问