What is wrong with that addArrangedSubview code? - swift

I'm trying to understand how addArrangedSubview is working so I tried with a dummy project. Here's my VC :
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var stackOutlet: UIStackView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let newView = UIView(frame: CGRect(x: 0, y: 0, width: 200, height: 200))
newView.backgroundColor = UIColor.darkGray
let newView2 = UIView(frame: CGRect(x: 0, y: 0, width: 200, height: 200))
newView2.backgroundColor = UIColor.blue
stackOutlet.addArrangedSubview(newView)
stackOutlet.addArrangedSubview(newView2)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
When I launch the app, nothing is appearing. I think I have to set some constraints in the stackView?

Ok so for everyone sakes : you need to use this =
mapView.heightAnchor.constraint(equalToConstant: 200).isActive = true
mapView.widthAnchor.constraint(equalToConstant: 200).isActive = true

Related

Button action selector inside class

I recently started developing in Swift (normally embedded C developer).
I want to create some button (later more than one) programmatically and change its label (just for practice).
For this I created a button class, which contains the button init and the callback function. My problem is that it seems like the #selector is not pointing to the instance of the button class the way I expected it will, so a button click does nothing. Can you tell me what I am doing wrong?
#objc class buttontest : NSObject{
let button = NSButton(frame: CGRect(x: 100, y: 100, width: 100, height: 50))
#objc func printSomething() {
print("Hello")
self.button.title="TEST13"
}
func buttoninit() -> NSButton{
self.button.title="Test"
self.button.bezelStyle=NSButton.BezelStyle.rounded
self.button.target=self;
//button.action = Selector(ViewController.printSomething)
self.button.action = #selector(self.printSomething)
return self.button
}
}
class ViewController: NSViewController {
private lazy var redBox = NSView(frame: NSRect(x: 0, y: 0, width: 100, height: 100))
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(redBox)
redBox.wantsLayer = true
redBox.layer?.backgroundColor = NSColor.red.cgColor
//button.init("Test12",self,Selector(printSomething())
let button = buttontest()
self.view.addSubview(button.buttoninit())
//self.view.addSubview(buttontest().buttoninit())
// Do any additional setup after loading the view.
}
override func loadView() {
self.view = NSView(frame: NSRect(x: 0, y: 0, width: NSScreen.main?.frame.width ?? 100, height: NSScreen.main?.frame.height ?? 100))
}
override var representedObject: Any? {
didSet {
// Update the view, if already loaded.
}
}
}
The OK version:
#objc class buttontest : NSObject{
let button = NSButton(frame: CGRect(x: 100, y: 100, width: 100, height: 50))
#objc func printSomething() {
print("Hello")
self.button.title="TEST13"
}
func buttoninit() -> NSButton{
self.button.title="Test"
self.button.bezelStyle=NSButton.BezelStyle.rounded
self.button.target=buttonX
self.button.action = #selector(buttontest.printSomething)
return self.button
}
}
let buttonX = buttontest()
class ViewController: NSViewController {
private lazy var redBox = NSView(frame: NSRect(x: 0, y: 0, width: 100, height: 100))
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(redBox)
redBox.wantsLayer = true
redBox.layer?.backgroundColor = NSColor.red.cgColor
self.view.addSubview(buttonX.buttoninit())
}
}

IPad Playground Has Different View.Frame

I am trying to show this simple ViewController in iPad Playgrounds with this code:
import UIKit
import PlaygroundSupport
class MyViewController : UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
setupViews()
}
func setupViews() {
let view1 = UIView(frame: CGRect(x: 0, y: 0, width: view.frame.width/2, height: 100))
view1.backgroundColor = .red
view.addSubview(view1)
}
}
// Present the view controller in the Live View window
PlaygroundPage.current.liveView = MyViewController()
You can see that, even though it says view.frame.width/2 for the frame of View1, the view still looks like this:
What is wrong? Thank you.
This is the solution I used which got it to work. In Swift Playgrounds, the layout is created in the viewDidLayoutSubview method so all frames should be created there.
You can set your preferred size after you init your ViewController:
import UIKit
import PlaygroundSupport
class VC: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
setupViews()
}
func setupViews() {
let view1 = UIView(frame: CGRect(x: 0, y: 0, width: view.frame.width/2, height: 100))
view1.backgroundColor = .red
view.addSubview(view1)
}
}
let vc = VC()
vc.preferredContentSize = CGSize(width: 768, height: 1024)
PlaygroundPage.current.liveView = vc
Playground with preferredContentSize
Playground without preferredContentSize

Create a horizontal UIScrollView in swift programmatically

