在从Objc超类继承的Swift子类中未调用viewDidLoad [英] viewDidLoad not being called in Swift subclasses inherited from Objc superclass
问题描述
我对Objc和Swift中的viewDidLoad有疑问.我不是 熟悉Swift,而我正试图第一次将Swift代码嵌入到我们的应用中.
I have a question about viewDidLoad in Objc versus Swift. I am not familiar with Swift, and I'm trying to embed Swift code into our app for the first time.
我要嵌入的快速代码有两个这样声明的继承类:
The swift code I am trying to embed has two classes with inheritance declared this way:
ViewController_A (swift) : ViewController_B (swift) : UIViewController
两个视图控制器A和B都具有覆盖"状态. viewDidLoad
方法.
也就是说,它们被声明为override func viewDidLoad() {}
.如果
我将上述关系保持原样,并在设置断点的情况下运行,
ViewController_A
和ViewController_B
的viewDidLoad
中的print
语句,
我确实看到viewDidLoad
的viewDidLoad
在viewDidLoad
的之前执行
viewController_B
.这似乎是很合理的.两者各自
viewDidLoad
方法调用super.viewDidLoad
.一切都很好.
Both view controllers A and B have "overriding" viewDidLoad
methods.
That is they are declared as override func viewDidLoad() {}
. If
I leave the above relationship as is and I run with breakpoints set and
print
statements in viewDidLoad
of both ViewController_A
and ViewController_B
,
I do see that viewDidLoad
for ViewController_A
executes before viewDidLoad
for
viewController_B
. That seems to make perfect sense. Both respective
viewDidLoad
methods call super.viewDidLoad
. All is good.
我试图通过添加一个 链中的Objective-C类:
I tried to change the inheritance of the above hierarchy by adding an Objective-C class in the chain:
ViewContoller_A
(Swift):ViewController_B
(Swift):ViewController_C
(Objective-C):UIViewController
.
ViewContoller_A
(Swift) : ViewController_B
(Swift) : ViewController_C
(Objective-C) : UIViewController
.
ViewController_C
还有一个viewDidLoad
方法,该方法也调用[super viewDidLoad]
.
ViewController_C
also has a viewDidLoad
method which also calls [super viewDidLoad]
.
如果我在所有三个视图控制器中的所有三个viewDidLoad
方法的开头都设置了断点并设置了print
s/NSLog
,则对于ViewController_C
,只有viewDidLoad
(Objective-C)
执行.控制器A和B viewDidLoad
中的断点/print
永远不会出现.我不确定这是否会向该主题添加不必要的信息,但是有趣的是,我会收到警告消息:
If I run with breakpoints set and print
s/NSLog
at the beginning of all three viewDidLoad
methods in all three view controllers, only viewDidLoad
for ViewController_C
(Objective-C)
executes. The breakpoints/print
s in controllers A and B viewDidLoad
never appear. I'm not sure this is adding unnecessary info to the topic, but what's interesting is I'll get a warning message:
尝试将ViewController_A呈现在其视图不在视图中的ViewController_C上 窗口层次结构!
Attempt to present ViewController_A on ViewController_C whose view is not in the window hierarchy!
这似乎是在告诉我有关ViewController_A
的某些内容正在尝试加载视图.因此,为确保确定,作为测试,我注释了ViewContoller_C
viewDidLoad
中所有与UI相关的代码.然后,我没有收到该警告消息,它不应该阻止ViewController_A
viewDidLoad
执行,但是ViewController_A
中的viewDidLoad
方法仍然没有.
This seems to be telling me that something about ViewController_A
is trying to load the view. So just to be sure, as a test, I commented out all the UI related code in ViewContoller_C
viewDidLoad
. I do not then get that warning message, and it shouldn't prevent ViewController_A
viewDidLoad
to execute, but the viewDidLoad
method in ViewController_A
still does not.
请注意,ViewController_C
由情节情节提要板segue提起,如果添加了任何相关信息.
Note, ViewController_C
is being brought up by a modal storyboard segue, if that adds any relevant info.
为所有这些麻烦感到抱歉,但是有一种方法可以强制在上面概述的类继承层次结构中将Swift子类视图控制器中的viewDidLoad
方法执行,并将Objective-C视图控制器添加到混合中?
So sorry for all that rambling, but is there a way to force the viewDidLoad
methods in the Swift subclass view controllers to be executed in the class inheritance hierarchy I outlined above with the Objective-C view controller added to the mix?
感谢您的帮助, 迈克
感谢您的答复.我在下面添加了一些代码供您查看.如果我可以添加其他任何内容,请告诉我.简要概述可能会有所帮助.
Thank you for your replies. I've added some code below for your review. If I can add anything else, please let me know. Maybe a brief overview will help.
我添加的我们应用程序的代码集代表一个条形码扫描控制器,用于从样品瓶中读取条形码标签.该代码在objc中.客户现在希望在相同的操作环境中阅读文本代码.因此,在短期内,我要砍下条形码扫描控制器以开始工作.
Our App's code set that I've added represents a barcode scanning controller we use to read barcode tags from sample vials. That code is in objc. A customer would like now to read a text code in the same operational context. So in the short term I'm chopping up the barcode scanning controller to get things started.
对于这个项目,我带来了一个Apple编写的示例应用程序,可以从其WWDC会话之一中下载该应用程序,以读取/识别电话号码.那就是迅速编写的代码.到目前为止,我已经对该代码进行了较小的修改.
For this project I brought in a sample app written by Apple available for download from one of their WWDC sessions for reading/recognizing phone numbers. That's the code written in swift. I've made minor modifications to this code so far.
一旦克服了技术障碍,我将同时重写两者.
Once the technical hurdles are overcome, I will be re-writing both.
BarCodeScan .h和.m文件的开头:
Beginning of BarCodeScan .h and .m files:
#ifndef _BARCODESCANNERCONTROLLER_H_
#define _BARCODESCANNERCONTROLLER_H_
#import <UIKit/UIKit.h>
#import "SystemHeader.h"
#import "RunParameters.h"
#import <RDPDFKit/RDPDFKit.h>
#import "FormInfo.h"
#import "PatientInfo.h"
#import "GradientButton.h"
#import "LogTextInfo.h"
#import "FileIOSupport.h"
#import "PadInfo.h"
#import "XMLiPadAndDBSupport.h"
#import "BarCodeScanSupport.h"
#import "LogonInfo.h"
#import "PadInfo.h" // ocr
#import "TextScanPreviewView.h" // ocr
#define YesIndex 0
//
// With PDF coordintates, pixels are spot on so no shift
// is needed. Keep these at 0 for now.
//
#define SCALE_Y_ADJUSTMENT_FACTOR 0
#define SCALE_X_ADJUSTMENT_FACTOR 0
#define XML_VERSION_STR "<?xml version=\"1.0\"?>"
#define XML_HEADER_NAME "IFD"
#define ResultCount "ResultCount"
#define Result "Result"
#define DoNotCheck @"DoNotCheck"
#define DoNotValidate @"DoNotValidate"
//
// These enums are for determining the action needed when
// an incorrect but valid bar code is scanned.
//
//
// These enums are for determining the action needed when
// an incorrect but valid bar code is scanned.
//
typedef enum IncorrectBarCodeStatusEnum
{
BCNotRecognized = 1,
BCNotUsedButBelongsToAnotherForm,
BCAlreadyUsedByAnotherForm,
BCIsOK
} IncorrectBarCodeStatusEnum;
@interface ReturnResultBarCodeStatus : NSObject
@property (strong, nonatomic) FormInfo * formWhereBarCodeFound;
@property (assign, nonatomic) IncorrectBarCodeStatusEnum incorrectBarCodeStatus;
@end
@interface BarCodeScanController : UIViewController <UIAlertViewDelegate> // Merck2
{
BOOL isScanModeOn;
UIColor *borderColorDefault;
UIColor *viewBackgroundColorDefault;
CGPoint lineStartingPoint;
CGPoint lineEndingPoint;
int barCodeImageViewUpperYCoordinate;
DecoderResult * decoder;
// ocr
NSString * textScanResult;
}
//
// This contains this page's pixel values that are read
// from the xml incoming DBToPad file.
//
@property (strong, nonatomic) Barcode * barCode;
@property (strong, nonatomic) PatientInfo * patient;
@property (strong, nonatomic) FormInfo * form;
@property (strong, atomic) PadInfo * pad;
@property (strong, atomic) LogonInfo * logon;
@property (strong, nonatomic) RDPDFDocument * pdfDocument;
@property (strong, nonatomic) RDPDFDocumentView *pdfDocumentView;
@property (strong, nonatomic) IBOutlet UIImageView * barCodeImageView;
@property (strong, nonatomic) IBOutlet TextScanPreviewView * previewView3;
@property (strong, nonatomic) IBOutlet UIView * cutoutView;
@property (weak, nonatomic) IBOutlet GradientButton *submitButton;
- (IBAction)submitButtonAction:(GradientButton *)sender;
@property (weak, nonatomic) IBOutlet GradientButton *cancelButton;
- (IBAction)cancelButtonAction:(GradientButton *)sender;
@property (weak, nonatomic) IBOutlet GradientButton *scanButton;
- (IBAction)scanButtonAction:(GradientButton *)sender;
@property (weak, nonatomic) IBOutlet UILabel *formLabel;
@property (weak, nonatomic) IBOutlet UILabel *barCodeResultLabel;
@property (strong, nonatomic) BarCodeScanSupport *barCodeScanner;
@property (strong, nonatomic) NSMutableArray *uniqueBarCodes;
- (void) writeBarCodeResultsToXMLDataFile : (BOOL) dataFlag;
- (void) determineIncorrectBarCodeCase
: (NSString *) barCodeResult
: (ReturnResultBarCodeStatus *) returnStatus;
- (void) continueDecodeResultNotification;
@end
#endif
`````` Controller "C"
#import "BarCodeScanController.h"
@implementation ReturnResultBarCodeStatus
@synthesize formWhereBarCodeFound;
@synthesize incorrectBarCodeStatus;
@end
@implementation BarCodeScanController : UIViewController
@synthesize barCode;
@synthesize form;
@synthesize pad;
@synthesize logon;
@synthesize submitButton;
@synthesize cancelButton;
@synthesize scanButton;
@synthesize barCodeImageView;
@synthesize previewView3;
@synthesize cutoutView;
@synthesize pdfDocument;
@synthesize pdfDocumentView;
@synthesize barCodeScanner;
@synthesize uniqueBarCodes;
@synthesize barCodeResultLabel;
@synthesize formLabel;
//
// This is temporary for the demo. Should read whats in the file
// if we scanned on a page, srolled to another, and came back to
// the scanned page. But for now, just .
//
static NSString * saveBarCodeResult;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[NSThread sleepForTimeInterval : 2.0];
[super viewDidLoad];
if (deviceIsIPad)
{
self.formLabel.text = [NSString stringWithFormat:
@"%@",form.form];
}
else
{
self.formLabel.text = [NSString stringWithFormat:
@" %@",form.form];
}
[self.cancelButton useAlertStyle];
[self.submitButton useAlertStyle];
[self.scanButton useAlertStyle];
if (self.form.displaySubmitButton == NO)
{
self.submitButton.hidden = YES;
}
else
{
self.submitButton.hidden = NO;
}
//
// This creates an .ifd file with no data in it. The data base server requires
// a file with valid data or null data for each vas page. So if the user
// evenutally enters valid data, it will overwrite this. Creating the file here
// is completely dependent on the user having to scroll to the end of the form
// to do a submit. In doing so, every vas page must be passed along the way
// which will initiate this call. If we ever go back to starting out with a
// submit button on every page when the form is brought up, then we will have
// to create a null .ifd file in the forms modal controller, which will mean
// we will have to have duplicate functionality in both that controller and
// this one. Note, later added code made sure file does not first exist. It
// may already be there if there was a crash during the submit. In this case
// don't write a null file, and set vsLineDrawn to YES.
//
//
FileIOSupport * sandbox = [[FileIOSupport alloc] init];
if (![sandbox checkIfFileExistsAtPath : self.barCode.bcPngPathNameData])
{
[self writeBarCodeResultsToXMLDataFile : NO];
}
[[NSNotificationCenter defaultCenter] addObserver: self selector:@selector(decodeResultNotification:) name: BarCodeResultNotification object: nil];
// ocr x
// Comment out for text reader.
// barCodeScanner = [[BarCodeScanSupport alloc] init : barCodeImageView : self
// : self.barCode.bcFormat];
// ocr x
// Comment out for text reader
// self.barCodeImageView.image = [UIImage imageWithContentsOfFile :
// barCode.bcPngPathNameImage];
[scanButton setTitle:Retry_Str forState:UIControlStateNormal];
//
// Setting isScanModeOn works for both cases below. If we have a prior
// result we don't start the scanner but put up the previous result and
// image. If there is no prior result, we call the scanButtonAction code
// to start the scanner.
//
isScanModeOn = NO;
if (self.barCode.bcImageBuffer != nil)
{
self.barCodeResultLabel.hidden = NO;
self.barCodeResultLabel.text = barCode.bcSelectedResult;
self.barCodeResultLabel.backgroundColor = [UIColor yellowColor];
}
else
{
self.barCodeResultLabel.hidden = YES;
self.barCodeResultLabel.text = Blank;
//
// Start scanner
//
[self scanButtonAction : scanButton];
}
// ocr
// This normally gets allocatd in bar code scanner support which we are not
// using for ocr. So allocate it here. We're only using the text part of it
// so as to not disturb alot of code.
//
decoder = [DecoderResult alloc];
// ocr
// Comment out for text reader
// barCodeImageViewUpperYCoordinate = self.barCodeImageView.frame.origin.y;
DISPATCH_TO_MAIN_THREAD
// ocr x
// Comment out for text reader
// [self startScanning];
// [self performSegueWithIdentifier:TextReaderModalSegue sender:self];
DISPATCH_OUT_OF_MAIN_THREAD
}
.
.
.
Project-Bridging-Header.h的内容
Contents of Project-Bridging-Header.h
// ocr
#import "ObjectiveCTestWithSwift.h"
#import "BarCodeScanController.h"
#import "TextScanPreviewView.h"
Apple的控制器之一-控制器"B".注意我尝试过viewDidLoad 与公共"关键字,也可以不包含.
One of Apple's controllers - Controller "B". Note I tried viewDidLoad with "public" keyword and without.
import UIKit
import AVFoundation
import Vision
// ocr
// class TextReaderViewController: UIViewController {
class TextReaderViewController : BarCodeScanController {
// MARK: - UI objects
//
// ocr
// Comment these out. These outlets will be provided by barcodescancontroller.
// @IBOutlet weak var cutoutView: UIView!
// @IBOutlet weak var previewView: PreviewView!
@IBOutlet weak var numberView: UILabel!
var maskLayer = CAShapeLayer()
// Device orientation. Updated whenever the orientation changes to a
// different supported orientation.
var currentOrientation = UIDeviceOrientation.portrait
// MARK: - Capture related objects
private let captureSession = AVCaptureSession()
let captureSessionQueue = DispatchQueue(label: "com.example.apple-samplecode.CaptureSessionQueue")
var captureDevice: AVCaptureDevice?
var videoDataOutput = AVCaptureVideoDataOutput()
let videoDataOutputQueue = DispatchQueue(label: "com.example.apple-samplecode.VideoDataOutputQueue")
// MARK: - Region of interest (ROI) and text orientation
// Region of video data output buffer that recognition should be run on.
// Gets recalculated once the bounds of the preview layer are known.
var regionOfInterest = CGRect(x: 0, y: 0, width: 1, height: 1)
// Orientation of text to search for in the region of interest.
var textOrientation = CGImagePropertyOrientation.up
// MARK: - Coordinate transforms
var bufferAspectRatio: Double!
// Transform from UI orientation to buffer orientation.
var uiRotationTransform = CGAffineTransform.identity
// Transform bottom-left coordinates to top-left.
var bottomToTopTransform = CGAffineTransform(scaleX: 1, y: -1).translatedBy(x: 0, y: -1)
// Transform coordinates in ROI to global coordinates (still normalized).
var roiToGlobalTransform = CGAffineTransform.identity
// Vision -> AVF coordinate transform.
var visionToAVFTransform = CGAffineTransform.identity
// MARK: - View controller methods
// ocr
public override func viewDidLoad() {
// ocr
print("viewDidLoad TextReaderViewController")
// ocr x
super.viewDidLoad()
// Set up preview view.
previewView3.session = captureSession
// Set up cutout view.
cutoutView.backgroundColor = UIColor.gray.withAlphaComponent(0.5)
maskLayer.backgroundColor = UIColor.clear.cgColor
maskLayer.fillRule = .evenOdd
cutoutView.layer.mask = maskLayer
// Starting the capture session is a blocking call. Perform setup using
// a dedicated serial dispatch queue to prevent blocking the main thread.
captureSessionQueue.async {
self.setupCamera()
// Calculate region of interest now that the camera is setup.
DispatchQueue.main.async {
// Figure out initial ROI.
self.calculateRegionOfInterest()
}
}
// ocr
// super.viewDidLoad()
}
.
.
.
2nd of Apples Controller "A". Note I tried viewDidLoad
with "public" keyword and without.
import Foundation
import UIKit
import AVFoundation
import Vision
// ocr
// class VisionViewController: ViewController {
class VisionViewController: TextReaderViewController {
var request: VNRecognizeTextRequest!
// Temporal string tracker
let numberTracker = StringTracker()
public override func viewDidLoad() {
// Set up vision request before letting ViewController set up the camera
// so that it exists when the first buffer is received.
// ocr
print("viewDidLoad VisionViewController")
request = VNRecognizeTextRequest(completionHandler: recognizeTextHandler)
super.viewDidLoad()
}
.
.
.
推荐答案
我发现我的表演任务正在执行错误的视图控制器.一旦我更正了该问题,就会按照正确的顺序执行viewDidLoad.
I discovered my perform segue was executing the wrong view controller. Once I corrected that, the viewDidLoad's executed in the correct sequence.
这篇关于在从Objc超类继承的Swift子类中未调用viewDidLoad的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!