Why does adding iOS AdMobs GADBannerView cause sigabrt in AppDelegate (Swift)? - ios

I'm having trouble getting AdMob advertising working in my iOS app.
I'm getting a specific error which I will show you below, but first here is what I've tried.
Here's What I've Tried
Once I got the error in my main app I retrieved the official BannerExample and got it running successfully. BannerView example app runs and I see the ad appear in the app while it's running on my iPhone 5s simulator.
I've done all manner of pod update to insure I have the exact new versions of all required packages and keep in mind that the app builds with no problems.
I've debugged it down to a single line of code that I will show you below.
Now that you know I've done quite a bit of work, take a look at what is happening.
The App Crash
The exact error is :
CYaPass[13155:433036] [MC] Reading from private effective user
settings. Google Mobile Ads SDK version: afma-sdk-i-v7.15.0 2016-12-04
14:37:26.046 CYaPass[13155:432944] -[UIView loadRequest:]:
unrecognized selector sent to instance 0x7f8bf4546090 2016-12-04
14:37:26.055 CYaPass[13155:432944] *** Terminating app due to uncaught
exception
This is not the normal sigabrt on AppDelegate error.
I have tried all the normal things related to StoryBoard and here is an image which shows you I don't have any undefined items that are blowing this up. Plus, I'll show you that when i remove the one line of AdMob code the app will run normally.
You can see that I do have two outlets defined on the UIView that I'm attempting to use for the BannerView. That's so I could test it when I remove the one line of AdMob code.
You can also see those outlets on the SettingsController
You can see them in my actual controller code which looks like the following:
#IBOutlet weak var AdMobs: GADBannerView!
#IBOutlet weak var SuperView: UIView!
func loadAd(){
AdMobs.adUnitID = "ca-app-pub-3940256099942544/2934735716"
AdMobs.rootViewController = self
AdMobs.load(GADRequest())
SuperView.backgroundColor = UIColor.black;
}
I separated those lines into the loadAd() func so I could test them from different locations, but it's the same code that the official BannerExample uses and calls in viewDidLoad() func.
Small Test On UIView
Then, you see I also do a little work on the exact same UIView (SuperView) where I set the backgroundColor to black.
That was to convince myself that it wasn't just becuase I'd attached an outlet to that UIView. But that code works fine, if I simply comment out the three lines before it.
Here, I'll run it and show you the output. Just before I do that, here's my AppDelegate application constructor which doesn't change. It is really a copy of the exact official BannerExample:
import Firebase
import UIKit
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate{
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
FIRApp.configure()
GADMobileAds.configure(withApplicationID: "ca-app-pub-myapp-hiddenforpublicConsumption")
return true
}
Now, I'll change change loadAd() to look like the following and run again:
func loadAd(){
//AdMobs.adUnitID = "ca-app-pub-3940256099942544/2934735716"
//AdMobs.rootViewController = self
//AdMobs.load(GADRequest())
SuperView.backgroundColor = UIColor.black;
}
Obviously, the only change is that I commented those three lines. Here's what it looks like when it runs.
Tabbed View Application
By the way, this is a tabbed app. So the app comes up, I click on the Settings tab and you can see that the altered code in loadAd() runs and turns the background of the UIView black.
Main Point : Specific Code Causes Problem
Now, let me show you that if I uncomment just that first line of Banner Ad code then the app crashes in the AppDelegate.
Here's the altered loadAd() again:
func loadAd(){
AdMobs.adUnitID = "ca-app-pub-3940256099942544/2934735716"
//AdMobs.rootViewController = self
//AdMobs.load(GADRequest())
SuperView.backgroundColor = UIColor.black;
}
Again, you can see that I've only uncommented the one line that sets the adUnitId on the GADBannerView. This is the exact same code that the BannerExample uses. It even uses the same test unitId which is free for everyone's testing. Also, even if you change that unitId to a invalid value the app does not crash, the ad just doesn't show up.
Here's The Result
Debugging Shows Exact Line of Code
I can step into the code and it is exactly on that loadAd() line we just added when this error occurs (shown below for clear reference):
AdMobs.adUnitID = "ca-app-pub-3940256099942544/2934735716"
Only Difference : Tabbed View -- Is That the Issue?
The only effective difference is that my app is based upon the tabbedview.
Does anyone know why this occurs?
I've been trying everything for almost 2 days now. Any help is appreciated.

