Init NSViewController without nib - macos

https://stackoverflow.com/a/28334583/4107801
I tried the method mentioned in this answer but it crashes with bad access every time.
Maybe the private APIs have changed or I'm simply implementing it incorrectly. Here is my implementation:
override func loadView() {
view.frame = CGRect(origin: CGPoint(x: 100, y: 100), size: CGSize(width: 1000, height: 1000))
//view = self.view
splitView = NSSplitView(frame: view.frame)
splitView?.autoresizingMask = .ViewWidthSizable | .ViewHeightSizable
splitView?.setPosition(300, ofDividerAtIndex: 0)
view.addSubview(splitView!)
}

LoadView doesn't init the contentView in the controller so you have to do that manually too.
Adding
view = NSView(frame:CGRect(origin: CGPoint(x: 100, y: 100), size: CGSize(width: 1000, height: 1000)))
solved the problem.

Related

simple fade in function in xcode

despite my best efforts, I am failing on the code for the fade-in timing of my frame. for some reason that I cant understand, the withDuration is not fading at all.
if someone has a moment to review my code I would v much appreciate the help...
import UIKit
import PlaygroundSupport
let view = UIView(frame: CGRect(x: 128, y: 128, width: 256, height: 256))
view.backgroundColor = .red
UIView.animate(withDuration: 3) {
view.alpha = 1
}
let containerView = UIView(frame: CGRect(x: 0, y: 0, width: 512, height:
512))
containerView.backgroundColor = .white
PlaygroundPage.current.liveView = containerView
containerView.addSubview(view)
Problem 1: view.alpha is already 1 so there is nothing to animate.
Problem 2: Order matters. Things happen in the order you command them. That order must be coherent.
So:
let containerView = UIView(frame: CGRect(x: 0, y: 0, width: 512, height: 512))
containerView.backgroundColor = .white
PlaygroundPage.current.liveView = containerView
let view = UIView(frame: CGRect(x: 128, y: 128, width: 256, height: 256))
view.alpha = 0
view.backgroundColor = .red
containerView.addSubview(view)
UIView.animate(withDuration: 3) {
view.alpha = 1
}

How to make the keyboard same size as the view

In the following code, the UIKeyboard is bigger than the view.
Question: How to make the keyboard same size as the view?
import UIKit
import PlaygroundSupport
class MyViewController : UIViewController, UITextFieldDelegate {
override func loadView() {
let view = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
view.backgroundColor = .white
let label = UITextField()
label.frame = CGRect(x: 150, y: 200, width: 200, height: 20)
label.text = "Hello World!"
label.textColor = .black
label.addTarget(self, action: #selector(myTargetFunction), for: .touchDown)
view.addSubview(label)
self.view = view
}
#objc func myTargetFunction() {
print("It works!")
}
}
// Present the view controller in the Live View window
PlaygroundPage.current.liveView = MyViewController()
The only "solution" I discovered so far is to set the preferredContentSize of your UIViewController to the size of the UIScreen.main of the current Xcode Playground environment:
let vc = MyViewController()
vc.preferredContentSize = UIScreen.main.bounds.size
PlaygroundPage.current.liveView = vc

CGRectMake, CGPointMake, CGSizeMake, CGRectZero, CGPointZero is unavailable in Swift

