use SnapKit make constraint to a UIView but show nothing - swift

At a full clear new swift project from "Single View App" template.
When I ensure SnapKit can be import correctly.
I just play very simple code to show a Rectangle:
let test = UIView()
test.backgroundColor = UIColor.green
test.frame.size = CGSize(width: 500, height: 300)
self.view.addSubview(test)
test.snp.makeConstraints { (maker) in
// maker.top.equalTo(30)
// maker.centerX.equalTo(self.view)
// maker.height.equalTo(100)
}
put this code into func viewDidLoad of "UIViewController.swift" .
from now, SnapKit things is commented, and it's work FINE! like picture showing:
work fine snap(use frame.size)
But when I uncomment SnapKit things, it's display Nothing! like this:
work bad snap(use SnapKit)
So,Please help me find the trouble,thank you!

You don't need to set frame size, if you using constraints.
This how your code should look like:
let test = UIView()
test.backgroundColor = UIColor.green
self.view.addSubview(test)
test.snp.makeConstraints { (make) in
make.top.equalTo(30)
make.centerX.equalToSuperview()
make.height.equalTo(300)
make.width.equalTo(500)
}

Related

How to resize a NSTextView automatically as per its content?

I am making an app where a user can click anywhere on the window and a NSTextView is added programmatically at the mouse location. I have got it working with the below code but I want this NSTextView to horizontally expand until it reaches the edge of the screen and then grow vertically. It currently has a fixed width and when I add more characters, the text view grows vertically (as expected) but I also want it to grow horizontally. How can I achieve this?
I have tried setting isHorizontallyResizable and isVerticallyResizable to true but this doesn't work. After researching for a while, I came across this https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/TextStorageLayer/Tasks/TrackingSize.html but this didn't work for me either.
Code in my ViewController to add the NSTextView to its view:
private func addText(at point: NSPoint) {
let textView = MyTextView(frame: NSRect(origin: point, size: CGSize(width: 150.0, height: 40.0)))
view.addSubview(textView)
}
And, MyTextView class looks like below:
class MyTextView: NSTextView {
override func viewWillDraw() {
isHorizontallyResizable = true
isVerticallyResizable = true
isRichText = false
}
}
I have also seen this answer https://stackoverflow.com/a/54228147/1385441 but I am not fully sure how to implement it. I have added this code snippet in MyTextView and used it like:
override func didChangeText() {
frame.size = contentSize
}
However, I think I am using it incorrectly. Ergo, any help would be much appreciated.
I'm a bit puzzled, because you're adding NSTextView to a NSView which is part of the NSViewController and then you're talking about the screen width. Is this part of your Presentify - Screen Annotation application? If yes, you have a full screen overlay window and you can get the size from it (or from the view controller's view).
view.bounds.size // view controller's view size
view.window?.frame.size // window size
If not and you really need to know the screen size, check the NSWindow & NSScreen.
view.window?.screen?.frame.size // screen size
Growing NSTextView
There's no any window/view controller's view resizing behavior specified.
import Cocoa
class BorderedTextView: NSTextView {
override func draw(_ dirtyRect: NSRect) {
super.draw(dirtyRect)
let path = NSBezierPath(rect: bounds)
NSColor.red.setStroke()
path.stroke()
}
}
class ViewController: NSViewController {
override func mouseUp(with event: NSEvent) {
// Convert point to the view coordinates
let point = view.convert(event.locationInWindow, from: nil)
// Initial size
let size = CGSize(width: 100, height: 25)
// Maximum text view width
let maxWidth = view.bounds.size.width - point.x // <----
let textView = BorderedTextView(frame: NSRect(origin: point, size: size))
textView.insertionPointColor = .orange
textView.drawsBackground = false
textView.textColor = .white
textView.isRichText = false
textView.allowsUndo = false
textView.font = NSFont.systemFont(ofSize: 20.0)
textView.isVerticallyResizable = true
textView.isHorizontallyResizable = true
textView.textContainer?.widthTracksTextView = false
textView.textContainer?.heightTracksTextView = false
textView.textContainer?.size.width = maxWidth // <----
textView.maxSize = NSSize(width: maxWidth, height: 10000) // <----
view.addSubview(textView)
view.window?.makeFirstResponder(textView)
}
}
I finally got it to work (except for one minor thing). The link from Apple was the key here but they haven't described the code completely, unfortunately.
The below code work for me:
class MyTextView: NSTextView {
override func viewWillDraw() {
// for making the text view expand horizontally
textContainer?.heightTracksTextView = false
textContainer?.widthTracksTextView = false
textContainer?.size.width = 10000.0
maxSize = NSSize(width: 10000.0, height: 10000.0)
isHorizontallyResizable = true
isVerticallyResizable = true
isRichText = false
}
}
That one minor thing which I haven't been able to figure out yet is to limit expanding horizontally until the edge of the screen is reached. Right now it keeps on expanding even beyond the screen width and, in turn, the text is hidden after the screen width.
I think if I can somehow get the screen window width then I can replace 10000.0 with the screen width (minus the distance of text view from left edge) and I can limit the horizontal expansion until the edge of the screen. Having said that, keeping it 10000.0 won't impact performance as described in the Apple docs.

