Open NiallBegley opened 9 months ago
Same issue I'm facing with Scanner Module
import SwiftUI import VisionKit
struct ScannerView: View {
// MARK: ObservedObject Variables -
@ObservedObject var scannerViewModel = ScannerViewModel()
@ObservedObject var startcontractViewModel: StartContractViewModel
// MARK: State Variables -
@State var isNavigateToStartContractView: Bool = false
@State var scanResults: String = ""
@State private var isDeviceCapacity = false
@State var appearVia: Views = .purchaserAgreementView
@State var isHideScanningText = false
@State var cornerStrokeColor: Color = Color.blue
@State var headingContent: String = "To continue, please scan your legitimate document, such as your licence."
@State var navigateVia: NavigateToPurchaserInfoViewVia = .scanner
// MARK: Binding Variables -
@Binding var isDismiss: Bool
@Binding var navigateToScannerView: Bool
// MARK: View Body -
var body: some View {
/// `ZStack` - A view that overlays its subviews, aligning them in both axes.
ZStack {
VStack {
if isDeviceCapacity {
DataScannerView(
startScanning: $isDeviceCapacity,
scanResult: $scanResults,
isNavigateToStartContractView: $isNavigateToStartContractView,
appearVia: $appearVia,
isDismiss: $isDismiss,
isHideScanningText: $isHideScanningText,
cornerStrokeColor: $cornerStrokeColor,
headingContent: $headingContent
)
} else {
Text("Please provide access to the camera in settings")
}
}
.task {
if scannerViewModel.dataScannerAccessStatus != .scannerAvailable {
await scannerViewModel.requestDataScannerAccessStatus()
}
}
.onAppear {
isDeviceCapacity = (DataScannerViewController.isSupported && DataScannerViewController.isAvailable)
scannedDetails = DriverLicense()
}
.navigationDestination(isPresented: $isNavigateToStartContractView) {
StartContractView(
startcontractViewModel: startcontractViewModel,
selectedOfferCreationOptions: .scanID,
backToPurchaserAgreementView: $navigateToScannerView,
navigateToStartContractViewVia: $navigateVia
)
}
}
.ignoresSafeArea()
}
}
import SwiftUI import UIKit import VisionKit import AVFoundation
struct DataScannerView: UIViewControllerRepresentable {
// MARK: ObservedObject Variables -
@ObservedObject var scannerViewModel = ScannerViewModel()
// MARK: Binding Variables -
@Binding var startScanning: Bool
@Binding var scanResult: String
@Binding var isNavigateToStartContractView: Bool
@Binding var appearVia: Views
@Binding var isDismiss: Bool
@Binding var isHideScanningText: Bool
@Binding var cornerStrokeColor: Color
@Binding var headingContent: String
// MARK: Shared Methods -
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
func makeUIViewController(context: Context) -> DataScannerViewController {
let viewController = DataScannerViewController(
recognizedDataTypes: [scannerViewModel.recognizedDataType],
qualityLevel: .accurate,
recognizesMultipleItems: false,
isHighFrameRateTrackingEnabled: false,
isGuidanceEnabled: true,
isHighlightingEnabled: true
)
viewController.delegate = context.coordinator
return viewController
}
func updateUIViewController(_ viewController: DataScannerViewController, context: Context) {
if startScanning {
try? viewController.startScanning()
} else {
viewController.stopScanning()
}
}
// Coordinator to manage interactions with the DataScannerViewController
class Coordinator: NSObject, DataScannerViewControllerDelegate {
// MARK: Shared Variables -
var parent: DataScannerView
var isPDF: Bool = false
// MARK: Init() -
init(_ parent: DataScannerView) {
self.parent = parent
}
// MARK: Delegate and DataSource Methods
func dataScanner(_ dataScanner: DataScannerViewController, didTapOn item: RecognizedItem) {
performActionAccordingToRecognizedItem(item)
}
func dataScanner(_ dataScanner: DataScannerViewController, didAdd addedItems: [RecognizedItem], allItems: [RecognizedItem]) {
UINotificationFeedbackGenerator().notificationOccurred(.success)
_ = performActionOnRecognizedItems(addedItems: addedItems)
// addedItems.forEach { item in performActionAccordingToRecognizedItem(item) }
}
func dataScanner(_ dataScanner: DataScannerViewController, didRemove removedItems: [RecognizedItem], allItems: [RecognizedItem]) {
}
func dataScanner(_ dataScanner: DataScannerViewController, becameUnavailableWithError error: DataScannerViewController.ScanningUnavailable) {
}
// MARK: Perform Action According To Recognized Item
fileprivate func performActionAccordingToRecognizedItem(_ item: RecognizedItem) {
switch item {
// Define a closure to handle captured text
case .text(let text):
parent.scanResult = text.transcript
// Define a closure to handle captured barcodes
case .barcode(let barcode):
// Validate symbology
let symbology = barcode.observation.symbology
switch symbology {
case .pdf417, .microPDF417:
parent.scanResult = barcode.payloadStringValue ?? "Unknown barcode"
parent.isHideScanningText = true
if parent.appearVia == .purchaserAgreementView {
parent.isNavigateToStartContractView = true
} else {
parent.isDismiss = false
}
break
default:
parent.isHideScanningText = true
}
default: break
}
}
fileprivate func performActionOnRecognizedItems(addedItems: [RecognizedItem]) -> Bool {
var isValidated = false
addedItems.forEach { item in
switch item {
case .barcode(let barcode):
if barcode.observation.symbology == .pdf417 || barcode.observation.symbology == .microPDF417 {
isValidated = true
parent.cornerStrokeColor = Color.green
parent.headingContent = "Your document is scanning, please wait..."
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
self.performActionAccordingToRecognizedItem(item)
}
break
} else {
isValidated = false
parent.cornerStrokeColor = Color.red
parent.headingContent = "Scanning..."
}
default: isValidated = false
parent.cornerStrokeColor = Color.red
parent.headingContent = "Scanning..."
}
}
return isValidated
}
}
}
Describe the bug?
I've run into a very particular bug where a SwiftUI iOS app will freeze and the CPU and memory usage will rapidly climb in a way consistent with something infinitely looping. It happens under these circumstances:
@Environment(\.dismiss) private var dismiss
variable defined (doesn't even need to be used)NavigationLink
to another View that must have a class member variable, usually this would be a view model. (structs do not cause the crash).When the user presses the control associated with the
NavigationLink
the app will immediately freeze and resource consumption will rapidly climb. If you remove any of the above variables (including the use ofokta-mobile-swift
as a dependency) the freeze will disappear.What is expected to happen?
When the
NavigationLink
is pressed the view should be pushed to the destination view as usualWhat is the actual behavior?
The app immediately freezes and resource consumption climbs. You can put a breakpoint on the
NavigationLink
and see it keeps getting called over and over again.Reproduction Steps?
okta-mobile-swift
dependency to the project (I used the latest version)RootView
as the root view and add the following code:Additional Information?
No response
SDK Version(s)
Verified on 1.3.0 and 1.5.0
Build Information
No response