Xcode6/Swift - How to implement an iAdBannerView in multiple view controllers? - view

Before I get started I am aware this question has been asked many times before, however all of them refer to xcode5/objective-C, not swift. I am only new to app development so I haven't been able to understand the objective-c and use it in swift.
I have got an adBannerView working on my first view controller, however how do I then take this banner and use it across my other 2 view controllers? Do I use the prepareForSegue function (and if so, how)?
My code for the adBannerView I currently have (from here)
//...
import iAd
class ViewController: UIViewController, ADBannerViewDelegate {
//link adBanner
#IBOutlet var adBannerView: ADBannerView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.canDisplayBannerAds = true
self.adBannerView.delegate = self
self.adBannerView.hidden = true
}
func bannerViewWillLoadAd(banner: ADBannerView!) {
NSLog("bannerViewWillLoadAd")
}
func bannerViewDidLoadAd(banner: ADBannerView!) {
NSLog("bannerViewDidLoadAd")
self.adBannerView.hidden = false
}
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")
}
//...
Thanks :)

When I have faced this problem my solution was to create a ParentViewController, and the others view controllers inheritate from him. In the parent view controller I create an outlet for a view which will contain iAdView, and in the .xib file of each view controller I link the iAdView container view to the created outlet. After that I create a singleton which has all the iAdView functionality and a property which is the iAdView. In the viewDidAppear of the parent I ask the singleton for the iAdView and add it as a subview of the iAd view container. Doing this that way in the view controllers you are not going to see any code of the iAdView, because all will be in the ParentViewController and in the singleton (lets call it iAdManager). Hope it helps.

Related

Xcode - How can i programmatically embed/change view controller within a container view?

I am trying to programmatically set / or change the embedded View Controller inside a Controller View.
I have 3 different View Controllers, that I would like to show in the Container View, all depending on if the user is logged in or not.
I have looked around and tried a bunch of code, I found one that worked, but the code changed the self view, and not the view containers view.
A lot of the code I have tried have also not been in Swift 3, so as a new app developer, this has been quite stressful, as I tried to convert it to Swift 3.
Can anyone provide a solution for changing the embedded view controller inside a view container? Thanks.
I might have found a solution for this. I'm answering here, in case it can help anyone else in my situation.
What I did was add a new View Controller and then embed it to the View Container - This will work as a "master view" - I then use this blank view controller to decide which other view controller should be changed within the self of the blank.
Here's some code I have in the blank view controller, but I suppose the blank view controller can also be used as a master view controller (in my case for "Account"), and then it can add the login/register view as a child.
override func viewDidLoad() {
super.viewDidLoad()
updateView()
}
private lazy var loginViewController: loginViewController = {
// Load Storyboard
let storyboard = UIStoryboard(name: "Main", bundle: Bundle.main)
// Instantiate View Controller
var viewController = storyboard.instantiateViewController(withIdentifier: "loginViewController") as! loginViewController
// Add View Controller as Child View Controller
self.add(asChildViewController: viewController)
return viewController
}()
private lazy var registerViewController: registerViewController = {
// Load Storyboard
let storyboard = UIStoryboard(name: "Main", bundle: Bundle.main)
// Instantiate View Controller
var viewController = storyboard.instantiateViewController(withIdentifier: "registerViewController") as! registerViewController
// Add View Controller as Child View Controller
self.add(asChildViewController: viewController)
return viewController
}()
private func add(asChildViewController viewController: UIViewController) {
// Add Child View Controller
addChildViewController(viewController)
// Add Child View as Subview
view.addSubview(viewController.view)
// Configure Child View
viewController.view.frame = view.bounds
viewController.view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
// Notify Child View Controller
viewController.didMove(toParentViewController: self)
}
private func remove(asChildViewController viewController: UIViewController) {
// Notify Child View Controller
viewController.willMove(toParentViewController: nil)
// Remove Child View From Superview
viewController.view.removeFromSuperview()
// Notify Child View Controller
viewController.removeFromParentViewController()
}
private func updateView() {
add(asChildViewController: registerViewController)
/*
if segmentedControl.selectedSegmentIndex == 0 {
remove(asChildViewController: sessionsViewController)
add(asChildViewController: summaryViewController)
} else {
remove(asChildViewController: summaryViewController)
add(asChildViewController: sessionsViewController)
}
*/
}
Credit to this guy: https://cocoacasts.com/managing-view-controllers-with-container-view-controllers/
The easiest way to do that is to have 3 container views in Storyboard above each other, each one of them is connected to a different view controller, then in your code, make 2 of these 3 container views hidden and leave one visible based on your business needs.
This is described in detail in this blog post. Hope this helps!

Simple displaying of second window: OS X & Swift

I'm trying to find how to bring up a second view/window after pushing a button on my primary window. I have read about segues and I can get the first window to display the second but the second is not connected to a view controller so I can't add any code to any controls on the second view. Try as I might I cannot create a SecondViewController.swift file and connect it to a window controller or a view controller. The tutorials I have found all deal with iOS and I want OS X which means there are just enough differences to keep me from figuring this out.
Can anyone show me how to do this?
Ta,
A.
First make new file like:
After that, put these codes in your classes and that should do it.
class SecondWindowController: NSWindowController {
convenience init() {
self.init(windowNibName: "SecondWindowController")
}
}
class ViewController: NSViewController {
private var secondWindowController: SecondWindowController?
#IBAction func showSecondWindow(sender: AnyObject) {
if secondWindowController == nil {
secondWindowController = SecondWindowController()
}
secondWindowController?.showWindow(self)
}
}

How do I subscribe to TextField's TextChanged event in Xcode