How to display a string/int within a UIView in Swift?

this is a very simple question, but I can't find an answer anywhere. I am trying to display a high score within a CGRect, but cannot figure out exactly how to do it. I am currently trying to do this on a playground so that might have something to do with it. Thanks for the help.
You can make a UILabel in a Swift playground. Here's how it might look:
Here's the code from the playground:
import UIKit
let score = 200
let label = UILabel(frame: CGRect(x: 0, y: 0, width: 300, height: 20))
label.backgroundColor = UIColor.purpleColor()
label.textColor = UIColor.orangeColor()
label.text = "High Score: \(score)"
A CGRect is the frame or dimensions assigned to a UIView, not the UIView itself. I would suggest creating a UILabel and add that to your view. You can set the text on the UILabel to, in your case, the high score variable as a string. Im not sure if it is possible to do this in a playground, but I may be mistaken. A XCode project would work perfect for this, but again, im not sure about the playground.
To do this in a playground, it would look like this:
import UIKit
import XCPlayground
let view = UIView(frame: CGRectMake(0,0,500,500)) //create a view and give it a proper size
let label = UILabel(frame: CGRectMake(0,0,100,23)) //create a label with a size
label.text = "My Label" //give the label some text
view.backgroundColor = UIColor.lightGrayColor() //default view in Playground as black background
view.addSubview(label) //add the label to the view
XCPlaygroundPage.currentPage.liveView = view //tell playgound to display your view as the root view in the assistant editor
You need to open the assistant editor in the playground to see the result (the two circles icon in the upper right corner)

NSVisualEffectBlendingMode OS X Swift

I want to be able to make the background of my application blurry so you can almost see through the window like this
rather than the standard window
Thank you!
I Found out the answer I was looking for and thought this might be useful for other people look for something similar. Heres my code :
import Cocoa
class window: NSWindowController {
override func windowDidLoad() {
super.windowDidLoad()
let view = NSVisualEffectView(frame: NSRect(x: 0, y: 0, width: 1500, height: 800))
view.blendingMode = NSVisualEffectBlendingMode.BehindWindow
view.material = NSVisualEffectMaterial.Dark
view.state = NSVisualEffectState.Active
self.window!.contentView!.addSubview(view)
}
}
I made a NSWindowController class and added the code above to it. Then connected the class to the window controller in my main.storyboard.

Programmatically place the Cursor inside a textField of a custom tableView header

