Unable to connect a Custom NSView to its view controller outlet (KPCTabsControl) - swift

I am trying to assign a KPCTabsControl class to a custom NSView. The window view class is MainViewController.
The MainViewController code looks like this:
class MainViewController : NSViewController {
#IBOutlet var myTabsController: TabsController!
#IBOutlet var myButton: NSButton!
//...
}
The TabsController code looks like this:
class TabsController : NSViewController, KPCTabsControlDataSource, KPCTabsControlDelegate {
#IBOutlet var tabsBar: KPCTabsControl?
var titles: Array<String> = []
func tabsControlNumberOfTabs(tabControl: KPCTabsControl) -> UInt {
return UInt(titles.count)
}
//...
}
The form looks like this:
I tried to connect the "Main View Controller" to the "KPCTabsControl" custom view with control-drag. I get the outlet choices: sourceItemView and view. On the other hand, if I try to connect "Main View Controller" to the "+" button, I get the outlet choices: myButton, sourceItemView and view. I don't understand why the "myTabsController" never appears while the "myButton" outlet is available.
Right now, the custom class of the "KPCTabsControl" view is "KPCTabsControl", I tried to enter "TabsController" but it is not listed in the possible choices. And writing it does not work, the value seems rejected and returns automatically to "KPCTabsControl".
What am I missing?
(I'm using Xcode 7.3.1)

Related

Why when I pass data to a UILabel directly in the Second View Controller it turns to be nil?

Why when I pass data to a UILabel directly in the Second View Controller it turns to be nil but when I pass data to a variable first and then apply it to the UILabel everything works fine?
The following code crash the app after segue performed (theResult is nil):
Second View Controller:
#IBOutlet weak var theResult: UILabel!
Main View Controler:
secondVC.theResult.text = “Nice”
But when I create a variable in the Second View Controller, I can pass the data to it easily and then apply it to the UILabel without any problem:
Second View Controller:
var calculation: String?
#IBOutlet weak var theResult: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
theResult.text = calculation
}
Main View Controler:
secondVC.calculation = “Nice”
Why is that?
Note: The UILabel has a default value already when it is created in the Storyboard.
I am almost sure that this is not working but I want to know the reason. Why you can easily change for example the background of the Second View Controller like this:
secondVC.view.backgroundColor = .green
but when you touch the IBOutlets it do not work.

How add IBOutlet to class in embedded TableView

Please give me a hint how to add IBOUTLET variables to the ViewControllerSettings class. TableViewController is embedded on Container View.
You need to control drag and drop it inside the ViewControllerSettings class's definition.
class ViewControllerSettings: UITableViewControntroller {
#IBOutlet weak var tableView: UITableView!
//...
}
Note: Make sure the class for the UITableViewController is set to ViewControllerSettings in your storyboard.
#IBOutlet weak var tableView: UITableView!
control Drag the table view to the above #IBOutlet
From your screenshot, it seems that you have not assigned the ViewControllerSettings for UITableViewController inside storyboard.
Inside storyboard, select added UITableViewController, got to Identity Inspector and set Class as ViewControllerSettings.
Also do connect outlets inside your class in .swift file.

Referring to viewcontroller outlets from viewcontroller extension

I have two view controllers SymbolsVC and ItemsVC. Both have a UIActivityIndicatorView which has been outlet by the name of spinner in each view controller like this:
class SymbolsVC: UIViewController {
#IBOutlet weak var spinner: UIActivityIndicatorView!
}
class ItemsVC: UIViewController {
#IBOutlet weak var spinner: UIActivityIndicatorView!
}
Now I need to write a lot of shared code between these view controllers, for example, a function which would start the spinner in its respective viewcontroller. So I have created an extension for UIViewController like this:
extension UIViewController {
func startSpinner() {
spinner.startAnimating()
}
}
However, this gives Use of unresolved identifier 'spinner' error.
What am I missing?
EDIT FOR FURTHER CLARIFICATION: My extension is actually an IAP. This IAP can be called from any number of ViewControllers. When one of the ViewControllers, call the IAP function which is in the extension, it is the flow of the program in that IAP function which determines when to start/stop the spinner. Hence it needs to be done within the extension.
When the compiler sees this:
extension UIViewController {
func startSpinner() {
spinner.startAnimating()
}
}
it thinks every instance of UIViewController in your module contains this spinner property, which of coarse is wrong.
Since as a rule, you can't place regular {set get} properties inside extension, my solution would be placing the spinner inside a base view controller SpinnerBaseVC, which inherits UIViewController.
Then, inherit SpinnerBaseVC with whatever class you want to utilize the spinner property.
class SpinnerBaseVC: UIViewController {
#IBOutlet weak var spinner: UIActivityIndicatorView!
func startSpinner() {
spinner.startAnimating()
}
}
// MARK: Classes which can naturally access `spinner` and `startSpinner`
class SymbolsVC: SpinnerBaseVC {
// Here you can access spinner
}
class ItemsVC: SpinnerBaseVC {
// Here you can access spinner
}

