Swift appdelegate error - appdelegate does not not confirm to protocol - swift

there are some codes i am writting.
import UIKit
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, XPageViewControllerDataSource {
var window: UIWindow?
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Override point for customization after application launch.
self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
let pageVeiwController = XPageviewcontroller()
pageVeiwController.dataSource = self
self.window?.rootViewController = UINavigationController(rootViewController: pageVeiwController)
self.window?.makeKeyAndVisible()
return true
}
func XPageNumberOfControllers() -> NSInteger {
return 5
}
func XPageControllersTitle(index: NSInteger) -> String {
return "ViewController"+"title"+String(index)
}
func XPageWillShowController(index: NSInteger) -> UIViewController {
let vc = ViewController()
return vc
}
}
i am writing a pure coding programme without mainstoryboard in Xcode,
this is my appdelegate.swift, i try to implement the protocol from my XPageViewController.swift, there are 3 functions in protocol which I have already written in appdelegate. And i have also declared in XPageViewController.swift
var dataSource:XPageViewControllerDataSource!
{
didSet{
self.numberOfControllers = self.dataSource.XPageNumberOfController()
self.addViewToSelf()
}
which is using in appdelegate
pageVeiwController.dataSource = self
but still a error occur there,
shows"Type 'AppDelegate' does not conform to protocol 'XPageViewControllerDataSource'"
i almost run out solutions :D
do anyone have any ideas can help me to solve this?

Can you show us what the XPageViewControllerDataSource protocol comprises of?
Command+Click it in Xcode to view the actual protocol.
Either way, when you view the protocol it should show you what the requirements for the protocol are.

Related

Can I expose a Swift function to React Native without using Objective-C (pure swift)?

I wonder if I can expose my func navigateToLoginWidget to React Native. So that it can be triggered from RN.
I have managed to change the Objective-C template that comes with React Native to Swift like so:
import Foundation
import IBMCloudAppID
import BMSCore
import UIKit
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
var bridge: RCTBridge!
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// initializing App ID SDK
let region = AppID.REGION_SOMEWHERE
let backendGUID = "MY_TENANT_ID_FROM_IBM"
AppID.sharedInstance.initialize(tenantId: backendGUID, region: region)
// Initializing React Native front-end with Swift instead of Obj-c template
let jsCodeLocation: URL
jsCodeLocation = RCTBundleURLProvider.sharedSettings().jsBundleURL(forBundleRoot: "index.js", fallbackResource:nil)
let rootView = RCTRootView(bundleURL: jsCodeLocation, moduleName: "MY_PROJECT_NAME", initialProperties: nil, launchOptions: launchOptions)
let rootViewController = UIViewController()
rootViewController.view = rootView
self.window = UIWindow(frame: UIScreen.main.bounds)
self.window?.rootViewController = rootViewController
self.window?.makeKeyAndVisible()
return true
}
func application(_ application: UIApplication, open url: URL, options :[UIApplication.OpenURLOptionsKey : Any]) -> Bool {
return AppID.sharedInstance.application(application, open: url, options: options)
}
func navigateToLoginWidget(_ sender : Any) {
print("clicked")
AppID.sharedInstance.loginWidget?.launch(delegate: SigninDelegate)
}
}
I would normally have this function in another module called SigninDelegate.swift, but I have included it in the same class for explanatory purposes.
According to the official documentation:
Swift doesn't have support for macros so exposing it to React Native
requires a bit more setup but works relatively the same.
So yes, it is possible, but some setup is needed. Check the docs in the link above for the steps you need to follow to set it up.

iOS 13/Facebook SDK error "Unable to find a valid UIWindow"

(To forestall well-intended suggestions, yes I posted this question last week on Facebook's developer forum. No responses yet.)
TL;DR
Facebook SDK 5.8 complains at startup FBSDKLog: Unable to find a valid UIWindow.
The Main Story
In a from-scratch, one-view Xcode 11/iOS 13 project, there is no longer a default UIWindow member associated with the application. (The window per se is still around; you can see it, contained in a UIWindowScene, using the View Hierarchy Debugger in Xcode, or the Reveal app.)
FBSDK 5.8 does seem to be iOS-13-aware, and looks around for it. The relevant code is at line 498 of
https://github.com/facebook/facebook-ios-sdk/blob/master/FBSDKCoreKit/FBSDKCoreKit/Internal/FBSDKInternalUtility.m.
Facebook's code iterates over the application's connectedScenes member, which for me is an empty set. How do I modify my code so that FBSDK finds the window?
Some Hacking
I tried adding the following to scene(_:willConnectTo:options:) but it seems to be too late — the FBSDKLog message has already appeared by then. (So I'm flailing...)
guard let s = (scene as? UIWindowScene) else { return }
self.window = UIWindow(windowScene: s)
The following also failed, but it was just a shot in the dark:
guard let s = (scene as? UIWindowScene) else { return }
self.window = UIWindow(frame: s.coordinateSpace.bounds)
self.window?.windowScene = s
self.window?.rootViewController = ViewController(nibName: nil, bundle: nil)
self.window?.makeKeyAndVisible()
If you don't use the new behaviour and don't mind reverting to the old way, you can try the following
Delete Application Scene Manifest key from Info.plist
Delete SceneDelegate.swift
Add var window: UIWindow?to AppDelegate.swift
import UIKit
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow? // <-- Here
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
// window!.makeKeyAndVisible()
return true
}
}
Add window variable to AppDelegate class
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
Assign UIWindow inside didFinishLaunchingWithOptions
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
window = UIWindow(frame: UIScreen.main.bounds)
if let window = window {
window.makeKeyAndVisible()
self.window = window
}
ApplicationDelegate.shared.application(
application,
didFinishLaunchingWithOptions: launchOptions
)
return true
}