Oh, the agony...I finally found the answer.
First of all, here you can see I've gained success.
Type of View Must Be Changed
If you go to storyboard and examine that UIView you will see it looks like the following:
However, it kind of makes sense that because it is not a GADBannerView that the error we got looks like:
[UIView setAdUnitID:]: unrecognized selector sent to instance
That was the clue that got me to the answer.
You have to change the value to a GADBannerView (just type it in the box over UIView):
I also confirmed that in the official example that the type is set properly there.
That's about 36 hours I'll never get back.
I missed that step in the initial documentation so this is "error between chair and keyboard".

If anyone else has this same problem and doesn't know what's going on, I had a different problem with a similar error.
Go to the View for the ad, and go down to where it says Label. Change that to your view's name, it worked for me.
Also make sure module is empty, and inherit module from target is unticked.

Related

EA showBluetoothAccessoryPicker not showing in SwiftUI

I have created a small program that needs to connect to an external accessory. I have been able to do so successfully with UIKit and the EA framework.
The problem I am having is that I have a SwiftUI based app that needs to use the External Accessory but when I call the showBluetoothAccessoryPicker function, the picker window does not show.
What I have tried so far:
I have read that you need to have the app delegate with
var window: UIWin
setup correctly to see the picker window. So I created a class
class AppDelegate: UIApplicationDelegate
{
var window: UIWindow?
}
I then associated the app delegate with my swiftui "App" struct like this:
#main
struct POC: App {
#UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
var body: some Scene {
WindowGroup {
TabSelectionView()
}
}
}
Nevertheless, when I call showBluetoothAccessoryPicker the picker window does not show.
I see the following in the output log:
2021-09-20 13:16:31.804796-0500 POC[2150:1514447] IAPDHasLaunched: kIAPAvailableNotification iapdAvailableState 0 -> 0
2021-09-20 13:16:31.805791-0500 POC[2150:1514447] IAP2DHasLaunched: kIAP2AvailableNotification iap2dAvailableState 0 -> 0
2021-09-20 13:16:31.807219-0500 POC[2150:1514447] -[EAAccessoryManager _initFromSingletonCreationMethod] isRunningOnMac
This log appears correct and matches the output from a working demo app that uses UIKit. It's just that the picker window does not show.
Does anybody know what needs to be done to get the picker window to appear correctly for SwiftUI apps? Is there any SwiftUI examples of connecting to an External Accessory that anybody could point me towards?
Thanks in advance for any help.
UPDATE: It's also broken in UIKit! Feedback reported as FB9856371.
Apparently the new UIScene-based mechanism kills it (and since SwiftUI is based on the new scene-based mechanism, it only looks like it's a problem with SwiftUI).
If you roll back to the UIApplicationDelegate-based lifecycle, it works again.
OLD ANSWER:
It's just broken in SwiftUI right now.
Further experimentation shows that the EAExternalAccessory picker seems to query the UIApplicationDelegate's window property to find out where to display itself in.
Alas, that being an optional property, which is not implemented in the SwiftUI's version of the AppDelegate, it only gets nil and does not show up.
It also seems that the #UIApplicationDelegateAdaptor approach does not work in this case, because it does not really act as a stand-in for the real app delegate, but rather gets the methods forwarded.
A way to work around this is to use the UIKit application lifecycle and present your SwiftUI app via the UIHostingController.
It might also be possible to hack this via method swizzling, but if so, I don't know how.
Please open a bug report.

Crash when instantiating ARSCNView for the second time

I have a problem in my iPhone app when trying to instantiate an ARSCNView again, after destroying it.
In my ViewController I programmatically create an ARSCNView for motion capture interaction:
func addARSceneView() {
arSceneView = ARSCNView(frame: self.view.frame)
arSceneView.loops = true
arSceneView.session.delegate = self
self.view.addSubview(arSceneView)
arSceneView.session.run(ARBodyTrackingConfiguration())
}
When the user leaves this part of the app, I tear it down like this:
func removeARSceneView() {
arSceneView.session.pause()
arSceneView.pause(self)
arSceneView.session.delegate = nil
arSceneView.removeFromSuperview()
arSceneView = nil
}
Later, when I try to instantiate an ARSCNView for the second time using the first function above, it crashes with an EXC_BAD_ACCESS in the constructor:
I also tried to use a view from a xib which contains an ARSCNView but the same problem occurs, in that case in the init(coder) function of that view.
I found nothing on this problem, I guess usually developers only create an ARSCNView once.
TLDR: Turn "Metal API Validation" on in your scheme.
I found the culprit, after creating a sample project with only the ARSCNView, which did not have this problem. I started by stripping everything away from my original project until it was as barebones as the sample. That did not solve it, so I compared every little setting of the two, and behold: in the "Run" scheme of the original project, under "Diagnostics", I had "Metal – API Validation" ticked off. I don't remember when and why I did that; I assume it was some attempt to improve performance at one point. However, enabling this checkbox solved the problem completely.

Why Google Maps crashes with "Attempt to set an unknown enum value" error?

I use 3.1.0 version of Google Maps SDK for iOS. When assigning view to GMSMapView in loadView function, app crashes with following error: 'NSInvalidArgumentException', reason: 'GMSx_GMMClientPropertiesRequestProto.screenPixelDensity: Attempt to set an unknown enum value (0)'. It is really strange why it happens. I tried to downgrade version of Google Maps, but it didn't help. In AppDelegate, I provide API_KEY. Here is my code, how I use Google Maps:
lazy var mapView: GMSMapView = GMSMapView(frame: .zero)
override func loadView() {
super.loadView()
view = mapView
}
What is the reason why this error occurs and how it can be solved?
UPDATE-1:
I made a little experiment and tested in several devices with following simple code:
override func viewDidLoad() {
super.viewDidLoad()
let mapView = GMSMapView()
let dummyView = UIView()
dummyView.backgroundColor = .purple
view = mapView
}
This code successfully shows a map on iPhone 7, but fails with the same error on iPhone SE. Both devices running on iOS 12.3.1. It fails on initialising mapView, not on setting it to view. Even when I set dummyView to view, it crashes, because I initialised mapView.
UPDATE-2:
Tried to avoid initialising mapView variable myself. Created storyboard, added view and indicated that the class is GMSMapView and connected to my view controller. Removed all above code from VC. Worked in iPhone 7, failed in iPhone SE with the same error.
UPDATE-3:
Created new project and used the same API_KEY to show maps. It worked in iPhone SE! It means, problem is not in device, it is in project. Still don't know where it is, but maybe in Pods.
Finally, after the all updates above, I came up with an idea that I should delete the app in my phone and run it again. Then, it worked! I don't know why it has worked. Possibly, this error occurs only in debug version of the app.
I am using localization in my app and when I changed the languages, I was also adding the following code:
UserDefaults.standard.setValue(lang, forKey: "AppleLanguages")
UserDefaults.standard.synchronize()
So by commenting it, and then reinstalling my app, it worked!

Xcode: LaunchScreen.storyboard is not showing up

I'm trying to set up the launch screen and initial view of my app. However, I can't get either to show up.
I have this set up:
Am I missing a step? Shouldn't I be seeing a page with "blah" on it as the launch screen? Instead, when I run the simulator it's just black.
Also, I don't understand why my initial view isn't showing up either.
In my AppDelegate.swift file:
import UIKit
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
self.window?.rootViewController = self.rootViewController()
return true
}
private func rootViewController() -> UIViewController {
return MapViewController.init()
}
}
And my MapViewController.swift:
import UIKit
class MapViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
var label = UILabel(frame: CGRectMake(0, 0, 200, 21))
label.center = CGPointMake(160, 284)
label.textAlignment = NSTextAlignment.Center
label.text = "I am a test label"
self.view.addSubview(label)
NSLog("heyyyy!!") // <----------------- doesn't get printed either, so I think I'm missing something again...
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
}
*/
}
Sorry for the noob questions.
== UPDATE ==
I do get these 2 warnings when I build it:
file:///Users/emai/Documents/ios/Sherpa/SherpaNewYork/LaunchScreen.storyboard: warning: Unsupported Configuration: Scene is unreachable due to lack of entry points and does not have an identifier for runtime access via -instantiateViewControllerWithIdentifier:.
/Users/emai/Documents/ios/Sherpa/SherpaNewYork/LaunchScreen.storyboard:9: Scene is unreachable due to lack of entry points and does not have an identifier for runtime access via -instantiateViewControllerWithIdentifier:.
I also struggled with a launchscreen storyboard not showing up. I tried everything fix I could find to no avail. Then I cleared the cache on my Simulator and it worked! Turned out it was a simulator problem. I cleared the cache with this command in terminal: xcrun simctl erase all
It looks like you haven't set up your storyboards with an entry point. Set up the first scene you want to show as the Initial View Controller
sure, this answer is a little late. ;-) Had the some problem but i fortuitous found a quiet simple solution using the Launch Screen.storyboard created with the app automatic.
Open the App-Settings and there App Icons and Launch Images
Select Launch Screen.storyboard in the DropDown-List, even when u think, this is already selected. The display of the screen won´t change after selecting. But when restart the project, the Launch Screen was showed!
BTW to test this tidy, u can set a breakpont in the last line of
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?)
After trying every other answer here, I finally deleted the LaunchScreen.Storyboard file and created a new one. This was the only thing that fixed the issue for me.
had the same problem with the launchscreen. As mentioned from Abizern, there is no ViewController allowed. If you had one only deleting this one will not be enough some times. The LaunchScreen file could still have some connections to the ViewController which is not available any more. This is a problem, too.
My fix:
Delete ViewController for LaunchScreen
Removed connections in LaunchScreen.storyboard
Removed app from Device
Reinstall
-> Worked :)
What you are missing is that a launch screen is static! It does not need a controller or anything. A controller will not do anything. For the launch screen you can design the UI only using the interface builder, not via code.
Xcode should generally tell you that, if you try to set a custom controller on the launch screen view it results in an error.
So deleting the LaunchScreen.storyboard + LaunchScreenViewController.swift files and adding a Launch Screen.xib file worked in fixing the launch screen. This makes sense to me since the launch screen should be static and not use code.
However the view is still black after the launch screen. I'll make another SO question for that.
i know it is very late but i want to share how i fixed it, if you are checking on real device then try to delete the app first, restart the handset and then reinstall the app. it will be fixed if you have followed all steps like clearing cache and settings in Target - General Tab etc.
In my case, the project navigator file filter was set to "recent". See bottom left of Xcode. I unselected recent, and the file showed up.
Easiest solution is to uninstall and reinstall the app when testing in the simulator. No need to remove and re-create LaunchScreen.Storyboard.

