-
Notifications
You must be signed in to change notification settings - Fork 54
Description
I've found that if you use the PayCardsRecognizer and set up the UI programmatically, you get "UI API called on a background thread" warnings intermittently, probably like 1/5 times, when presenting the view controller.
The warning stack trace is:
=================================================================
Main Thread Checker: UI API called on a background thread: -[UIView layer]
PID: 20583, TID: 4297841, Thread name: (none), Queue name: com.sunsetlakesoftware.GPUImage.openGLESContextQueue, QoS: 0
Backtrace:
4 PayCardsRecognizer 0x0000000108781a50 -[GPUImageView createDisplayFramebuffer] + 188
5 PayCardsRecognizer 0x0000000108781be4 -[GPUImageView setDisplayFramebuffer] + 48
6 PayCardsRecognizer 0x0000000108781f50 __44-[GPUImageView newFrameReadyAtTime:atIndex:]_block_invoke + 72
7 PayCardsRecognizer 0x000000010875633c runSynchronouslyOnVideoProcessingQueue + 100
8 PayCardsRecognizer 0x0000000108781efc -[GPUImageView newFrameReadyAtTime:atIndex:] + 68
9 PayCardsRecognizer 0x00000001086cafec -[GPUImageVideoCamera updateTargetsForVideoCameraUsingCacheTextureAtWidth:height:time:] + 960
10 PayCardsRecognizer 0x00000001086cb584 -[GPUImageVideoCamera processVideoSampleBuffer:] + 1316
11 PayCardsRecognizer 0x00000001086cba50 __74-[GPUImageVideoCamera captureOutput:didOutputSampleBuffer:fromConnection:]_block_invoke + 124
12 libdispatch.dylib 0x000000010a11a338 _dispatch_call_block_and_release + 24
13 libdispatch.dylib 0x000000010a11b730 _dispatch_client_callout + 16
14 libdispatch.dylib 0x000000010a122740 _dispatch_lane_serial_drain + 744
15 libdispatch.dylib 0x000000010a1232e0 _dispatch_lane_invoke + 444
16 libdispatch.dylib 0x000000010a12e6c4 _dispatch_workloop_worker_thread + 1304
17 libsystem_pthread.dylib 0x00000001b3638b74 _pthread_wqthread + 272
18 libsystem_pthread.dylib 0x00000001b363b740 start_wqthread + 8
2020-09-17 10:00:37.740128+1000 MyProjectName[20583:4297841] [reports] Main Thread Checker: UI API called on a background thread: -[UIView layer]
PID: 20583, TID: 4297841, Thread name: (none), Queue name: com.sunsetlakesoftware.GPUImage.openGLESContextQueue, QoS: 0
Backtrace:
4 PayCardsRecognizer 0x0000000108781a50 -[GPUImageView createDisplayFramebuffer] + 188
5 PayCardsRecognizer 0x0000000108781be4 -[GPUImageView setDisplayFramebuffer] + 48
6 PayCardsRecognizer 0x0000000108781f50 __44-[GPUImageView newFrameReadyAtTime:atIndex:]_block_invoke + 72
7 PayCardsRecognizer 0x000000010875633c runSynchronouslyOnVideoProcessingQueue + 100
8 PayCardsRecognizer 0x0000000108781efc -[GPUImageView newFrameReadyAtTime:atIndex:] + 68
9 PayCardsRecognizer 0x00000001086cafec -[GPUImageVideoCamera updateTargetsForVideoCameraUsingCacheTextureAtWidth:height:time:] + 960
10 PayCardsRecognizer 0x00000001086cb584 -[GPUImageVideoCamera processVideoSampleBuffer:] + 1316
11 PayCardsRecognizer 0x00000001086cba50 __74-[GPUImageVideoCamera captureOutput:didOutputSampleBuffer:fromConnection:]_block_invoke + 124
12 libdispatch.dylib 0x000000010a11a338 _dispatch_call_block_and_release + 24
13 libdispatch.dylib 0x000000010a11b730 _dispatch_client_callout + 16
14 libdispatch.dylib 0x000000010a122740 _dispatch_lane_serial_drain + 744
15 libdispatch.dylib 0x000000010a1232e0 _dispatch_lane_invoke + 444
16 libdispatch.dylib 0x000000010a12e6c4 _dispatch_workloop_worker_thread + 1304
17 libsystem_pthread.dylib 0x00000001b3638b74 _pthread_wqthread + 272
18 libsystem_pthread.dylib 0x00000001b363b740 start_wqthread + 8
=================================================================
Main Thread Checker: UI API called on a background thread: -[UIView bounds]
PID: 20583, TID: 4297841, Thread name: (none), Queue name: com.sunsetlakesoftware.GPUImage.openGLESContextQueue, QoS: 0
Backtrace:
4 PayCardsRecognizer 0x0000000108781b0c -[GPUImageView createDisplayFramebuffer] + 376
5 PayCardsRecognizer 0x0000000108781be4 -[GPUImageView setDisplayFramebuffer] + 48
6 PayCardsRecognizer 0x0000000108781f50 __44-[GPUImageView newFrameReadyAtTime:atIndex:]_block_invoke + 72
7 PayCardsRecognizer 0x000000010875633c runSynchronouslyOnVideoProcessingQueue + 100
8 PayCardsRecognizer 0x0000000108781efc -[GPUImageView newFrameReadyAtTime:atIndex:] + 68
9 PayCardsRecognizer 0x00000001086cafec -[GPUImageVideoCamera updateTargetsForVideoCameraUsingCacheTextureAtWidth:height:time:] + 960
10 PayCardsRecognizer 0x00000001086cb584 -[GPUImageVideoCamera processVideoSampleBuffer:] + 1316
11 PayCardsRecognizer 0x00000001086cba50 __74-[GPUImageVideoCamera captureOutput:didOutputSampleBuffer:fromConnection:]_block_invoke + 124
12 libdispatch.dylib 0x000000010a11a338 _dispatch_call_block_and_release + 24
13 libdispatch.dylib 0x000000010a11b730 _dispatch_client_callout + 16
14 libdispatch.dylib 0x000000010a122740 _dispatch_lane_serial_drain + 744
15 libdispatch.dylib 0x000000010a1232e0 _dispatch_lane_invoke + 444
16 libdispatch.dylib 0x000000010a12e6c4 _dispatch_workloop_worker_thread + 1304
17 libsystem_pthread.dylib 0x00000001b3638b74 _pthread_wqthread + 272
18 libsystem_pthread.dylib 0x00000001b363b740 start_wqthread + 8
2020-09-17 10:00:46.642641+1000 MyProjectName[20583:4297841] [reports] Main Thread Checker: UI API called on a background thread: -[UIView bounds]
PID: 20583, TID: 4297841, Thread name: (none), Queue name: com.sunsetlakesoftware.GPUImage.openGLESContextQueue, QoS: 0
Backtrace:
4 PayCardsRecognizer 0x0000000108781b0c -[GPUImageView createDisplayFramebuffer] + 376
5 PayCardsRecognizer 0x0000000108781be4 -[GPUImageView setDisplayFramebuffer] + 48
6 PayCardsRecognizer 0x0000000108781f50 __44-[GPUImageView newFrameReadyAtTime:atIndex:]_block_invoke + 72
7 PayCardsRecognizer 0x000000010875633c runSynchronouslyOnVideoProcessingQueue + 100
8 PayCardsRecognizer 0x0000000108781efc -[GPUImageView newFrameReadyAtTime:atIndex:] + 68
9 PayCardsRecognizer 0x00000001086cafec -[GPUImageVideoCamera updateTargetsForVideoCameraUsingCacheTextureAtWidth:height:time:] + 960
10 PayCardsRecognizer 0x00000001086cb584 -[GPUImageVideoCamera processVideoSampleBuffer:] + 1316
11 PayCardsRecognizer 0x00000001086cba50 __74-[GPUImageVideoCamera captureOutput:didOutputSampleBuffer:fromConnection:]_block_invoke + 124
12 libdispatch.dylib 0x000000010a11a338 _dispatch_call_block_and_release + 24
13 libdispatch.dylib 0x000000010a11b730 _dispatch_client_callout + 16
14 libdispatch.dylib 0x000000010a122740 _dispatch_lane_serial_drain + 744
15 libdispatch.dylib 0x000000010a1232e0 _dispatch_lane_invoke + 444
16 libdispatch.dylib 0x000000010a12e6c4 _dispatch_workloop_worker_thread + 1304
17 libsystem_pthread.dylib 0x00000001b3638b74 _pthread_wqthread + 272
18 libsystem_pthread.dylib 0x00000001b363b740 start_wqthread + 8
I'm using Cocoapods to install the framework, and interestingly I'm not able to reproduce this issue if I use a storyboard to generate the UI. I noticed that your example project doesn't have this issue, and also uses a storyboard, which appears to work there too. If you want to try reproduce this, the view controller I'm using which runs into the issue is:
import PayCardsRecognizer
import UIKit
protocol CreditCardScanPresenting {
func scanned(name: String?, number: String?, expiryMonth: String?, expiryYear: String?)
}
final class CreditCardScanViewController: UIViewController {
private let presenter: CreditCardScanPresenting
private let cancelBag = CancelBag()
private let cardScanContainer = UIView()
private let labelContainer = UIView()
private let titleLabel = UILabel()
private let subtitleLabel = UILabel()
private lazy var recognizer = PayCardsRecognizer(
delegate: self,
resultMode: .async,
container: cardScanContainer,
frameColor: .theme(.primaryColor)
)
init(presenter: CreditCardScanPresenting) {
self.presenter = presenter
super.init(nibName: nil, bundle: nil)
}
required init?(coder: NSCoder) {
fatalError("Init with coder not supported.")
}
override func viewDidLoad() {
super.viewDidLoad()
prepareLayout()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
navigationController?.navigationBar.shadowImage = UIImage()
recognizer.startCamera()
}
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
recognizer.stopCamera()
}
}
private extension CreditCardScanViewController {
func prepareLayout() {
prepareNavigationBar()
prepareCardScanContainer()
prepareTitleLabel()
prepareSubtitleLabel()
prepareLabelContainer()
}
private func prepareNavigationBar() {
navigationItem.largeTitleDisplayMode = .never
navigationItem.leftBarButtonItem = {
let item = UIBarButtonItem(image: .asset(.closeIcon), style: .plain)
item.tintColor = .theme(.primaryColor)
item.tapPublisher
.sink { [weak self] in
self?.dismiss(animated: true, completion: nil)
}
.cancelledBy(cancelBag)
return item
}()
}
private func prepareCardScanContainer() {
view.addSubview(cardScanContainer)
cardScanContainer.constrain([.leading, .trailing], to: view)
cardScanContainer.topAnchor
.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor)
.activate()
}
private func prepareTitleLabel() {
titleLabel.text = LocalizationKey.creditCardScanTitle.localized()
titleLabel.font = .theme(.contentTitle)
titleLabel.numberOfLines = 0
titleLabel.textAlignment = .center
labelContainer.addSubview(titleLabel)
titleLabel.constrain(
[.leading, .trailing, .top],
to: labelContainer,
constants: [
.top: .contentPadding,
.leading: .contentPadding,
.trailing: -.contentPadding
]
)
}
private func prepareSubtitleLabel() {
subtitleLabel.text = LocalizationKey.creditCardScanSubtitle.localized()
subtitleLabel.font = .theme(.contentValue)
subtitleLabel.numberOfLines = 0
subtitleLabel.textAlignment = .center
labelContainer.addSubview(subtitleLabel)
subtitleLabel.constrain(
[.leading, .trailing, .bottom],
to: labelContainer,
constants: [
.bottom: -.contentPadding,
.leading: .contentPadding,
.trailing: -.contentPadding
]
)
subtitleLabel.topAnchor
.constraint(equalTo: titleLabel.bottomAnchor, constant: 8)
.activate()
}
private func prepareLabelContainer() {
view.addSubview(labelContainer)
labelContainer.constrain([.leading, .trailing, .bottom], to: view)
labelContainer.topAnchor
.constraint(equalTo: cardScanContainer.bottomAnchor, constant: 0)
.activate()
}
}
extension CreditCardScanViewController: PayCardsRecognizerPlatformDelegate {
func payCardsRecognizer(_ payCardsRecognizer: PayCardsRecognizer, didRecognize result: PayCardsRecognizerResult) {
presenter.scanned(
name: result.recognizedHolderName,
number: result.recognizedNumber,
expiryMonth: result.recognizedExpireDateMonth,
expiryYear: result.recognizedExpireDateYear
)
}
}
There's a few custom extensions used there for constraints, but you get the general idea.
I did some Googling too and it looks like a similar issue is appearing here:
BradLarson/GPUImage#2512
I'm guessing from the stack trace you guys use the GPUImage library, and might find that useful, I could be misinterpreting it though.
Good luck, and thank you for an awesome card scanning framework!