How can you programmatically make sure that the cursor of a tableView-HeaderView-TextField gets active (i.e. is the first responder) ??
My table looks like this (i.e with the custom TextField header). So far, the cursor only gets inside the grey header field by clicking inside the textfield. But I would like to be able to get the cursor inside the textfield programmatically....
The code for my custom tableview-header looks like this :
// drawing a custom Header-View with a TextField on top of the tableView
func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let container = UIView(frame: CGRectMake(0, 0, self.view.frame.size.width, 50))
let textField = UITextField(frame: CGRectMake(10, 15, self.view.frame.size.width/2 - 40, 45))
textField.delegate = self
self.txtfield = textField
textField.textColor = UIColor.blackColor()
let placeholder = NSAttributedString(string: "..add player", attributes: [NSForegroundColorAttributeName: UIColor.darkGrayColor()])
textField.attributedPlaceholder = placeholder
textField.backgroundColor = UIColor.lightGrayColor()
container.addSubview(textField)
var headPlusBttn:UIButton = UIButton.buttonWithType(UIButtonType.ContactAdd) as! UIButton
headPlusBttn.center.x = self.view.frame.size.width - 20
headPlusBttn.center.y = 38
headPlusBttn.enabled = true
headPlusBttn.addTarget(self, action: "addTeam:", forControlEvents: UIControlEvents.TouchUpInside)
container.addSubview(headPlusBttn)
return container
}
My first approach was to set the first-responder of the headerViewForSection like this (see code):
// reload entries
func reloadEntries() {
self.tableView.reloadData()
// the following does unfortunately not work !!!!!
self.tableView.headerViewForSection(1)?.becomeFirstResponder()
}
Not sure why this does not work. Maybe, the Section-Nr (Int=1) is wrong. But I tried several section-numbers. No curser where it should be.
Any help appreciated !
Usually adding a delay helps in situations like this. It allows the OS to do everything it wants with the view, and then it won't mess up what you're trying to do at the same time.
Maybe something like this:
func reloadEntries() {
self.tableView.reloadData()
let delay = (Int64(NSEC_PER_SEC) * 0.1)
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, triggerTime), dispatch_get_main_queue(), { () -> Void in
self.tableView.headerViewForSection(1)?.becomeFirstResponder()
})
}
I haven't tested this to do what you want, so you may need to find a different place to put this.
Also, are you sure you want to affect the view in section 1? From your image it looks like you want to mess with the header in section 0.
Be sure to drop into the debugger and check that the header isn't nil. Your code implies that that's a valid condition. You might try writing it like this (at least for testing):
if let header = self.tableView.headerViewForSection(1) {
header.becomeFirstResponder()
}
else {
print("There is no header.")
}
Try
self.tableView.headerViewForSection(1)?.textfield.becomeFirstResponder()

Swift : CGRect interactive?

Hi good fellows of the Code.
I'm still trying to figure out how Swift's working, and how to use it to make nice interactive UI.
Therefore, I'm trying to make an CGRect being draggable, touch-sensible, etc.
I've seen that's it's quite easy to do so with images in the storyboard, but in that case it's not working because the CGRect does not appears in the storyboard as it is generated by the code.
So far, my code is :
import UIKit
class ViewController: UIViewController, UIGestureRecognizerDelegate {
var square: UIView!
override func viewDidLoad() {
super.viewDidLoad()
square = UIView(frame: CGRect(x: 200, y: 200, width: 100, height: 100))
square.backgroundColor = UIColor.grayColor()
square.userInteractionEnabled = true
view.addSubview(square)
}
}
It makes a very nice gray square.
But I can't figure how to make it move. I tried several things, like adding the working code of an IBAction like this :
func handlePan(recognizer:UIPanGestureRecognizer) {
let translation = recognizer.translationInView(self.view)
recognizer.view.center = CGPoint(x:recognizer.view.center.x + translation.x,
y:recognizer.view.center.y + translation.y)
recognizer.setTranslation(CGPointZero, inView: self.view)
}
But it's returning an Thread 1 SIGBRT error.
I tried replacing self.view by square, it's not better.
A link with the error : http://imgur.com/SAmOOXv
If someone here can either show me an example or a link related to that topic I would be extremely happy.
Thanks for the help !
EDIT : To be clear, I tried to work it as a classic IBAction, which means I tried to find a way to call the handlePan function. But either it's not how it's intended to work, or I'm just not doing it right.