シュミレーションした直後に アプリケーションが停止されます。広告の貼り方に問題があるようなのですが、どこに問題があるのかわかりません。
キャッチされていない例外 'NSInvalidArgumentException' とは何のことですか?。どうすればエラーが解消されるでしょうか。
エラーコード↓
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'NSLayoutConstraint for <GADBannerView: 0x7fdb4361d8f0; frame = (0 0; 320 50); clipsToBounds = YES; layer = <CALayer: 0x6000028cd7e0>>: Constraint items must each be a view or layout guide.'
*** First throw call stack:
(
0 CoreFoundation 0x000000010ba238db __exceptionPreprocess + 331
1 libobjc.A.dylib 0x000000010afc6ac5 objc_exception_throw + 48
2 Foundation 0x00000001080d5045 +[NSLayoutConstraint constraintWithItem:attribute:relatedBy:toItem:attribute:multiplier:constant:] + 0
3 Foundation 0x00000001080d5095 +[NSLayoutConstraint constraintWithItem:attribute:relatedBy:toItem:attribute:multiplier:constant:] + 80
4 gokuTimer 0x0000000105840db8 $sSo18NSLayoutConstraintC4item9attribute9relatedBy6toItemAD10multiplier8constantAByp_So0A9AttributeVSo0A8RelationVypSgAJ12CoreGraphics7CGFloatVAPtcfCTO + 424
5 gokuTimer 0x000000010584097f $s9gokuTimer14ViewControllerC09addBannerc2ToC0yySo09GADBannerC0CF + 1215
6 gokuTimer 0x000000010583ede7 $s9gokuTimer14ViewControllerC11viewDidLoadyyF + 455
7 gokuTimer 0x0000000105840164 $s9gokuTimer14ViewControllerC11viewDidLoadyyFTo + 36
8 UIKitCore 0x00000001140b00f7 -[UIViewController loadViewIfRequired] + 1183
9 UIKitCore 0x0000000114013cf0 -[UINavigationController _updateScrollViewFromViewController:toViewController:] + 68
10 UIKitCore 0x0000000114013fe3 -[UINavigationController _startTransition:fromViewController:toViewController:] + 146
11 UIKitCore 0x00000001140150a1 -[UINavigationController _startDeferredTransitionIfNeeded:] + 896
12 UIKitCore 0x0000000114016393 -[UINavigationController __viewWillLayoutSubviews] + 150
13 UIKitCore 0x0000000113ff7041 -[UILayoutContainerView layoutSubviews] + 217
14 UIKitCore 0x0000000114b91e69 -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 1417
15 QuartzCore 0x0000000108fbdd22 -[CALayer layoutSublayers] + 173
16 QuartzCore 0x0000000108fc29fc _ZN2CA5Layer16layout_if_neededEPNS_11TransactionE + 396
17 QuartzCore 0x0000000108fced58 _ZN2CA5Layer28layout_and_display_if_neededEPNS_11TransactionE + 72
18 QuartzCore 0x0000000108f3e24a _ZN2CA7Context18commit_transactionEPNS_11TransactionE + 328
19 QuartzCore 0x0000000108f75606 _ZN2CA11Transaction6commitEv + 610
20 UIKitCore 0x00000001146cc2c3 __34-[UIApplication _firstCommitBlock]_block_invoke_2 + 128
21 CoreFoundation 0x000000010b98acbc __CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK__ + 12
22 CoreFoundation 0x000000010b98a480 __CFRunLoopDoBlocks + 336
23 CoreFoundation 0x000000010b984d04 __CFRunLoopRun + 1252
24 CoreFoundation 0x000000010b9844d2 CFRunLoopRunSpecific + 626
25 GraphicsServices 0x000000010e9b42fe GSEventRunModal + 65
26 UIKitCore 0x00000001146b2fc2 UIApplicationMain + 140
27 gokuTimer 0x000000010584f3bb main + 75
28 libdyld.dylib 0x000000010ce62541 start + 1
29 ??? 0x0000000000000001 0x0 + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb)
ViewController
import UIKit
import GoogleMobileAds
class ViewController: UIViewController, GADBannerViewDelegate {
@IBOutlet weak var characterImage: UIImageView!
@IBOutlet weak var timerlabel: UILabel!
@IBOutlet weak var startButton: UIButton!
var bannerView: GADBannerView!
override func viewDidLoad() {
super.viewDidLoad()
/*******ad**********************************************************/
//In this case, we instantiate the banner with desired ad size.
bannerView = GADBannerView(adSize: kGADAdSizeBanner)
addBannerViewToView(bannerView)
bannerView.adUnitID = "ca-app-pub-3940256099942544/2934735716"
bannerView.rootViewController = self
bannerView.load(GADRequest())
bannerView.delegate = self
/******************************************************************/
SkillModal.shared.load()
if let myTitle = SkillModal.shared.fastSkill(){ //This is change
self.title = myTitle.title
} else {
let alert = UIAlertController(title: "Title Name", message: "Please enter new name", preferredStyle: .alert)
alert.addTextField(configurationHandler: nil)
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: { _ in
if let text = alert.textFields?[0].text {
self.title = text
SkillModal.shared.add(Skill(title: text, goalCount: 60 * 60 * 20))
SkillModal.shared.save()
}
}))
alert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
present(alert, animated: true, completion: nil)
}
startButton.layer.cornerRadius = 25.0
}
override func viewWillAppear(_ animated: Bool) {
guard let skill = SkillModal.shared.currentSkill else {
return
}
self.title = skill.title
timerlabel.text = secondsToGoalTimerLabel(skill.goalCount)
}
func addBannerViewToView(_ bannerView: GADBannerView) {
bannerView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(bannerView)
view.addConstraints(
[NSLayoutConstraint(item: bannerView,
attribute: .bottom,
relatedBy: .equal,
toItem: view.safeAreaLayoutGuide.bottomAnchor,
attribute: .top,
multiplier: 1,
constant: 0),
NSLayoutConstraint(item: bannerView,
attribute: .centerX,
relatedBy: .equal,
toItem: view,
attribute: .centerX,
multiplier: 1,
constant: 0)
])
}
/// Tells the delegate an ad request loaded an ad.
func adViewDidReceiveAd(_ bannerView: GADBannerView) {
print("adViewDidReceiveAd")
}
/// Tells the delegate an ad request failed.
func adView(_ bannerView: GADBannerView,
didFailToReceiveAdWithError error: GADRequestError) {
print("adView:didFailToReceiveAdWithError: \(error.localizedDescription)")
}
/// Tells the delegate that a full-screen view will be presented in response
/// to the user clicking on an ad.
func adViewWillPresentScreen(_ bannerView: GADBannerView) {
print("adViewWillPresentScreen")
}
/// Tells the delegate that the full-screen view will be dismissed.
func adViewWillDismissScreen(_ bannerView: GADBannerView) {
print("adViewWillDismissScreen")
}
/// Tells the delegate that the full-screen view has been dismissed.
func adViewDidDismissScreen(_ bannerView: GADBannerView) {
print("adViewDidDismissScreen")
}
/// Tells the delegate that a user click will open another app (such as
/// the App Store), backgrounding the current app.
func adViewWillLeaveApplication(_ bannerView: GADBannerView) {
print("adViewWillLeaveApplication")
}
/****************このコードで最初ダメでコメントアウトし、GoogleAddのドキュメントを見てViewDidLoad()に書いた。*************************************************/
// override func viewDidLayoutSubviews() {
// //広告インスタンス作成
// var admobView = GADBannerView()
// admobView = GADBannerView(adSize: kGADAdSizeBanner)
//
// //広告位置設定
// let safeArea = self.view.safeAreaInsets.bottom
// admobView.frame.origin = CGPoint(x: 0, y: self.view.frame.size.height - safeArea - admobView.frame.height)
// admobView.frame.size = CGSize(width: self.view.frame.width, height: admobView.frame.height)
//
// //広告ID設定
// admobView.adUnitID = "ca-app-pub-3940256099942544/2934735716"
//
// //広告表示
// admobView.rootViewController = self
// admobView.load(GADRequest())
// self.view.addSubview(admobView)
// }
/*******************************************************************/
}
AppDelegate
import UIKit
import Firebase
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch
// Use Firebase library to configure APIs
FirebaseApp.configure()
// Initialize Google Mobil Ads SDK, application ID を設定 GADMobileAds.sharedInstance().start(completionHandler: nil)
// if userDefaults.object(forKey: theFarstBoolKey) as! Bool == true //{ }
return true
}
func applicationWillResignActive(_ application: UIApplication) {
// 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.
}
func applicationDidEnterBackground(_ application: UIApplication) {
// 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.
}
func applicationWillEnterForeground(_ application: UIApplication) {
// 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.
}
func applicationDidBecomeActive(_ application: UIApplication) {
// 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.
}
func applicationWillTerminate(_ application: UIApplication) {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
}
変更後コード
import UIKit
import GoogleMobileAds
class ViewController: UIViewController, GADBannerViewDelegate {
@IBOutlet weak var characterImage: UIImageView!
@IBOutlet weak var timerlabel: UILabel!
@IBOutlet weak var startButton: UIButton!
// var bannerView: GADBannerView!
var theView: UIView!
var bannerView: GADBannerView!
override func viewDidLoad() {
super.viewDidLoad()
/*******ad**********************************************************/
//In this case, we instantiate the banner with desired ad size.
bannerView = GADBannerView(adSize: kGADAdSizeBanner)
addBannerViewToView(bannerView)
bannerView.adUnitID = "ca-app-pub-3940256099942544/2934735716"
bannerView.rootViewController = self
bannerView.load(GADRequest())
bannerView.delegate = self
theView = UIView(frame: CGRect.zero)
theView.backgroundColor = .lightGray
view.addSubview(theView)
theView.translatesAutoresizingMaskIntoConstraints = false //この一行は必要
theView.widthAnchor.constraint(equalToConstant: 240).isActive = true
theView.heightAnchor.constraint(equalToConstant: 80).isActive = true
theView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor).isActive = true
theView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
/******************************************************************/
SkillModal.shared.load()
if let myTitle = SkillModal.shared.fastSkill(){ //This is change
self.title = myTitle.title
} else {
let alert = UIAlertController(title: "Title Name", message: "Please enter new name", preferredStyle: .alert)
alert.addTextField(configurationHandler: nil)
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: { _ in
if let text = alert.textFields?[0].text {
self.title = text
SkillModal.shared.add(Skill(title: text, goalCount: 60 * 60 * 20))
SkillModal.shared.save()
}
}))
alert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
present(alert, animated: true, completion: nil)
}
startButton.layer.cornerRadius = 25.0
}
override func viewWillAppear(_ animated: Bool) {
guard let skill = SkillModal.shared.currentSkill else {
return
}
self.title = skill.title
timerlabel.text = secondsToGoalTimerLabel(skill.goalCount)
}
func addBannerViewToView(_ bannerView: GADBannerView) {
bannerView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(bannerView)
view.addConstraints(
[NSLayoutConstraint(item: bannerView,
attribute: .bottom,
relatedBy: .equal,
toItem: view.safeAreaLayoutGuide.bottomAnchor,
attribute: .top,
multiplier: 1,
constant: 0),
NSLayoutConstraint(item: bannerView,
attribute: .centerX,
relatedBy: .equal,
toItem: view,
attribute: .centerX,
multiplier: 1,
constant: 0)
])
}
/// Tells the delegate an ad request loaded an ad.
func adViewDidReceiveAd(_ bannerView: GADBannerView) {
print("adViewDidReceiveAd")
}
/// Tells the delegate an ad request failed.
func adView(_ bannerView: GADBannerView,
didFailToReceiveAdWithError error: GADRequestError) {
print("adView:didFailToReceiveAdWithError: \(error.localizedDescription)")
}
/// Tells the delegate that a full-screen view will be presented in response
/// to the user clicking on an ad.
func adViewWillPresentScreen(_ bannerView: GADBannerView) {
print("adViewWillPresentScreen")
}
/// Tells the delegate that the full-screen view will be dismissed.
func adViewWillDismissScreen(_ bannerView: GADBannerView) {
print("adViewWillDismissScreen")
}
/// Tells the delegate that the full-screen view has been dismissed.
func adViewDidDismissScreen(_ bannerView: GADBannerView) {
print("adViewDidDismissScreen")
}
/// Tells the delegate that a user click will open another app (such as
/// the App Store), backgrounding the current app.
func adViewWillLeaveApplication(_ bannerView: GADBannerView) {
print("adViewWillLeaveApplication")
}
// override func viewDidLayoutSubviews() {
// //広告インスタンス作成
// var admobView = GADBannerView()
// admobView = GADBannerView(adSize: kGADAdSizeBanner)
//
// //広告位置設定
// let safeArea = self.view.safeAreaInsets.bottom
// admobView.frame.origin = CGPoint(x: 0, y: self.view.frame.size.height - safeArea - admobView.frame.height)
// admobView.frame.size = CGSize(width: self.view.frame.width, height: admobView.frame.height)
//
// //広告ID設定
// admobView.adUnitID = "ca-app-pub-3940256099942544/2934735716"
//
// //広告表示
// admobView.rootViewController = self
// admobView.load(GADRequest())
// self.view.addSubview(admobView)
// }
}