- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
SwiftViewController 对象的初始化函数没有执行(我什至不相信它被调用了)。我在 init 函数中设置了一个断点,调试器永远不会停在那里。这项目未使用 Storyboard、xib 或 nib 文件。我已按照 this question 中的建议将 init public
设置为.
Objective-c UIViewController 工作正常,所以我可以看到其中一个选项卡。
当我单步执行 didFinishLaunchingWithOptions 及其子函数中的 AppDelegate 代码时,SwiftViewController 对象中的所有指针和值都为零或零。所以对象被创建,但没有被初始化。
SwiftViewController 在独立的 Swift 应用程序中完美运行。
我是否遗漏了头文件中的任何内容?我需要做什么才能在 AppDelegate 中执行对 init 的调用?
我再次对问题的冗长感到遗憾。
我在 SO 上检查了以下问题:
背景
OSX - 埃尔卡皮坦Xcode - 版本 8.2 (8C38)在模拟器中运行。
编程挑战:
使用 Objective-C 创建静态库或 iOS 框架,执行以下 3 个功能: - 收集用户在某个时间点的GPS位置(经纬度) - 收集电池状态并返回设备是否已插入以及剩余电量百分比。 - 访问任何公开可用的免费 API 以收集您选择的数据并将其返回 (这应该是网络调用)
使用 3 个按钮和一个可以显示文本的标签构建一个简单的应用程序。每个按钮都应调用上述库的三个函数并将响应输出到标签。
您的应用程序应包含两个选项卡,一个用 Objective-C 编写,一个用 Swift 编写。这两个选项卡应调用相同的 Objective-C 库并执行相同的功能。
仅使用 Apple 框架来完成此任务。完整注释您的代码,解释您的逻辑和选择,其中有多种选择。例如,Apple 提供了多种方法来检索网络资源,记录您选择该解决方案的原因。
请将完整的单个 Xcode 项目发送给我。
信息.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
<key>NSLocationAlwaysUsageDescription</key>
<string>This application requires location services to work</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>This will be used to obtain your current location.</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
</dict>
</plist>
AppDelegate.m
//
// AppDelegate.m
// TabbedOCandSwift
//
// Created by Paul Chernick on 4/18/17.
//
#import "AppDelegate.h"
#import "ObjectiveCViewController.h"
#import "TabbedOCandSwift-Swift.h"
@interface AppDelegate ()
@end
@implementation AppDelegate
@synthesize dataModelLibrary = _dataModelLibrary;
- (BOOL) dataModelLibraryInitialize {
BOOL libraryCreatedAndInitialized = YES;
if (!self.dataModelLibrary || !_dataModelLibrary) {
PCI7DataModelLibrary *tempLibPtr = [[PCI7DataModelLibrary alloc] init];
if (!tempLibPtr) {
// If the library can't be allocated or initialized none of the buttons will work in any view controller.
NSLog(@"application didFinishLaunchingWithOptions: Unable to alloc or init the PCI7DataModelLibrary object");
return NO;
}
_dataModelLibrary = tempLibPtr;
}
return libraryCreatedAndInitialized;
}
- (BOOL) createTabBarAndViewControllers {
ObjectivCViewController* objectiveVC = nil;
SwiftViewController* swiftVC = nil;
self.tabBarController = [[UITabBarController alloc] init];
objectiveVC = [[ObjectivCViewController alloc] init];
if (objectiveVC) {
[objectiveVC setTitle:@"Objective-C"];
}
else {
NSLog(@"In AppDelegate.createTabBarAndViewControllers: Unable to create objectiveVC");
return NO;
}
swiftVC = [[SwiftViewController alloc] init];
if (swiftVC) {
[swiftVC setTitle:@"Swift"];
}
else {
NSLog(@"In AppDelegate.createTabBarAndViewControllers: Unable to create swiftVC");
return NO;
}
// NSArray* controllers = [NSArray arrayWithObjects:objectiveVC, swiftVC, nil];
NSArray* controllers = [NSArray arrayWithObjects:swiftVC, objectiveVC, nil];
self.tabBarController.viewControllers = controllers;
self.tabBarController.selectedIndex = 0;
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window.rootViewController = self.tabBarController;
[self.window makeKeyAndVisible];
return YES;
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Create the library object if it hasn't already been created
// There should only be one copy of the library.
// - Reduce memory usage, devices have limitied memory, no app should use more than it needs and only one library is necessary.
// - There is a runtime cost to starting up the library, if it is done once early in the life of the application
// the user will notice it less than when a viewcontroller starts or resumes.
// - There is asyncronous code that runs in the library in a serial manner to reduce possible interactions and prevent deadlock only one library should exist.
if (![self dataModelLibraryInitialize]) {
// If the library can't be allocated or initialized none of the buttons will work in any view controller.
NSLog(@"application didFinishLaunchingWithOptions: Unable to alloc or init the PCI7DataModelLibrary object");
return NO;
}
if (![self createTabBarAndViewControllers]) {
return NO;
}
return YES;
}
- (void)applicationWillResignActive:(UIApplication *)application {
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
}
- (void)applicationDidEnterBackground:(UIApplication *)application {
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}
- (void)applicationWillEnterForeground:(UIApplication *)application {
// Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}
- (void)applicationWillTerminate:(UIApplication *)application {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
// Saves changes in the application's managed object context before the application terminates.
[self saveContext];
}
#pragma mark - Core Data stack
@synthesize persistentContainer = _persistentContainer;
- (NSPersistentContainer *)persistentContainer {
// The persistent container for the application. This implementation creates and returns a container, having loaded the store for the application to it.
@synchronized (self) {
if (_persistentContainer == nil) {
_persistentContainer = [[NSPersistentContainer alloc] initWithName:@"DevAndNetInfo2"];
[_persistentContainer loadPersistentStoresWithCompletionHandler:^(NSPersistentStoreDescription *storeDescription, NSError *error) {
if (error != nil) {
// Replace this implementation with code to handle the error appropriately.
// abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
/*
Typical reasons for an error here include:
* The parent directory does not exist, cannot be created, or disallows writing.
* The persistent store is not accessible, due to permissions or data protection when the device is locked.
* The device is out of space.
* The store could not be migrated to the current model version.
Check the error message to determine what the actual problem was.
*/
NSLog(@"Unresolved error %@, %@", error, error.userInfo);
abort();
}
}];
}
}
return _persistentContainer;
}
#pragma mark - Core Data Saving support
- (void)saveContext {
NSManagedObjectContext *context = self.persistentContainer.viewContext;
NSError *error = nil;
if ([context hasChanges] && ![context save:&error]) {
// Replace this implementation with code to handle the error appropriately.
// abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
NSLog(@"Unresolved error %@, %@", error, error.userInfo);
abort();
}
}
@end
AppDelegate.h
//
// AppDelegate.h
// DevAndNetInfo2
//
// Created by Paul Chernick on 4/18/17.
//
#import <UIKit/UIKit.h>
#import <CoreData/CoreData.h>
#import "PCI7DataModelLibrary/PCI7DataModelLibrary/PCI7DataModelLibrary.h"
@interface AppDelegate : UIResponder <UIApplicationDelegate>
@property (strong, nonatomic) UIWindow *window;
@property (readonly, strong) NSPersistentContainer *persistentContainer;
@property (strong) UITabBarController *tabBarController;
// Create the library as a property so that consumer objects can use a getter to receive a pointer to it.
// Prevent objects that use the library from changing it.
@property (readonly, strong) PCI7DataModelLibrary *dataModelLibrary;
- (void)saveContext;
@end
TabbedOCandSwift-Bridging-Header.h
//
// Use this file to import your target's public headers that you would like to expose to Swift.
//
#import "AppDelegate.h"
SwiftViewController.swift
//
// SwiftViewController.swift
// SwiftTabForApp
//
import UIKit
@objc class SwiftViewController: UIViewController {
class SwiftViewController: UIViewController {
var getGPSLongitudeAndLatitudeWithTimeStamp : UIButton?
var getBatteryLevelAndState : UIButton?
var getNextorkImplementation : UIButton?
var displayButtonAction : UILabel?
var screenTitle : UILabel?
var displayDataModel : PCI7DataModelLibrary?
// The following variables are used in multiple functions. They are constant during the display of the super view
// and control the size of the subviews. They should change when the orientation changes
var selfWidth : CGFloat = 0.0
var buttonHeight : CGFloat = 0.0
var viewElementWidth : CGFloat = 0.0
var buttonYCenterOffset : CGFloat = 0.0 // The y center should be half the value of the height
var buttonXCenter : CGFloat = 0.0 // Center the button title relative to the width of the button and the width of the super view
var buttonXInit : CGFloat = 0.0
var buttonVerticalSeparation : CGFloat = 0.0
var startingVerticalLocation : CGFloat = 0.0
var displayLabelHeight: CGFloat = 75.0
// TODO: This function should be altered so that all values are calculated on screen height and screen width,
// this will allow for changes in orientation.
func initFramingValuesOfMyDisplay() {
selfWidth = self.view.bounds.size.width
buttonHeight = 20.0 // This should be programmable in relative to self.view.bounds.size.height
viewElementWidth = 0.85 * selfWidth;
buttonXCenter = selfWidth / 2.0; // Center the button title relative to the width of the button and the width of the super view
buttonXInit = (selfWidth - viewElementWidth) / 2.0; // 10 percent margin on the left leaves a 10% margin on the right as well
buttonYCenterOffset = buttonHeight / 2.0; // The y center should be half the value of the height
buttonVerticalSeparation = buttonHeight + buttonYCenterOffset;
startingVerticalLocation = 250.0; // 430 was chosen based on experimentation in the simulator
}
// This function is called when the getGPSLongitudeAndLatitudeWithTimeStamp button is receives the touchUpInside event.
func setLabelWithGPSLatitudeAndLongitudeWithTimeStampData()
{
var actionString : String = "Testing Label Text"
if (self.displayDataModel != nil) {
actionString = (self.displayDataModel?.provideGPSLocationData())!
}
else {
actionString = "GPS Button Action Failure: Data Model not created"
}
DispatchQueue.main.async {
self.displayButtonAction?.text = nil
self.displayButtonAction?.text = actionString
}
}
// This function is called when the getBatteryLevelAndState button is receives the touchUpInside event.
func setLabelWithBatteryLevelAndState() {
var actionString : String = "Get Battery Level and State";
if (self.displayDataModel != nil) {
actionString = (self.displayDataModel?.provideBatteryLevelAndState())!
}
else {
actionString = "Battery Button Action Failure: Data Model not created"
}
DispatchQueue.main.async {
self.displayButtonAction?.text = nil
self.displayButtonAction?.text = actionString
}
}
// This function is called when the getNextorkImplementation button is receives the touchUpInside event.
func setLabelActionNetwork() {
var actionString :String = "Fake Button set to American Express Stock Price"
if (self.displayDataModel != nil) {
actionString = (self.displayDataModel?.provideNetworkAccessData())!
}
else {
actionString = "Network Button Action Failure: Data Model not created"
}
DispatchQueue.main.async {
self.displayButtonAction?.text = nil
self.displayButtonAction?.text = actionString
}
}
func makeAButton(yButtonStart : CGFloat, buttonTitle: String, underSubview: UIView?) -> UIButton
{
let thisButton = UIButton.init(type: .system)
thisButton.frame = CGRect(x: buttonXInit, y: yButtonStart, width: viewElementWidth, height: buttonHeight)
thisButton.setTitle(buttonTitle, for:UIControlState.normal)
thisButton.backgroundColor = UIColor.yellow
thisButton.setTitleColor(UIColor.black, for: UIControlState.normal)
if ((underSubview) == nil) {
self.view.addSubview(thisButton)
}
else {
self.view.insertSubview(thisButton, belowSubview:underSubview!)
}
return thisButton;
}
func makeALabel(yLabelStart : CGFloat, height: CGFloat, underSubview: UIView?) -> UILabel
{
let thisLabel = UILabel.init()
thisLabel.frame = CGRect(x: buttonXInit, y: yLabelStart, width: viewElementWidth, height: height)
thisLabel.font = thisLabel.font.withSize(12) // Reduce the size of the text so that more output fits on a single line
thisLabel.lineBreakMode = .byWordWrapping;
thisLabel.numberOfLines = 0; // Allow the label to grow as necessary
thisLabel.textAlignment = NSTextAlignment.center;
thisLabel.textColor = UIColor.black;
if ((underSubview) == nil) {
self.view.addSubview(thisLabel)
}
else {
self.view.insertSubview(thisLabel, belowSubview:underSubview!)
}
return thisLabel;
}
override func viewDidLoad() {
super.viewDidLoad()
// rather than assume a particular background color, set the background color so that everything can be seen.
self.view.backgroundColor = UIColor.white
initFramingValuesOfMyDisplay()
if (!self.displayModelLibraryInitialization())
{
addButtonAndLabels()
}
self.view.backgroundColor = UIColor.white
}
func addButtonAndLabels() -> Void {
// If the width of the screen hasn't been used as a base for the size of the sub-views then
// this function is not ready to generate the sub-views.
if (selfWidth < 1.0) {
return;
}
var viewElementVerticalLocation: CGFloat = startingVerticalLocation;
self.screenTitle = makeALabel(yLabelStart: viewElementVerticalLocation, height: buttonHeight, underSubview: nil)
self.screenTitle?.text = "Swift Implementation"
viewElementVerticalLocation += buttonVerticalSeparation
viewElementVerticalLocation += buttonVerticalSeparation
// To prevent memory leaks only create the UIView object if it hasn't already been created
// if (self.getGPSLongitudeAndLatitudeWithTimeStamp == nil) {
self.getGPSLongitudeAndLatitudeWithTimeStamp = makeAButton(yButtonStart: viewElementVerticalLocation, buttonTitle: "Get GPS Location with TimeStamp", underSubview: nil)
self.getGPSLongitudeAndLatitudeWithTimeStamp?.addTarget(self, action: #selector(setLabelWithGPSLatitudeAndLongitudeWithTimeStampData), for: .touchUpInside)
viewElementVerticalLocation += buttonVerticalSeparation
// }
// if (self.getGPSLongitudeAndLatitudeWithTimeStamp == nil) {
self.getBatteryLevelAndState = makeAButton(yButtonStart: viewElementVerticalLocation, buttonTitle: "Get Battery Level and State", underSubview: getGPSLongitudeAndLatitudeWithTimeStamp)
self.getBatteryLevelAndState?.addTarget(self, action: #selector(setLabelWithBatteryLevelAndState), for: .touchUpInside)
viewElementVerticalLocation += buttonVerticalSeparation
// }
// if (self.getNextorkImplementation == nil) {
self.getNextorkImplementation = makeAButton(yButtonStart: viewElementVerticalLocation, buttonTitle: "Get American Express Stock Price", underSubview: getBatteryLevelAndState)
self.getNextorkImplementation?.addTarget(self, action: #selector(setLabelActionNetwork), for: .touchUpInside)
viewElementVerticalLocation += buttonVerticalSeparation
// }
// if (self.displayButtonAction == nil) {
self.displayButtonAction = makeALabel(yLabelStart: viewElementVerticalLocation, height: displayLabelHeight, underSubview: getNextorkImplementation)
// }
}
func displayModelLibraryInitialization() -> CBool {
if (self.displayDataModel == nil) {
if let myDelegate = UIApplication.shared.delegate as? AppDelegate {
self.displayDataModel = myDelegate.dataModelLibrary;
}
}
return (self.displayDataModel == nil)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
public required init(coder aDecoder: NSCoder) {
super.init(nibName: nil, bundle: nil)
if (self.displayDataModel == nil) {
if (self.displayModelLibraryInitialization()) {
abort()
}
self.getGPSLongitudeAndLatitudeWithTimeStamp = nil
self.getGPSLongitudeAndLatitudeWithTimeStamp = nil
self.getNextorkImplementation = nil
self.screenTitle = nil
self.displayButtonAction = nil
}
initFramingValuesOfMyDisplay()
}
public init() {
super.init(nibName: nil, bundle: nil)
if (self.displayDataModel == nil) {
if (self.displayModelLibraryInitialization()) {
abort()
}
self.getGPSLongitudeAndLatitudeWithTimeStamp = nil
self.getGPSLongitudeAndLatitudeWithTimeStamp = nil
self.getNextorkImplementation = nil
self.screenTitle = nil
self.displayButtonAction = nil
}
initFramingValuesOfMyDisplay()
}
}
}
最佳答案
@objc class SwiftViewController: UIViewController {
class SwiftViewController: UIViewController {
// ... your methods ...
}
}
定义两个类:
SwiftViewController
和SwiftViewController.SwiftViewController
在
swiftVC = [[SwiftViewController alloc] init];
你创建了一个不覆盖的“外部”类的实例任何 UIViewController
方法。特别是嵌套类的 init
方法没有被调用。 (无论如何,嵌套类对 Objective-C 运行时是不可见的。)
所以你想要的是
@objc class SwiftViewController: UIViewController {
// ... your methods ...
}
相反(你可以省略 @objc
因为类已经继承自 NSObject
)。
关于ios - 从 Objective-C AppDelegate 调用时,Swift UIViewController init 不执行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43698561/
何时使用 init、带参数的 init 或 iOS 8 (Swift) 中的便利 init, Objective-C 中的 convenience init 等价于什么? 最佳答案 你的类将有一个必需
我正在阅读这个 First Search Program - Artificial Intelligence for Robotics 算法,我正在阅读它的 Python 代码。在这里,我们创建了一个
我觉得答案很明显,但我一直无法弄清楚,这对我来说似乎是一个反复出现的问题。基本上我想做这样的事情: extension NSData { convenience init(JSONObject
cloud-init 是在首次启动时在虚拟机上执行各种配置的包。您必须使用您的配置配置一个文件,然后将其扔到您的 VM 上,然后对其进行虚拟化。 但它究竟是如何工作的呢?用户数据如何发送到 VM,cl
我目前正在与 CoreOS 打交道,到目前为止,我认为我已经掌握了总体思路和概念。我还没有得到的一件事是执行 cloud-init . 我明白 cloud-init是一个为 CoreOS 做一些配置的
部署项目后,当客户端第一次向 TestServlet 发送请求时,服务器会创建 testServlet 对象,然后调用第一个 init() 方法(init(ServletConfig config))
是否有可能在 convenience init 中以某种方式解包可选 init? convenience init(...) { self.init?(...) ?? self.init() }
使用时 write_files使用 cloud-init,是否可以附加内容?如果是这样,如何? write_files: [ { "path": "/home/user/some-file
我对 Ansible 比较陌生,我创建了一个剧本,可以在“裸”服务器上安装 Tomcat 配置。我想知道如何解决能够更新 init.d 脚本的问题,同时避免在脚本没有更改时在剧本开始时停止服务。这是基
我打算在 iOS 中使用参数调用 init 方法中的默认 init 方法。像这样: -(id)init{ self = [super init]; if (self) {
Objective C 规范(来自 Apple)第 49 页指出每个声明实例变量的类都必须提供一个 init 方法来初始化它们 我的问题 -为什么这是必要的? NSObject 不会为实例初始化 iV
所以我有一个带有指定初始化器的类,它为每个存储的属性取值。我所有存储的属性也有一个默认值,所以我假设这个类有一个默认的初始化。 在我指定的 init 中,我调用 super.init() 问题是,如果
我对此有些困惑: class Person { var name: String var age: Int init(){ name = “Tim”
我有一个带有两个初始化方法的对象。其中一个接受 NSDictionary,另一个接受一大堆 String 变量。我想调用 NSDictionary init,然后从那里将我的字典转换为字符串,然后用我
我正在尝试为我的类创建一个方便的初始化:User。我之前为另一个类(class)做过这个,并且 - 再次创建它 - 我使用了相同的代码,只是我的用户类(class)有所不同。 这是我的用户类: imp
我已经通读了以下秘诀,它展示了一种使用 Google Cloud Endpoints 后端为 AngularJS 前端提供动力的方法: https://cloud.google.com/resourc
本文整理了Java中com.netflix.zuul.init.ZuulFiltersModule.()方法的一些代码示例,展示了ZuulFiltersModule.()的具体用法。这些代码示例主要来
我想实现一个 初始化 下功能 box.once() 在 Tarantool 中只执行一次,但是,只有在 时才对我有用初始化 已成功执行。 问题 : 如何使“onceinit”记录只有在 init 成功
如果在Xcode中创建新的游戏模板项目,则默认GameViewController将使用以下初始化程序实例化游戏场景: let scene = SKScene(fileNamed: "GameScen
我有一个 MKPolyline我要实现的 subblas NSCoding , IE。 @interface RSRoutePolyline : MKPolyline I asked a quest
我是一名优秀的程序员,十分优秀!