I've recently started working on some test projects to get the feel for OS X development with Xcode. I come from Windows, so I might not be making much sense here.
How would I subscribe to certain "events" in Swift? I have just learned how to connect actions to UI objects. For example, I can now click a button, and change the text of a label programatically. However, and this may just be a case of lack of knowledge on my part - I am not able to find a way to subscribe to a TextField's "Text Changed" event.
Let's say that I have a TextField, and when I change the text at runtime (i.e. type something), I want to do something in the textChanged event for that particular TextField.
Is there even such a thing as a TextChanged event in OS X development?
Update
I am now using the following code:
import Cocoa
class ViewController: NSViewController {
class textField:NSTextField, NSTextFieldDelegate
{
override func awakeFromNib() {
delegate = self;
}
override func controlTextDidChange(obj: NSNotification)
{
println("Text changed.")
}
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override var representedObject: AnyObject? {
didSet {
// Update the view, if already loaded.
}
}
}
And I have added a ClassName to the TextField control in the Identity Inspector, but it isn't responding to the text changing. The message given is:
Failed to connect (textField) outlet from
(Xcode_Action_Basics.ViewController) to (NSTextField): missing setter
or instance variable
I just googled that error and came across this page: Failed to connect (storyboard) outlet from (NSApplication) to (NSNibExternalObjectPlaceholder) error in Cocoa and storyboard which states that this is a known issue in Xcode and that it does not mean there is a problem with your code - but I'm not so sure about that, because the code isn't working. Not sure if I've missed out on something.
Create a class that implements the protocol NSTextFieldDelegate like
class MyTextField:NSTextField, NSTextFieldDelegate {
override func awakeFromNib() {
delegate = self // tell that we care for ourselfs
}
override func controlTextDidChange(obj: NSNotification) {
// .... handle change, there are a lot of other similar methods. See help
}
}
In IB assign this class here:

How to add tableview datasource and delegate to a separate class/object?

I'm trying to learn how to make a native MacOS X app with SWIFT. I've no background in using Objective-C and even Xcode for the moment.
I achieved to do a simple app which answer to some button clicks and modify some labels. Now, I want to put some stuff in a table. I've put a NSTableView on my UI and figured out that I will have to implement a class which offer implementation for the NSTableViewDelegate and NSTableViewDataSource protocols.
I think that it would be cleaner, for code organization and readability, to put all the stuff to control my TableView in a separate module of the main AppDelegate. Anyway, any tutorial I've seen so far is just focused on how to implement the protocols and put them all in the AppDelegate class.
I've created a new SWIFT file and put the temporary following code inside it:
import Foundation
import Cocoa
class LogTableController: NSObject, NSTableViewDelegate, NSTableViewDataSource {
#IBOutlet var tableView: NSTableView!
var logTableData:[NSDictionary] = []
func numberOfRowsInTableView (tableView: NSTableView!) -> Int {
return 0
}
func tableView(tableView: NSTableView, objectValueForTableColumn tableColumn: NSTableColumn!, row rowIndex: Int) -> AnyObject! {
return "Hello"
}
}
But I'm unable to find how to proceed to make outlet beetween my TableView and my custom class or an instance of that class. Nothing allow me to do that in the InterfaceBuilder.
I think I'm missing something, any answer on how to organize my code to not put all the stuff in the AppDelegate class would be appreciated.
Thanks !
In Interface Builder you would need to add an object from the object library to the document outline and then set its class to your custom class. Then you can connect the delegate and datasource to that object.

OS X addsubview from xib in swift

I'm trying to add a new sub view form a nib using swift for OS X.
So far i've:
created a new "Cocoa Application"
added a new "Cocoa Class" called "TestSubView" as a subclass of NSViewController with a XIB file
I want to add this subview to my main view when the application loads.
in my ViewController ( the ViewController for the main window ) i have.
import Cocoa
class ViewController: NSViewController {
override func viewDidLoad() {
super.viewDidLoad()
let newSubView = TestSubView();
self.view.addSubview(newSubView.view);
}
override var representedObject: AnyObject? {
didSet {
// Update the view, if already loaded.
}
}
}
But i'm getting the following error
Failed to set (contentViewController) user defined inspected property on (NSWindow):
-[NSNib initWithNibNamed:bundle:] could not load the nibName: temp.TestSubView in bundle (null).
I realise i will need to size and position this subview but I can't seem to get to that point.
I've spent the better part of a day trying to figure this one out so any help would be greatly appreciated.
I finally got this thing to work. My new code looks like
import Cocoa
class ViewController: NSViewController {
override func viewDidLoad() {
super.viewDidLoad()
let subview = TestSubView(nibName: "TestSubView", bundle: nil)!
self.view.addSubview(subview.view)
}
override var representedObject: AnyObject? {
didSet {
// Update the view, if already loaded.
}
}
}
Found with the help of the docs & this answer
It was suggested that if the nib name and the class name are the same you shouldn't need to declare nibname: (as i'd tried to do originally) but the docs didn't mention this - explains why it didn't work!
For prosperity, this worked for me with Xcode 6.1.1 on OS X Yosemite (10.10.1)
A nib is really nothing but an XML file with view information in it. You have to get it from the application bundle and get one of the views contained in it explicitly. You are perhaps confounding views and view controllers (your attempt to extract view from newSubView suggests that).
Try this:
let subview = NSBundle.mainBundle().loadNibNamed("TestSubView",
owner:self, options:nil)![0]! // maybe no final unwrapping "!" in Swift 3
self.view.addSubview(subview)
Make sure the xib is really called the name you are using and contains at a least one view (otherwise the two unwrapping ! above will crash your app).

Resources