Unexpected non-void return value in void function for return true

I am doing a test based on a tutorial (https://www.youtube.com/watch?v=B6W2Rp8Uumo&feature=youtu.be) before i start my school based major project coding. Everything went well until I faced an error.
Unexpected non-void return value in void function.
I have read other posts about this but was not able to find specifically what i need to change. The code is shown below:
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
var MainVC:MainViewController?
func application(_application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?)
{
MainVC = MainViewController(nibName: "MainViewController", bundle: nil)
let frame = UIScreen.main.bounds
window = UIWindow(frame: frame)
window!.rootViewController = MainVC
window!.makeKeyAndVisible()
return true //this is where the error occurs
}
if someone could help me fix this and explain what this error means that would be awesome!
The method signature should have -> Bool at the end. This tells the compiler that the method will return a boolean value. Check this.

How to share properties between AppDelegate and ViewController, and save before App is terminated

I have a class with properties updated in viewController. I wanted to save the properties when the app goes into background or quit using AppDelegate. I used the following codes but it appears that the properties were not passed to the AppDelegate. Furthermore the applicationWillTerminate codes did not seem to get executed.
// testClass is defined and the properties are updated in viewController, e.g
testClass.status = true // default is false
// I want to save testClass.status when the app goes into background or being terminated using the following:
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var vc = ViewController()
func applicationDidEnterBackground(_ application: UIApplication) {
print(vc.testClass.status) // prints false
//codes to save
}
// save before App is terminated
func applicationWillTerminate(_ application: UIApplication) {
print(vc.testClass.status) // this code did not get executed?
//codes to save
}
}
applicationWillTerminate is called only when a user terminates the app without switching it to background mode.
When the app is active, double press on Home button and terminate the app.
But if you switch the app to the background, and then try to terminate the app, applicationWillTerminate will not be called.
And you are creating an instance of ViewController in AppDelegate
var vc = ViewController()
If you change the testClass property in another ViewController class instance, you won't get that value here. So create a singleton class like this
class TestClass: NSObject {
static let shared = TestClass()
private override init() {
super.init()
}
var status = false
}
Now update the value in any view controller from the singleton class
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
TestClass.shared.status = true
}
}
In AppDelegate save and retrieve the value from UserDefaults
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
TestClass.shared.status = UserDefaults.standard.bool(forKey: "Status")
return true
}
func applicationDidEnterBackground(_ application: UIApplication) {
UserDefaults.standard.set(TestClass.shared.status, forKey: "Status")
}
func applicationWillTerminate(_ application: UIApplication) {
UserDefaults.standard.set(TestClass.shared.status, forKey: "Status")
}
}
Or create a computed property to save the value in UserDefaults whenever it is changed.
class TestClass: NSObject {
static let shared = TestClass()
private override init() {
super.init()
}
var status: Bool {
get {
return UserDefaults.standard.bool(forKey: "Status")
}
set {
UserDefaults.standard.set(newValue, forKey: "Status")
}
}
}
As already mentioned by others you can ignore applicationWillTerminate.
To get notified when the app goes into the background just add an observer in the view controller.
However rather than didEnterBackground I'd recommend to observe willResignActive.
Add the observer in viewDidLoad once
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(forName: UIApplication.willResignActiveNotification, object: nil, queue: nil) { notification in
// save the properties
}
}
Or if you are using multiple view controllers you can add the observer in viewWillAppear and remove it in viewDidDisappear
Side note:
Never create a view controller with the default initializer ViewController() if you are using storyboard. You'll get a brand new instance which is not the storyboard instance.

Pass data from tabBarController to uiviewcontroller embedded in navigationcontroller

I have a custom tab bar controller. each tab contains a viewcontroller embedded in a navigation controller. I get a value for pro_user from the database in appledelegate and set it there. then before CustomTabBarController gets launched (in appledelegate), i set it's "pro_user" property to true or false (this works and CustomTabBarController receives the value from appledelegate).
Now i'm trying to pass this same value to the ViewControllers (ViewController1 and ViewController2). each view controller also has a "pro_user" property.I'm doing this by creating the viewcontroller instances and then setting their pro_user property before embedding each viewcontroller in a navigationcontroller. but neither viewcontroller is actually receiving the value of pro_user which i'm setting in CustomTabBarController. I hope this is clear. How do i pass the value of pro_user from CustomTabBarController to each of the view controllers? programmatically (i'm not using storyboards)
class AppDelegate: UIResponder, UIApplicationDelegate {
var pro_user = true
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions:
[UIApplicationLaunchOptionsKey: Any]?) -> Bool {
window = UIWindow(frame:UIScreen.main.bounds)
window?.makeKeyAndVisible()
let customTabBarController = CustomTabBarController()
customTabBarontroller.pro_user = pro_user
self.window?.rootViewController = customTabBarController
return true
}
}
class CustomTabBarController:UITabBarController{
var pro_user : Bool?
override func viewDidLoad(){
super.viewDidLoad()
let viewController1 = ViewController1()
viewController1.pro_user = pro_user //doesn't work
let firstNavigationController = UINavigationController(rootViewController: viewController1)
let viewController2 = ViewController2()
viewController2.pro_user = pro_user //doesn't work
let secondNavigationController = UINavigationController(rootViewController:viewController2)
viewControllers=[firstNavigationController,secondNavigationController]
}
It looks like you're setting a global setting. If so you may want to consider using UserDefaults.
E.g. with a nice extension:
extension UserDefaults {
var isProUser: Bool {
get {
return bool(forKey: "isProUser")
}
set {
set(newValue, forKey: "isProUser")
}
}
}
Then anywhere in your app you can set it:
UserDefaults.standard.isProUser = true
And get it:
let isProUser = UserDefaults.standard.isProUser
The value is also saved between launches.