After converting code to latest swift 3.0 I am shown this error.
Also tell me solution for CGSize = CGSizeMake(0,0)
static var frameAtStartOfPan: CGRect = CGRectZero
static var startPointOfPan: CGPoint = CGPointZero
Which is also unavailable.
CGRect Can be simply created using an instance of a CGPoint or CGSize, thats given below.
let rect = CGRect(origin: CGPoint(x: 0,y :0), size: CGSize(width: 100, height: 100))
// Or
let rect = CGRect(origin: .zero, size: CGSize(width: 100, height: 100))
Or if we want to specify each value in CGFloat or Double or Int, we can use this method.
let rect = CGRect(x: 0, y: 0, width: 100, height: 100) // CGFloat, Double, Int
CGPoint Can be created like this.
let point = CGPoint(x: 0,y :0) // CGFloat, Double, Int
CGSize Can be created like this.
let size = CGSize(width: 100, height: 100) // CGFloat, Double, Int
Also size and point with 0 as the values, it can be done like this.
let size = CGSize.zero // width = 0, height = 0
let point = CGPoint.zero // x = 0, y = 0, equal to CGPointZero
let rect = CGRect.zero // equal to CGRectZero
CGRectZero & CGPointZero replaced with CGRect.zero & CGPoint.zero in Swift 3.0.
Quick fix for CGRectMake , CGPointMake, CGSizeMake in Swift3 & iOS10
Add these extensions :
extension CGRect{
init(_ x:CGFloat,_ y:CGFloat,_ width:CGFloat,_ height:CGFloat) {
self.init(x:x,y:y,width:width,height:height)
}
}
extension CGSize{
init(_ width:CGFloat,_ height:CGFloat) {
self.init(width:width,height:height)
}
}
extension CGPoint{
init(_ x:CGFloat,_ y:CGFloat) {
self.init(x:x,y:y)
}
}
Then go to "Find and Replace in Workspace"
Find CGRectMake , CGPointMake, CGSizeMake and Replace them with CGRect , CGPoint, CGSize
These steps might save all the time as Xcode right now doesn't give us quick conversion from Swift 2+ to Swift 3
In Swift 3, you can simply use CGPoint.zero or CGRect.zero in place of CGRectZero or CGPointZero.
However, in Swift 4, CGRect.zero and 'CGPoint.zero' will work
If you want to use them as in swift 2, you can use these funcs:
For CGRectMake:
func CGRectMake(_ x: CGFloat, _ y: CGFloat, _ width: CGFloat, _ height: CGFloat) -> CGRect {
return CGRect(x: x, y: y, width: width, height: height)
}
For CGPointMake:
func CGPointMake(_ x: CGFloat, _ y: CGFloat) -> CGPoint {
return CGPoint(x: x, y: y)
}
For CGSizeMake:
func CGSizeMake(_ width: CGFloat, _ height: CGFloat) -> CGSize {
return CGSize(width: width, height: height)
}
Just put them outside any class and it should work. (Works for me at least)
The structures as well as all other symbols in Core Graphics and other APIs have become cleaner and also include parameter names.
https://developer.apple.com/reference/coregraphics#symbols
CGRect(x: Int, y: Int, width: Int, height: Int)
CGVector(dx: Int, dy: Int)
CGPoint(x: Double, y: Double)
CGSize(width: Int, height: Int)
CGPoint Example:
let newPoint = stackMid.convert(CGPoint(x: -10, y: 10), to: self)
CGVector Example:
self.physicsWorld.gravity = CGVector(dx: 0, dy: gravity)
CGSize Example:
hero.physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: 16, height: 18))
CGRect Example:
let back = SKShapeNode(rect: CGRect(x: 0-120, y: 1024-200-30, width: 240, height: 140), cornerRadius: 20)
Apple Blog
Swift syntax and API renaming changes in Swift 3 make the language feel more natural, and provide an even more Swift-y experience when calling Cocoa frameworks. Popular frameworks Core Graphics and Grand Central Dispatch have new, much cleaner interfaces in Swift.
Swift 3 Bonus: Why didn't anyone mention the short form?
CGRect(origin: .zero, size: size)
.zero instead of CGPoint.zero
When the type is defined, you can safely omit it.
Try the following:
var myToolBar = UIToolbar.init(frame: CGRect.init(x: 0, y: 0, width: 320, height: 44))
This is for the swift's latest version
You can use this with replacement of CGRectZero
CGRect.zero
For CGSize
CGSize(width: self.view.frame.width * 3, height: self.view.frame.size.height)
Instead of CGSizeMake add CGSize it will work.
CGSizeMake is used in objective c.
you don't want to use make with swift
In Swift 4 it works like below
collectionView.setContentOffset(CGPoint.zero, animated: true)

Text Field with Only top and Bottom Border using swift 2

