Cocoa Custom Control not visible - swift

I try to define a Custom Control in Cocoa like this
#IBDesignable
class MyCustomContol: NSControl
{ var textfield: NSTextField!
required public init?(coder: NSCoder)
{ super.init(coder: coder)
textfield = NSTextField(frame: self.frame)
textfield.backgroundColor = NSColor.yellow
textfield.stringValue="DEFAULT"
self.addSubview(textfield)
}
}
In Interfacebuilder I added a Custom View and set its class to my class "MyCustomContol"
The control does not appear in Interfacebuilder an not at runtime.
What´s going wrong.

The textfield is invisible in IB, you only see the NSView. Runtime you add the textfield with the same frame as the custom control. You don't see it because the textfield is outside the custom control. Set the frame (coordinates in the superview) of the textfield to the bounds (coordinates in the view itself) of the control.

tnx #Willeke
with:
textfield = NSTextField(frame: NSRect(x: 0, y: 0, width: self.frame.width, height: self.frame.height) )
it works

Related

NSTouchBar not releasing last touched view

I am making an app which uses the NSTouchBar.
The touchbar is made by the NSWindowController.makeTouchBar()method.
In this touchbar I can place NSCustomTouchBarItems.
I have made two NSCustomTouchBarItems.
The first one sets a view to a default ui button, with this:
let item001 = NSCustomTouchBarItem(identifier: someIdentifier)
item001.view = NSButton(title: "myButton", target: nil, action: nil)
The second one sets a viewController, with this:
let item002 = NSCustomTouchBarItem(identifier: someIdentifier)
item002.viewController = TestViewController()
The TestViewController only loads a simple view inside its loadView()
method.
class TestViewController: NSViewController {
override func loadView() {
self.view = TestView001(frame: NSRect(x: 0, y: 0, width: 100, height: 30))
}
}
The TestView001 only creates a background color so you can see it.
TestView001 has the following code:
class TestView001: NSView {
override init(frame frameRect: NSRect) {
super.init(frame: frameRect)
print("TestView001.init()")
// Create a background color.
self.wantsLayer = true
self.layer?.backgroundColor = NSColor.green.cgColor
}
required init?(coder decoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
All of this works perfectly.
But when I have touched the second item inside the touchbar,
and then close my app's window.
The windowController and everything else is nicely released
from memory.
But I can still see that TestView001 is in memory and not being
released.
When using a standard ui button like in item001, then you don't
have this problem.
It looks like some NSTouch still has a reference to the view
if you look at this image:
However, I do not completely understand this image.
What is the best way of solving this.
Thanks in advance.

NSTextField created from custom class appears randomly

I have a main NSView with 2 NSView subviews containing each a custom NSButton (all created in Interface Builder). My custom button class is programmatically creating an NSTextField below the buttons, by adding it from the superview:
And the custom NSButton class code:
class buttonUpDown: NSButton {
var myLabel:NSTextField!
required public init?(coder: NSCoder) {
super.init(coder: coder)
let labelWidth=CGFloat(90)
print("init")
superview?.autoresizesSubviews = false
myLabel = NSTextField(frame: NSMakeRect(frame.origin.x+frame.size.width/2-labelWidth/2,frame.origin.y-20,labelWidth,16))
myLabel?.stringValue = "Mesh Quality"
myLabel.alignment = .center
myLabel.font? = .systemFont(ofSize: 8)
myLabel.backgroundColor = .red
myLabel.isBordered = false
myLabel.isEditable = false
superview!.addSubview(myLabel)
}
}
When I have a single Button referencing the class, the label appears properly.
But when I have 2, only 1 label is appearing randomly left or right:
What do I miss to have a text displayed below each button ?
Found the issue. Creating a label in the init function will give erratic positioning of the view frame. Adding them from the draw func, makes it more reliable.

How to move or resize an NSView by setting the frame property?

I created the NSView in a storyboard. In this case, it is an NSTextField. In the NSViewController's viewDidLoad() method, I want to conditionally resize and reposition the NSTextField, but setting the frame has no effect.
For example:
class ViewController: NSViewController {
#IBOutlet var label: NSTextField!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
label.frame = NSRect(x: 0, y: 0, width: 200, height: 17)
label.setNeedsDisplay()
}
}
When the view loads, the label still has its original frame as set in interface builder, and not the newly set frame.
How does one programmatically move/resize the label?
The autolayout system is the culprit here. When you set the frame, the autolayout system overrides that to re-establish the implicit constraints set in the storyboard.
Set the translatesAutoresizingMaskIntoConstraints property of the label to true. This tells the autolayout system that it should create a new set of autolayout constraints that satisfy the new frame you've set:
class ViewController: NSViewController {
#IBOutlet var label: NSTextField!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
label.frame = NSRect(x: 0, y: 0, width: 200, height: 17)
label.translatesAutoresizingMaskIntoConstraints = true
label.setNeedsDisplay()
}
}

How to work properly with UIView and drawRect() to customize it in the playground?

Why in playground function drawRect() doesn't work when I want to override it and show view?
I try to do this:
class CustomView: UIView {
override func drawRect(rect: CGRect) {
//some code to change self properties
}
}
let rect = CGRect(x: 0.0, y: 0.0, width: 300.0, height: 300.0)
let view = CustomView(frame: rect)
view
Then I try to change some properties (for example: backgroundColor). But they aren't applied.
I discovered the next case:
To apply set backgroundColor in drawRect I need to call this:
view.setNeedsDisplay()
BUT: From documentation:
For example, you do not need to override this method if your view just
displays a background color or if your view sets its content directly
using the underlying layer object.

swift IBDesignable view not show in storyboard

I want to custom a 5-star UIView,also I want it to be render in storyboard. So I decide to use #IBDesignable and #IBInspectable.The following is my code.
import UIKit
#IBDesignable
class RatingView: UIView {
override init(frame: CGRect) {
super.init(frame: frame)
setUpView()
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setUpView()
}
func setUpView() {
let imageView = UIImageView(frame:CGRectMake(0, 0, 50,50))
imageView.image = UIImage(named: "star")
addSubview(imageView)
}
}
And then in my storyboard , I pull a UIView into my canvas,and set Custom class to my custom view as RatingView.The compiler starts to compile storyboard file and I just wait for the custom view to be renderd in canvas.Here is the screenshot.
The state is "up to date",but the view has not been renderd.The view is just staying white,what I want to see is the image I add to the parent view.
When I use UILabel instead of UIImageView, the label is renderd in the canvas but not the UIImageView,how can I render my lovely star image in my canvas.(Images.xcassets has star.png file)
use UILabel instead of UIImageView
func setUpView() {
let label = UILabel(frame: CGRectMake(0, 0, 50, 50))
label.text = "text"
addSubview(label)
}
result:
I was trying to do the same exact thing. You need to put the view in a framework. As #Benson Tommy said in the comments take a look at WWDC 2014 session 411.
Here is a link to the session:https://developer.apple.com/videos/wwdc/2014/#411
Here is a link to the transcript of the session: http://asciiwwdc.com/2014/sessions/411