I would like to know how to create a horizontal scrollview in swift programmatically without using storyboards, with a page controller.
import UIKit
class SecondViewController: UIViewController, UIScrollViewDelegate {
var scrollview = UIScrollView()
var imageview = UIImageView()
var view1 = UIView()
override func viewDidLoad() {
super.viewDidLoad()
imageview.frame = CGRect(x: 0, y: 0, width: view.frame.size.width , height: 1000)
imageview.image = UIImage(named: "image")
scrollview.delegate = self
scrollview.contentSize = CGSize(width: imageview.frame.width, height: imageview.frame.height)
scrollview.backgroundColor = UIColor.red
imageview.backgroundColor = UIColor.green
self.scrollview.addSubview(imageview)
view.addSubview(scrollview)
scrollview.translatesAutoresizingMaskIntoConstraints = false
scrollview.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
scrollview.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true
scrollview.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
scrollview.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
// Do any additional setup after loading the view.
}
Try This
import UIKit
class ViewController: UIViewController, UIScrollViewDelegate {
var scrollView: UIScrollView!
let textData: String = "Just to add onto the already great answers, you might want to add multiple labels in your project so doing all of this (setting size, style etc) will be a pain. To solve this, you can create a separate UILabel class."
override func viewDidLoad() {
super.viewDidLoad()
let textLable = UILabel(frame: CGRect(x: 0, y: 0, width: 1000, height: 200))
textLable.text = textData
self.scrollView = UIScrollView()
self.scrollView.delegate = self
self.scrollView.contentSize = CGSize(width: textLable.frame.width, height: textLable.frame.height)
scrollView.addSubview(textLable)
view.addSubview(scrollView)
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
scrollView.frame = view.bounds
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}

Event scrolling (scrollViewDidScroll) never called - Swift 3

I would like to detect when the user scroll, I used a UIScrollView, I implemented the UIScrollViewDelegate in my ViewController and tried scrollViewDidScroll, scrollViewDidEndScrollingAnimation and all the others but these events are never called.
import UIKit
class ViewController: UIViewController, UIScrollViewDelegate {
#IBOutlet weak var scrollView: UIScrollView!
override func viewDidLoad() {
super.viewDidLoad()
let xOrigin = self.view.frame.width
let view1 = View1(frame: CGRect(x: 0, y: 0, width:self.view.frame.width, height: self.view.frame.height))
let view2 = View2(frame: CGRect(x: xOrigin, y: 0, width: self.view.frame.width, height: self.view.frame.height))
let view3 = View3(frame: CGRect(x: xOrigin * 2, y: 0, width: self.view.frame.width, height: self.view.frame.height))
scrollView.addSubview(view1)
scrollView.addSubview(view2)
scrollView.addSubview(view3)
self.scrollView.contentSize = CGSize(width: self.view.frame.width * 3, height: self.view.frame.height)
// hide the scrol bar.
scrollView?.showsHorizontalScrollIndicator = false
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
print("end scroll")
}
func scrollViewDidEndScrollingAnimation(_ scrollView: UIScrollView) {
print("end scroll")
}
}
You just have to add the delegate to your viewDidLoad() func:
override func viewDidLoad() {
super.viewDidLoad()
//add this line
self.scrollView.delegate = self
}

How can I draw a simple line?(OS X)

I tried this:
import Cocoa
class ViewController: NSViewController {
#IBOutlet weak var butt: NSButton!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override var representedObject: AnyObject? {
didSet {
// Update the view, if already loaded.
}
}
#IBAction func buttPressed(sender: AnyObject) {
let myPath = NSBezierPath()
myPath.moveToPoint(CGPoint(x: 20, y: 20))
myPath.lineToPoint(CGPoint(x: 100, y: 100))
myPath.stroke()
}
}
It compiles and runs but doesn't draw anything when the button is clicked.
I tried setting the color: NSColor.redColor().set(), setting the width: myPath.lineWidth = 20 and using NSPoint instead of CGPoint but still the same thing happens. What is it that I'm missing?
Thank you for your answers in advance and sorry for the elementary question.
Try doing it inside drawRect (NSView):
import Cocoa
final class Line: NSView {
override func drawRect(dirtyRect: NSRect) {
let myPath = NSBezierPath()
myPath.moveToPoint(CGPoint(x: 20, y: 20))
myPath.lineToPoint(CGPoint(x: 100, y: 100))
myPath.stroke()
}
}
final class ViewController: NSViewController {
override func viewDidLoad() {
super.viewDidLoad()
let frame = CGRect(x: 0, y: 0, width: 100, height: 100)
let line = Line(frame: frame)
view.addSubview(line)
}
override var representedObject: AnyObject? {
didSet {
// Update the view, if already loaded.
}
}
}