I tried to implement ADBannerView with the old way like Objective C but unsuccessfull. Everythings work but the advertisments didn't show up, it stays a blank field.
func bannerViewDidLoadAd(banner: ADBannerView!) {
UIView.beginAnimations(nil, context: nil)
UIView.setAnimationDuration(1)
banner.alpha = 1
UIView.commitAnimations()
}
func bannerView(banner: ADBannerView!, didFailToReceiveAdWithError error: NSError!) {
UIView.beginAnimations(nil, context: nil)
UIView.setAnimationDuration(1)
banner.alpha = 0
UIView.commitAnimations()
}
Anyone who already tried iAd on Swift?
I've found a solution, how to implement it. (You can use inside each method "banner.alpha 1.0" or other things, too.)
//import ... your normal imports as UIKit etc.
import iAd
class YourClassViewController: UIViewController, ADBannerViewDelegate {
#IBOutlet var adBannerView: ADBannerView //connect in IB connection inspector with your ADBannerView
override func viewDidLoad() {
super.viewDidLoad()
self.canDisplayBannerAds = true
self.adBannerView.delegate = self
self.adBannerView.hidden = true //hide until ad loaded
}
func bannerViewWillLoadAd(banner: ADBannerView!) {
NSLog("bannerViewWillLoadAd")
}
func bannerViewDidLoadAd(banner: ADBannerView!) {
NSLog("bannerViewDidLoadAd")
self.adBannerView.hidden = false //now show banner as ad is loaded
}
func bannerViewActionDidFinish(banner: ADBannerView!) {
NSLog("bannerViewDidLoadAd")
//optional resume paused game code
}
func bannerViewActionShouldBegin(banner: ADBannerView!, willLeaveApplication willLeave: Bool) -> Bool {
NSLog("bannerViewActionShouldBegin")
//optional pause game code
return true
}
func bannerView(banner: ADBannerView!, didFailToReceiveAdWithError error: NSError!) {
NSLog("bannerView")
}
//... your class implementation code
}
See the following answer, on how to do it without IBBuilder!
If you are using iOS 7, extension methods and properties have been added to UIViewController to support handling of iAd:
See
https://developer.apple.com/library/prerelease/ios/documentation/iAd/Reference/UIViewController_iAd_Additions/index.html
To show an iAd you first need to add the iAd framework, go to the projects properties, general tab, add the iAd.framework in the Linked framework and libraries section.
In your view controller, import iAd to access the iAd extensions. And finally in viewDidLoad, set self.canDisplayBannerAds = true.
To remove ads, set canDisplayBannerAds to false
Note there is no need to create an AdBannerView in the story board or programmatically and there is no need for your view controller to implement the AdViewDelegate.
import UIKit
import iAd
class ViewController : UIViewController
{
override func viewDidLoad()
{
super.viewDidLoad()
//That's it
self.canDisplayBannerAds = true
}
}
Mr. T answer contains a lot of useless code.
All you need is this part to show ads in your controller:
override func viewDidLoad() {
super.viewDidLoad()
canDisplayBannerAds = true
}
And when you don't need ads, you canDisplayBannerAds = false.
What it does — wrapping your controller into another controller with ad banner at the bottom. This feature is available since iOS7.
It's not possible to get delegate messages with it, so if you need it — you should replace it with ADBannerView instance variable.
Related
I've tried, without success, respond to events such as windowWillClose() and windowShouldClose() inside NSWindowController (yes conforming to NSWindowDelegate).
Later, to my surprise, I was able to receive those events if I make my contentViewController (NSViewController) conform to NSWindowDelegate.
Unfortunately, later on, found out that view.window?.windowController is nil inside windowWillClose() or windowShouldClose(), code:
override func viewDidAppear() {
super.viewDidAppear()
self.view.window?.delegate = self
self.view.window?.windowController // not nil!
}
func windowWillClose(_ notification: Notification) {
self.view.window?.windowController // nil!!
}
func windowShouldClose(_ sender: NSWindow) -> Bool {
self.view.window?.windowController // nil!!
return true
}
After realizing that view.window?.windowController is not nil inside viewDidAppear() the next thing I thought was that Swift garbage collected the controller, so I changed viewDidAppear() in a way that creates another reference of windowController thus preventing garbage collection on said object, code:
var windowController: NSWindowController?
override func viewDidAppear() {
super.viewDidAppear()
self.view.window?.delegate = self
windowController = view.window?.windowController
}
func windowWillClose(_ notification: Notification) {
self.view.window?.windowController // NOT nil
}
func windowShouldClose(_ sender: NSWindow) -> Bool {
self.view.window?.windowController // NOT nil
return true
}
My hypothesis turned out to be correct (I think).
Is this the same issue that is preventing me from receiving those events inside NSWindowController?
Is there another way I can achieve the same thing without creating more object references?
In order to post code, I use the Answer option even though it is more of a comment.
I added in NSViewController:
override func viewDidAppear() {
super.viewDidAppear()
parentWindowController = self.view.window!.windowController
self.view.window!.delegate = self.view.window!.windowController as! S1W2WC. // The NSWC class, which conforms to NSWindowDelegate
print(#function, "windowController", self.view.window!, self.view.window!.windowController)
}
I get print log:
viewDidAppear() windowController Optional()
and notification is passed.
But if I change to
override func viewDidAppear() {
super.viewDidAppear()
// parentWindowController = self.view.window!.windowController
self.view.window!.delegate = self.view.window!.windowController as! S1W2WC
print(#function, "windowController", self.view.window!, self.view.window!.windowController)
}
by commenting out parentWindowController, notification don't go anymore to the WindowController…
Edited: I declared in ViewController:
var parentWindowController: NSWindowController? // Helps keep a reference to the controller
The proposed solutions are, in my opinion, hacks that can cause serious problems with memory management by creating circular references. You definitely can make instances of NSWindowController work as the window’s delegate. The proper way is to wire it up correctly in either code or in Interface Builder in Xcode. An example of how to do it properly is offered here.
If the delegate methods are not called is because the wiring up is not done correctly.
Another thing that must be done in Swift is when you add the name of the NSWindowController subclass in Interface Builder in Xcode is to check the checkbox of Inherits from Module. If you fail to do this, none of your subclass methods will be called.
I'm trying to save a bool value to UserDefaults from a UISwitch, and retrieve it in another view. However, I've tried following multiple tutorials and stack answers and none seem to work.
This is how I'm saving it:
class SettingsViewController: UITableViewController {
#IBOutlet weak var soundSwitchOutlet: UISwitch!
#IBAction func soundSwitch(_ sender: UISwitch) {
UserDefaults.standard.set(soundSwitchOutlet.isOn, forKey: "sound")
}
and this is how I'm trying to retrieve it in another view:
if let savedValue = UserDefaults.standard.bool(forKey: "sound") {
boolValue = savedValue
}
//this is inside viewDidLoad and "boolValue" was declared outside viewDidLoad//
For a reason this code is giving me errors and none of the things I've tried have worked. How can I save a bool to UserDefaults and retrieve it in another view?
Edit: I think I fixed the first part. However, the way I'm retrieving the boolean seems to be totally wrong. Also: No other stackExchange answer responds to what I'm asking, at least not in swift.
As Leo mentioned in the comments bool(forKey returns a non-optional Bool. If the key does not exist false is returned.
So it's simply
boolValue = UserDefaults.standard.bool(forKey: "sound")
Calling synchronize() as suggested in other answers is not needed. The framework updates the user defaults database periodically.
Do it like this.
In your first view controller.
create an IBoutlet connection to your UISwitch
And then the action for your UISwitch. so in the end, your first view controller should look like this.
import UIKit
class FirstViewController: UIViewController {
#IBOutlet weak var myswitch: UISwitch! // Outlet connection to your UISwitch (just control+ drag it to your controller)
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
#IBAction func myswitchAction(_ sender: Any) { // Action for your UISwitch
var myswitctBool : Bool = false // create a local variable that holds your bool value. assume that in the beginning your switch is offed and the boolean value is `false`
if myswitch.isOn == true { // when user turn it on then set the value to `true`
myswitctBool = true
}
else { // else set the value to false
myswitctBool = false
}
// finally set the value to user default like this
UserDefaults.standard.set(myswitctBool, forKey: "mySwitch")
//UserDefaults.standard.synchronize() - this is not necessary with iOS 8 and later.
}
}
End of the first view controller
Now in your second view controller
you can get the value of userdefault, which you set in first view controller. I put it in the viewdidload method to show you how it works.
import UIKit
class SecondViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let myswitchBoolValuefromFirstVc : Bool = UserDefaults.standard.bool(forKey: "mySwitch")// this is how you retrieve the bool value
// to see the value, just print those with conditions. you can use those for your things.
if myswitchBoolValuefromFirstVc == true {
print("true")
}
else {
print("false")
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
Hope this will help to you. good luck
Use this line of code:
#IBAction func soundSwitch(_ sender: UISwitch) {
UserDefaults.standard.set(soundSwitchOutlet.isOn, forKey: "sound")
}
insteadof :
#IBAction func soundSwitch(_ sender: UISwitch) {
UserDefaults.standard.set(soundSwitchOutlet, forKey: "sound")
}
Try this:
#IBAction func soundSwitchs(_ sender: Any)
{
UserDefaults.standard.set(soundSwitchOutlet.isOn, forKey: "sound")
UserDefaults.standard.synchronize()
}
//this is inside viewDidLoad and "boolValue" was declared outside viewDidLoad//
boolValue = UserDefaults.standard.bool(forKey: "sound")
I'm trying to trigger a save of my CoreData on a window close as its only a single window application.
I've got the following code in my viewDidLoad and viewDidAppear
override func viewDidLoad() {
super.viewDidLoad()
if windowShouldClose(self) {
saveValues()
}
}
override func viewDidAppear() {
super.viewDidAppear()
self.view.window?.delegate = self
}
however im still getting the following error
Use of unresolved identifier 'windowShouldClose'
Any advice as to why i'm still getting this error after declaring the window delegate as self?
Set the delegate in viewDidLoad
override func viewDidLoad() {
super.viewDidLoad()
self.view.window?.delegate = self
}
and implement the delegate method
func windowWillClose(notification: NSNotification) {
saveValues()
}
windowShouldClose is different. It asks for permission to close the window and expects a boolean return value.
I have this hierarchy - UIViewController -> ChildUIViewController -> WKWebView.
I had an issue with the WKWebView message handler that leaked and prevented the child view controller from being released.
After some reading I found a way to fix the retain cycle by using this fix - WKWebView causes my view controller to leak
Now I can see that the child view controller is reaching deinit but right after that the WKWebView is crashing on deinit (No useful log from Xcode).
Any Idea or direction what could be the issue ?
Thanks
UPDATE
here is my code - Code Gist
Put this inside deinit method of child view controller:
webView.scrollView.delegate = nil
Don't forget to remove WKWebView's delegates you added:
deinit {
webView.navigationDelegate = nil
webView.scrollView.delegate = nil
}
Looks like WKWebView stores __unsafe_unretained pointer to your delegate. Sometimes when web view deallocated not immediate after view controller deallocation. This cause crash when web view tries to notify delegate something.
I tried with same way as you mentioned. It works perfectly for me. Code which i tried is,
class CustomWKWebView : WKWebView {
deinit {
print("CustomWKWebView - dealloc")
}
}
class LeakAvoider : NSObject, WKScriptMessageHandler {
weak var delegate : WKScriptMessageHandler?
init(delegate:WKScriptMessageHandler) {
self.delegate = delegate
super.init()
}
func userContentController(userContentController: WKUserContentController,
didReceiveScriptMessage message: WKScriptMessage) {
self.delegate?.userContentController(
userContentController, didReceiveScriptMessage: message)
}
deinit {
print("LeakAvoider - dealloc")
}
}
class ChildViewController: UIViewController , WKScriptMessageHandler{
var webView = CustomWKWebView()
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
}
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(webView)
webView.frame = self.view.bounds;
}
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
let url = NSURL(string: "https://appleid.apple.com")
webView.loadRequest(NSURLRequest(URL:url!))
webView.configuration.userContentController.addScriptMessageHandler(
LeakAvoider(delegate: self), name: "dummy")
}
func userContentController(userContentController: WKUserContentController, didReceiveScriptMessage message: WKScriptMessage)
{
}
deinit {
print("ChaildViewController- dealloc")
webView.stopLoading()
webView.configuration.userContentController.removeScriptMessageHandlerForName("dummy")
}
}
class ViewController: UIViewController {
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
}
override func viewDidLoad() {
super.viewDidLoad()
}
deinit {
print("ViewController - dealloc")
}
}
Log after popping ViewController is:
ViewController - dealloc
ChaildViewController- dealloc
LeakAvoider - dealloc
CustomWKWebView - dealloc
UPDATE
Put below lines in your WebViewViewController's viewWillDisappear function.
webView.navigationDelegate = nil
webView.scrollView.delegate = nil
I tried by setting these two delegates in my code and it started crashing. Solved by putting above lines in viewWillDisappear of ChildViewController.
Remember, the reason might caused by weak reference to it.
I'm sure that you have instantiated local variable of wrapped class with WKWebView.
I've made a game using SpriteBuilder and it's written in Swift. I'd like to add advertisements before I ship an update to the App Store. Can someone please help me with how to do this?
To add iAd to your game, you need to add the iAd framework to your app (via Build Phases) and add the import statement import iAd in the class that handles your iAd implementation.
The simplest iAd ad to add to your Swift game is a banner ad:
override func viewDidLoad() {
super.viewDidLoad()
self.canDisplayBannerAds = true
}
Make sure to import iAd and add the AdBannerViewDelegate protocol to your class declaration:
import iAd
class MasterViewController: UITableViewController, NSFetchedResultsControllerDelegate,ADBannerViewDelegate
Then you need to create the actual banner view, set the delegate (in ViewDidLoad) and add two delegate methods, so that you know when to add/remove the advertisement banner from the view:
bannerViewDidLoadAd:
bannerView:didFailToReceiveAdWithError:
It's fairly easy.
1) Import the iAd framework >Build Phases> Link Binary With Libraries> find iAd
2) drag an iAd BannerView from the object library
3) Make an outlet connecting the iAd BannerView to your VC file
4) Add the delegate to your VC class
import iAd
class ViewController: UIViewController, ADBannerViewDelegate{
#IBOutlet var adBannerView: ADBannerView?
override func viewDidLoad(){
self.canDisplayBannerAds = true
self.ADBannerView?.delegate = self
self.ADBannerView.hidden = true
}
func bannerViewWillLoadAd(banner: AdBannerView!){ // any addition set up you want
}
func bannerViewDidLoadAd(banner: ADBannerView!){
self.ADBannerView?.hidden = false
}
func bannerViewActionDidFinish(banner: ADBannerView!){// any addition set up you want
}
func bannerViewActionShouldBegin(banner: ADBannerView!, willLeaveApplication willLeave: Boll) -> Bool {
return true
}
func bannerView(banner: ADBannerView!, didFailToReceiveAdWithError error: NSError!){
self.adBannerView?.hidden = false
}
}
Of course you'll have to adjust to display when ever and where you wan it.