I have a page for forgot password. It has only a text field asking the user to fill in their email address. The Designer designed the text field with top and bottom border only.
I tried answer from here UITextField Only Top And Bottom Border
but in the result it only shows bottom border for the text field.
Like in the image i would like to create a grey border for top and bottom
To remove Fights with views you could create a tableView with a static cell that contains a TextField. Voila done... Top and bottom border comes for free and you will use standard apple stuff :)
If you really want to draw the layers than follow the steps on your linked questions:
CALayer *topBorder = [CALayer layer];
topBorder.frame = CGRectMake(0, 0, self.frame.size.width, 1);
topBorder.backgroundColor = [UIColor blackColor].CGColor;
[myTextField.layer addSublayer:topBorder];
CALayer *bottomBorder = [CALayer layer];
bottomBorder.frame = CGRectMake(0, self.frame.size.height - 1, self.frame.size.width, 1);
bottomBorder.backgroundColor = [UIColor blackColor].CGColor;
[myTextField.layer addSublayer:bottomBorder];
In Swift:
let topBorder = CALayer()
topBorder.frame = CGRectMake(0, 0, bounds.size.width, 1)
topBorder.backgroundColor = UIColor.grayColor()
textField.layer.addSublayer(topBorder)
let bottomBorder = CALayer()
bottomBorder.frame = CGRectMake(0, bounds.size.height-1, bounds.size.width, 1)
bottomBorder.backgroundColor = UIColor.grayColor()
textField.layer.addSublayer(bottomBorder)
Thanks #El Captain for the valuable comment and nice answer by #Bjorn Ro even if it was in Objective-c i think.
And my answer for the question is (i'm using swift 2 Xcode 7)
Override the function viewDidLayoutSubviews() in your swift file. And the Code for the same is
override func viewDidLayoutSubviews() {
// Creates the bottom border
let borderBottom = CALayer()
let borderWidth = CGFloat(2.0)
borderBottom.borderColor = UIColor.grayColor().CGColor
borderBottom.frame = CGRect(x: 0, y: forgotPasswordEmailText.frame.height - 1.0, width: forgotPasswordEmailText.frame.width , height: forgotPasswordEmailText.frame.height - 1.0)
borderBottom.borderWidth = borderWidth
forgotPasswordEmailText.layer.addSublayer(borderBottom)
forgotPasswordEmailText.layer.masksToBounds = true
// Creates the Top border
let borderTop = CALayer()
borderTop.borderColor = UIColor.grayColor().CGColor
borderTop.frame = CGRect(x: 0, y: 0, width: forgotPasswordEmailText.frame.width, height: 1)
borderTop.borderWidth = borderWidth
forgotPasswordEmailText.layer.addSublayer(borderTop)
forgotPasswordEmailText.layer.masksToBounds = true
}
forgotPasswordEmailText is the text field for entering Email
The Final output looks like this... with a gray Colour border (Screen shot of iPhone 4s Simulator)
Good suggestions for programatic solution posted so far. But I figured I'd share an Interfacebuilder solution....
1) Create view collection in your view controller
#IBOutlet private var borderViews: [UIView]?
2) Create 2 UIViews in interface builder 1px high constrained to where you want them around the textfield
3) Connect the 2 views in interface builder to borderViews IBOutlet
4) Customise appearance of both views by using setValue forKeyPath... for example, on success you may want the border to turn green
setValue(UIColor.green, forKeyPath: "borderViews.backgroundColor")
In Swift 3 use extension:
Create Swift file
import UIKit
extension UITextField {
func setBottomBorder() {
self.borderStyle = .none
self.layer.backgroundColor = UIColor.white.cgColor
self.layer.masksToBounds = false
self.layer.shadowColor = UIColor.gray.cgColor
self.layer.shadowOffset = CGSize(width: 0.0, height: 1.0)
self.layer.shadowOpacity = 1.0
self.layer.shadowRadius = 0.0
}
}
Call from anywhere:
PasswordField.setBottomBorder();
Here's a nice and easy Swift 4 implementation that handles resizing views as well :)
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
viewToShadow.backgroundColor = .white
viewToShadow.layer.masksToBounds = false
viewToShadow.layer.sublayers?
.filter { layer -> Bool in
return layer.backgroundColor == UIColor.almostBlack.alpha(0.5).cgColor
}
.forEach { layer in
layer.removeFromSuperlayer()
}
[CGRect(x: 0.0, y: 0.0, width: viewToShadow.bounds.width, height: 0.5),
CGRect(x: 0.0, y: viewToShadow.bounds.height, width: viewToShadow.bounds.width, height: 0.5)]
.forEach { frame in
let layer = CALayer()
layer.frame = frame
layer.backgroundColor = UIColor.almostBlack.alpha(0.5).cgColor
viewToShadow.layer.addSublayer(layer)
}
}
Use handy extension for it
extension UITextField {
func addTopBorder(){
let bottomLine = CALayer()
bottomLine.frame = CGRect.init(x: 0, y: 0, width: self.frame.size.width, height: 1)
bottomLine.backgroundColor = UIColor.white.cgColor
self.borderStyle = UITextField.BorderStyle.none
self.layer.addSublayer(bottomLine)
}
func addBottomBorder(){
let bottomLine = CALayer()
bottomLine.frame = CGRect.init(x: 0, y: self.frame.size.height - 1, width: self.frame.size.width, height: 1)
bottomLine.backgroundColor = UIColor.white.cgColor
self.attributedPlaceholder = NSAttributedString(string: self.placeholder ?? "-", attributes: [NSAttributedString.Key.foregroundColor : #colorLiteral(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0)])
self.borderStyle = UITextField.BorderStyle.none
self.layer.addSublayer(bottomLine)
}
}
use it in you controller like this
yourTextfield.addTopBorder()
yourTextfield.addBottomBorder()
and don't forget to use it on main thread
DispatchQueue.main.async {
self.yourTextfield.addTopBorder()
self.yourTextfield.addBottomBorder()
}

Why is UIBarButtonItem image always fuzzy/blurry/pixelated

Here is my current code:
var reply = UIBarButtonItem(image: UIImage(named: "reply"), style: UIBarButtonItemStyle.Plain, target: self, action: Selector("reply:"))
self.navigationItem.rightBarButtonItem = reply
The button in the top right corner is always fuzzy. This is a screenshot from an iPhone4s device so it is not a retina-related issue.
I have tried different image sizes ranging from 30x30 to 512x512 and adding the image using customView. These methods have not fixed the issue.
Thanks in advance.
I have solved it using this method:
var replyBtn = UIButton(frame: CGRect(x: 0, y: 0, width: 30, height: 30))
replyBtn.setImage(UIImage(named: "reply"), forState: UIControlState.Normal)
replyBtn.addTarget(self.navigationController, action: Selector("reply:"), forControlEvents: UIControlEvents.TouchUpInside)
var item = UIBarButtonItem(customView: replyBtn)
self.navigationItem.rightBarButtonItem = item
It displays a very crisp button using the exact same image.
From IOS human interface guide the icon should be 22x22
Take a look at the documentation here:
https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/MobileHIG/BarIcons.html
Try this:
func createBarButton(image: String, size: CGSize, offset: (x: CGFloat, y: CGFloat) = (0,0), hightlightable: Bool = true, action: Selector) -> UIBarButtonItem {
let btn = UIButton(type: .custom)
let img = UIImage(named: image)
btn.setBackgroundImage(img, for: .normal)
btn.addTarget(self, action: action, for: .touchUpInside)
btn.frame = CGRect(x: offset.x, y: offset.y, width: size.width, height: size.height)
btn.adjustsImageWhenHighlighted = hightlightable
let view = UIView(frame: CGRect(x: 0, y: 0, width: size.width, height: size.height))
// view.bounds = view.bounds.offsetBy(dx: offset.x, dy: offset.y)
view.addSubview(btn)
let barButton = UIBarButtonItem(customView: view)
return barButton
}
self.navigationItem.rightBarButtonItem = createBarButton(image: "YOUR_IMAGE",
size: CGSize(width: 35, height: 35),
offset: (x: -10, y: 0),
action: #selector(showXY))

Resources