Swift Access Objects In View Controller From Window Controller

I'm just getting into development on mac os and I made a simple app for the touch bar that allows you to change the color (with a nscolorpicker) of a label that is also on the touch bar.
Now I would like to get the same effect on the actual window like so: I change the color using the picker on the touch bar and the color of the colorwell in the window changes as well.
This is the code that I currently have for the touch bar actions:
import Cocoa
#available(OSX 10.12.2, *)
class MainWindowController: NSWindowController {
#IBOutlet weak var cptHello: NSColorPickerTouchBarItem!
#IBOutlet var lblHello: NSTextField!
override func windowDidLoad() {
super.windowDidLoad()
// Implement this method to handle any initialization after your window controller's window has been loaded from its nib file.
cptHello.color = NSColor.white
setCol()
}
func setCol(){
lblHello.textColor = cptHello.color
}
#IBAction func colorPicked(_ sender: Any) {
setCol()
}
}
This piece of code resides in MainWindowController.swift which is paired with the window controller.
In the view controller, I have a single NSColorWell that I would like to change the color for inside the function "setCol()". I created an outlet in the view controller for it like so:
#IBOutlet var cwHello: NSColorWell!
So ideally what I want to achieve is something like this:
func setCol(){
lblHello.textColor = cptHello.color
ViewController.cwHello.color = cptHello.color
}
Can this be done at all?

Swift - IBOutletCollection equivalent

I'm trying to replicate the Stanford Matchismo game from "Developing ios7 apps for iphone and ipad" in iTunesU in Swift.
On page 77 of the 3rd lecture slides, it shows using an IBOutletCollection which isn't an option on Swift. The Swift doc example shows one example that has an array of IBOutlet, but I can't figure out how to make Interface Builder connect multiple outlets to the same IBOutlet/IBOutlet Array.
Has anyone figured out how to do this yet?
I know that I can create 12 outlets and deal with it that way, but I'd like to make this work as closely as possible to the example in the lecture slides.
Update: This works properly in Xcode now - "Outlet Collection" is one of the connection options in Interface Builder, which creates something that looks like:
#IBOutlet var labelCollection: [UILabel]!
While we're waiting for a fix, you can approximate this using a computed property. Let's say my view has five UILabels that I want in a collection. I still have to declare each one, but then I also declare a computed property that collects them:
class MyViewController {
#IBOutlet var label1 : UILabel
#IBOutlet var label2 : UILabel
#IBOutlet var label3 : UILabel
#IBOutlet var label4 : UILabel
#IBOutlet var label5 : UILabel
var labels: UILabel![] { return [label1, label2, label3, label4, label5] }
Kind of annoying, but from then on we can treat the labels property as if it were an IBOutletCollection, and won't have to change the rest of our code once the bug is fixed:
override func viewDidLoad() {
super.viewDidLoad()
for (index, item) in enumerate(self.labels) {
item.text = "Label #\(index)"
}
}
Use:
#IBOutlet var lineFields: [UITextField]!
Then control-drag from UITextField elements to lineFields in order.
#IBOutlet var buttons : [UIView]!
then drag it from the connections inspector in the interface builder or whatever metod you usually use for that
EDIT
This was fixed in a later Beta release of Swift - there's now in
IBCollection option in the interface builder.
For early Beta releases of Swift:
I came across the same problem: in the release notes of Beta 2 you find the following statement:
Interface Builder does not support declaring outlet collections in Swift classes
I solved this the following way (easy to customize):
class CardGameViewController: UIViewController {
#lazy var cardButtons : UIButton[] = {
var tempBtn: UIButton[] = []
for v:AnyObject in self.view.subviews {
if v is UIButton {
tempBtn.append(v as UIButton)
}
}
return tempBtn
}()
...
Basically, it loops through all the subviews and checks if one is a UIButton. In that case it gets added to a temporary array. This temporary array is then used to lazy instantiate the cardButtons array. For all details, check: Matchismo: Objective-C to Swift
Follow steps to create an array of outlets and connect it with IB Elements:
Create an array of IBOutlets
Add multiple UIElements (Views) in your Storyboard ViewController interface (As shown in below snapshot)
Select ViewController (In storyboard) and open connection inspector
There is option 'Outlet Collections' in connection inspector (You will see an array of outlets there)
Connect if with your interface elements
-
class ViewController2: UIViewController {
#IBOutlet var collection:[UIView]!
override func viewDidLoad() {
super.viewDidLoad()
}
}
I got this working in Xcode seed 3 using this syntax
#IBOutlet strong var views: NSArray?
See my discussion here: https://stackoverflow.com/a/24686602/341994
What #machine said seems to be the current state (XCode 7.1) with iOS 9 bindings.
The key is to drag them all in order.
Use the first item to control+drag into the controller code and then change the Outlet type to collection. After the from the controller code file drag the outlet point onto each of the screen controls one by one in order (as #machine says)