Issues with Today Widget extension

I have a Today Widget for my app, however I have been told about an issue with it.
Basically, what seems to be happening (I can't test this for myself) is that the widget will sometimes just display 'unable to load' and other times it will just display with a height of 0.
I can't really see why this is happening. I've tested it out on my device and the simulator for weeks now and have never ran into this issue.
I was wondering if it could possibly be down to the refresh code:
func widgetPerformUpdateWithCompletionHandler(completionHandler: ((NCUpdateResult) -> Void)!) {
// Perform any setup necessary in order to update the view.
var defaults = NSUserDefaults(suiteName: "group.AffordIt")
var newCheck = defaults.boolForKey("new")
if newCheck == true {
completionHandler(NCUpdateResult.NewData)
} else {
completionHandler(NCUpdateResult.NoData)
}
}
'newCheck' is true whenever something changes within my app that needs to be displayed in the widget.
Does anyone know what the possible causes of these issues are?
"unable to load" message appears if your extension crashes often. You can try to re-enable it by removing and adding the extension again.
Are you using your own view controller and xib instead of using storyboard? If yes, it is probably that you didn't set the preferredContentSize in your view controller.
try to put the following code in the init function of ur view controller:
self.preferredContentSize = CGSizeMake(320, 100);
I have just began the extension programming today so I am not sure is it really helpful for u or not. Here is the result in my own widget:
Press Edit button in today extensions
Remove your extension
Add your extension again.

Resources