Swift 3 Initializing buttons - uibutton

Where does one put button initialization code for controls. It won't work in ViewController.swift correct? because I need it to init immediately, not after a button is pressed.
For example I want rounded corners on the buttons.
#IBAction func buttonAdd(_ sender: AnyObject) {
let button = buttonAdd!
button.backgroundColor = UIColor.cyan
// button.backgroundColor = .clear
button.layer.cornerRadius = 15
button.layer.borderWidth = 1
button.layer.borderColor = UIColor.black.cgColor
}
However the this let statement won't work outside of the function either.
Do I need to put init code in a function?
Where would I call the function from?

'buttonAdd' is a function, not a button.
try this code.
if let button = sender as? UIButton
{
button.backgroundColor = UIColor.cyan
// button.backgroundColor = .clear
button.layer.cornerRadius = 15
button.layer.borderWidth = 1
button.layer.borderColor = UIColor.black.cgColor
}
So, you want to init the button with roundedCorner and border.
There's a 'viewDidLoad' function that called only once in view controller's life cycle.
If you want to do something only once, do it in 'viewDidLoad' function.
override func viewDidLoad()
{
super.viewDidLoad()
let btn = UIButton(type: .custom)
btn.frame = .init(x: 100, y: 100, width: 100, height: 30)
btn.setTitle("Hello", for: .normal)
btn.backgroundColor = UIColor.cyan
btn.layer.cornerRadius = 15
btn.layer.borderColor = UIColor.black.cgColor
btn.layer.borderWidth = 1
// you must call this for rounded corner
btn.layer.masksToBounds = true
self.view.addSubview(btn)
}
If you created your button in Interface Builder, You can do it like this.
#IBOutlet weak var btn: UIButton!
override func viewDidLoad()
{
super.viewDidLoad()
btn.layer.cornerRadius = 15
btn.layer.borderColor = UIColor.black.cgColor
btn.layer.borderWidth = 1
// you must call this for rounded corner
btn.layer.masksToBounds = true
}

I found the answer to my question...You would put button init code in ViewController.Swift...in the following function created automatically by the View Controller and you must add button Outlet in addition to button Action.
override func viewDidLoad() {
super.viewDidLoad()
let button = buttonAdd!
button.backgroundColor = UIColor.cyan
// button.backgroundColor = .clear
button.layer.cornerRadius = 10
button.layer.borderWidth = 1
button.layer.borderColor = UIColor.black.cgColor

Related

How to have a button which is projected outside the NSView?

I want to implement a button which is projected outside the NSView. The similar button is shown in below image.
If you have to have a view overflowing the window, you can't do that using the masksToBound property of CALayer. You need to use a child borderless window and position it correctly.
Here's an example (in ObjC):
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
// Insert code here to initialize your application
NSRect windowFrame = self.window.frame;
NSRect childWindowFrame = {
.origin.x = CGRectGetMidX(windowFrame) - 25,
.origin.y = CGRectGetMinY(windowFrame) - 25,
.size.width = 50,
.size.height = 50,
};
NSWindow *childWindow = [[NSWindow alloc] initWithContentRect:childWindowFrame
styleMask:NSWindowStyleMaskBorderless
backing:NSBackingStoreBuffered
defer:YES];
childWindow.backgroundColor = [NSColor clearColor];
childWindow.contentView.wantsLayer = YES;
childWindow.contentView.layer.backgroundColor = [NSColor redColor].CGColor;
childWindow.contentView.layer.cornerRadius = 25.0;
[self.window addChildWindow:childWindow ordered:NSWindowAbove];
}
The red circle in this screenshot is the child window.
You can do this by making sure your parent view is layer backed and setting the masksToBounds property of its layer to false.
Here's an AppKit playground showing this in action:
//: A Cocoa based Playground to present user interface
import AppKit
import PlaygroundSupport
let nibFile = NSNib.Name("MyView")
var topLevelObjects : NSArray?
Bundle.main.loadNibNamed(nibFile, owner:nil, topLevelObjects: &topLevelObjects)
let views = (topLevelObjects as! Array<Any>).filter { $0 is NSView }
let rootView = views.first as! NSView
// create parent
let parentView = NSView()
rootView.addSubview(parentView)
parentView.wantsLayer = true
parentView.layer?.masksToBounds = false
parentView.layer?.backgroundColor = NSColor.red.cgColor
parentView.translatesAutoresizingMaskIntoConstraints = false
parentView.centerXAnchor.constraint(equalTo: rootView.centerXAnchor).isActive = true
parentView.centerYAnchor.constraint(equalTo: rootView.centerYAnchor).isActive = true
parentView.widthAnchor.constraint(equalToConstant: 200).isActive = true
parentView.heightAnchor.constraint(equalToConstant: 200).isActive = true
let childView = NSView()
parentView.addSubview(childView)
childView.wantsLayer = true
childView.layer?.backgroundColor = NSColor.green.cgColor
childView.translatesAutoresizingMaskIntoConstraints = false
childView.centerXAnchor.constraint(equalTo: parentView.leadingAnchor).isActive = true
childView.centerYAnchor.constraint(equalTo: parentView.centerYAnchor).isActive = true
childView.widthAnchor.constraint(equalToConstant: 100).isActive = true
childView.heightAnchor.constraint(equalToConstant: 100).isActive = true
// Present the view in Playground
PlaygroundPage.current.liveView = views[0] as! NSView
This will draw:
The green view is a child of the red view.

ios 10 Snapshotting a view that has not been rendered results in an empty snapshot

this question ask again but i dont find for ios 10
if UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.camera)
{
self.imagePicker.delegate = self
self.imagePicker.sourceType = UIImagePickerControllerSourceType.camera;
self.imagePicker.allowsEditing = false
self.imagePicker.cameraCaptureMode = .photo
//self.imagePicker.modalPresentationStyle = UIModalPresentationStyle.overCurrentContext
self.present(self.imagePicker, animated: true, completion: nil)
self.imagePicked.isUserInteractionEnabled = true
}
else
{
print("No Camera")
}
Snapshotting a view that has not been rendered results in an empty
snapshot.Ensure your view has been rendered at least once before
snapshotting or snapshot after screen updates.
when i rotate the camera and take a shot than this error occurs.
Self Solution Working for me like charm :-) hope its helpful for all
DispatchQueue.global(qos: .userInitiated).async
{
self.present(self.imagePicker, animated: true, completion: nil)
}
I got the error
This application is modifying the autolayout engine from a background thread, which can lead to engine corruption and weird crashes...
Using DispatchQueue.main.async instead works for me.
This behavior is not limited to UIImagePickerController. Below is an example of a UIViewController which presents another UIViewController modally. In the second UIViewController, Safari is launched to present a URL, thus triggering the same error message, "Cannot snapshot view (>) with afterScreenUpdates:NO, because the view is not in a window. Use afterScreenUpdates:YES."
I haven't yet found any way of suppressing the message, but in my app it does no harm. I think what's going on here is that some Apple code is taking a snapshot of the app's view hierarchy, but the keyboard (which is owned by a separate UIWIndow) has not been rendered before the snapshot is taken.
/* Generates the error message:
Cannot snapshot view (<UIKeyboardImpl: 0x7f82ded12ea0; frame = (0 0; 414 271); layer = <CALayer: 0x610000035e20>>) with afterScreenUpdates:NO, because the view is not in a window. Use afterScreenUpdates:YES.
... after the "Now Tap Me, For Glory!" label is clicked
*/
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let input = UITextField()
input.placeholder = "Tap here first -- to bring up keyboard"
input.frame = CGRect(x: 10, y: 50, width: 300, height: 20)
view.addSubview(input)
let button = UIButton()
button.setTitleColor(UIColor.blue, for: .normal)
button.setTitle("Then tap here", for: .normal)
button.addTarget(self,
action: #selector(buttonPushed),
for: .touchUpInside)
button.frame = CGRect(x: 10, y: 80, width: 200, height: 20)
view.addSubview(button)
}
func buttonPushed() {
let modalVC = ModalViewController()
present(modalVC, animated: true, completion: nil)
}
}
class ModalViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor.white
let label = UILabel()
label.text = "Now Tap Me, For Glory!"
label.frame = CGRect(x: 10, y: 50, width: 300, height: 20)
view.addSubview(label)
label.isUserInteractionEnabled = true
label.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(labelTapped)))
}
func labelTapped() {
UIApplication.shared.open(URL(string: "http://planetbeagle.com")!, options: [:], completionHandler: { _ in
self.dismiss(animated: true, completion: nil) })
}
}

How to draw a dash line border for NSView

In my custom view, i have code as below:
- (void)drawRect:(NSRect)dirtyRect {
[super drawRect:dirtyRect];
//Drawing code here.
[self setWantsLayer: YES];
[self.layer setBorderWidth: 1];
[self.layer setBorderColor:[NSColor colorWithRed:205/255.0 green:211/255.0 blue:232/255.0 alpha:1.0].CGColor];
[self.layer setCornerRadius: 10];
}
This is OK to set border line and color for my NSView, but i want to set a dash line, anyone know how to do this?
And i tried some codes from the web search, but it doens't draw a border at all.
- (void)drawRect:(NSRect)dirtyRect {
[super drawRect:dirtyRect];
// Drawing code here.
CGFloat dashPattern[] = {10,4}; //make your pattern here
NSBezierPath *textViewSurround = [NSBezierPath bezierPathWithRoundedRect:self.frame xRadius:10 yRadius:10];
[textViewSurround setLineWidth:2.0f];
[textViewSurround setLineDash:dashPattern count:2 phase:0];
[[NSColor colorWithRed:205/255.0 green:211/255.0 blue:232/255.0 alpha:1.0] set];
[textViewSurround stroke];
}
here is a complete example using a subclass of NSView in Swift 3:
class BorderedView: NSView {
override func draw(_ dirtyRect: NSRect) {
super.draw(dirtyRect)
// dash customization parameters
let dashHeight: CGFloat = 3
let dashLength: CGFloat = 10
let dashColor: NSColor = .red
// setup the context
let currentContext = NSGraphicsContext.current()!.cgContext
currentContext.setLineWidth(dashHeight)
currentContext.setLineDash(phase: 0, lengths: [dashLength])
currentContext.setStrokeColor(dashColor.cgColor)
// draw the dashed path
currentContext.addRect(bounds.insetBy(dx: dashHeight, dy: dashHeight))
currentContext.strokePath()
}
}
In case you want to setup line border with CAShapeLayer (Swift 4.2):
class StrokeWithDashedLineView: NSView {
private let shapeLayer = CAShapeLayer()
private let fillLayer = CALayer()
private let textLabel = NSTextField().autolayoutView()
override init(frame frameRect: NSRect) {
super.init(frame: frameRect)
setupUI()
setupLayout()
}
required init?(coder decoder: NSCoder) {
fatalError()
}
override var intrinsicContentSize: NSSize {
return CGSize(intrinsicHeight: 76)
}
override func layout() {
super.layout()
updateLayers()
}
private func updateLayers() {
layer?.cornerRadius = 0.5 * bounds.height // Making ourselves rounded.
// Stroke Layer
let shapeBounds = CGRect(width: bounds.width - shapeLayer.lineWidth, height: bounds.height - shapeLayer.lineWidth)
let shapeRadius = 0.5 * shapeBounds.height
let path = CGMutablePath()
path.addRoundedRect(in: shapeBounds, cornerWidth: shapeRadius, cornerHeight: shapeRadius)
shapeLayer.path = path
shapeLayer.bounds = shapeBounds
shapeLayer.position = CGPoint(x: 0.5 * shapeLayer.lineWidth, y: 0.5 * shapeLayer.lineWidth)
// Fill Layer
let fillBounds = CGRect(width: bounds.width - 2 * shapeLayer.lineWidth, height: bounds.height - 2 * shapeLayer.lineWidth)
fillLayer.cornerRadius = 0.5 * fillBounds.height
fillLayer.bounds = fillBounds
fillLayer.position = CGPoint(x: shapeLayer.lineWidth, y: shapeLayer.lineWidth)
}
private func setupUI() {
wantsLayer = true
layer?.masksToBounds = true
shapeLayer.lineWidth = 3
shapeLayer.strokeColor = NSColor.red.cgColor
shapeLayer.fillColor = nil
shapeLayer.lineDashPattern = [11.2, 11.2]
shapeLayer.lineCap = .round
shapeLayer.anchorPoint = .zero
fillLayer.backgroundColor = NSColor.yellow.cgColor
fillLayer.anchorPoint = .zero
layer?.addSublayer(shapeLayer)
layer?.addSublayer(fillLayer)
addSubview(textLabel)
textLabel.text = "Drag Xib or Storyboard files onto\nthis window to open them"
textLabel.alignment = .center
textLabel.textColor = .black
textLabel.font = NSFont.semibold(size: 13)
textLabel.isEditable = false
textLabel.drawsBackground = false
textLabel.isBezeled = false
}
private func setupLayout() {
textLabel.centerXAnchor.constraint(equalTo: centerXAnchor).activate()
textLabel.centerYAnchor.constraint(equalTo: centerYAnchor).activate()
}
}
Result:
You can do this through CGContext Here is an answer that worked for me:
how to make dashed line moveable
And my result:
You can do this like,
[yourView.layer setBorderWidth:5.0];
[yourView.layer setBorderColor:[[UIColor colorWithPatternImage:[UIImage imageNamed:#"DotedImage.png"]] CGColor]];
Add dashed image in project and import QuartzCore/QuartzCore.hin project,
#import <QuartzCore/QuartzCore.h>
Update :
Image size and View size should be same.

XIB View background is set to Clear Color, but it is not transparent

I need set backgroud color in title to transparent, but it is not set to transparent, i am using custom dialog pin in MAPKit. whats is wrong ?
Backgroud View color is set to CLear Color..
And programatically is set color to Clear Color:
customMarkerXIB.backgroundColor = UIColor.clearColor()
import UIKit
#IBDesignable class Widget: UIView {
var view: UIView!
var nibName: String = "Widget"
#IBOutlet weak var titleLabel: UILabel!
/* #IBInspectable var image: UIImage? {
get {
return imageView.image
}
set(image) {
imageView.image = image
}
}
*/
#IBInspectable var title: String? {
get {
return titleLabel.text
}
set(title) {
titleLabel.text = title
}
}
func setSelectedState(){
println("hola")
}
// init
override init(frame: CGRect) {
// properties
super.init(frame: frame)
// Set anything that uses the view or visible bounds
setup()
}
required init(coder aDecoder: NSCoder) {
// properties
super.init(coder: aDecoder)
// Setup
setup()
}
func setup() {
view = loadViewFromNib()
view.frame = bounds
view.autoresizingMask = UIViewAutoresizing.FlexibleWidth | UIViewAutoresizing.FlexibleHeight
addSubview(view)
}
func loadViewFromNib() -> UIView {
let bundle = NSBundle(forClass: self.dynamicType)
let nib = UINib(nibName: nibName, bundle: bundle)
let view = nib.instantiateWithOwner(self, options: nil)[0] as UIView
return view
}
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
override func drawRect(rect: CGRect) {
// Drawing code
}
*/
}
Loading custom annotation
func mapView(mapView: MKMapView!, viewForAnnotation annotation: MKAnnotation!) -> MKAnnotationView! {
var identifier = "CustomAnnotation"
var position = 0;
if let mapPin = annotation as? MyAnnotation {
position = mapPin.position; // assosiate annotation with a position
}
if annotation.isKindOfClass(MyAnnotation) {
var marker = mapView.dequeueReusableAnnotationViewWithIdentifier(identifier)
if marker == nil {
marker = MKAnnotationView(annotation: annotation, reuseIdentifier: identifier)
marker.tag = position;
marker.image = UIImage(named: "mapa_pin")
marker.centerOffset = CGPointMake(0, -10)
marker.canShowCallout = true
marker.backgroundColor = UIColor.clearColor()
//var pointTitle = marker!.annotation.title! as String
/* var label:UILabel = UILabel(frame: CGRectMake(0, CGFloat(floorf((56.0-20)/2)), 26.0, 20))
label.backgroundColor = UIColor.clearColor()
label.text = "asdfasdfasdfasd"
label.textAlignment = NSTextAlignment.Center
label.font = UIFont.systemFontOfSize(11.0)
marker.addSubview(label) */
var customMarkerXIB : Widget = Widget(frame: CGRect(x: 0, y: 250, width: 300, height: 150))
customMarkerXIB.backgroundColor = UIColor.clearColor()
customMarkerXIB.title = "olakease";
customMarkerXIB.setSelectedState()
marker.rightCalloutAccessoryView = customMarkerXIB
// Callout
/* var button = UIButton.buttonWithType(.DetailDisclosure) as UIButton
marker!.leftCalloutAccessoryView = button
var image = UIImageView(image: UIImage(named: "mapa_pin"))
marker!.rightCalloutAccessoryView = image*/
} else {
marker!.annotation = annotation
}
return marker
}

CSStickyHeaderFlowLayout swift

I'm trying to make parallax photo effect in my app using CSStickyHeaderFlowLayout
- https://github.com/jamztang/CSStickyHeaderFlowLayout/
and Swift language.
I have installed necessary Pod's file, add #import "CSStickyHeaderFlowLayout.h" to my "appName"-Bridging-Header.h file, and implemented this method:
func collectionView(collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, atIndexPath indexPath: NSIndexPath) -> UICollectionReusableView {
var cell: UICollectionViewCell = UICollectionViewCell(frame: CGRectMake(0, 0, 400, 200));
var imageView: UIImageView = UIImageView();
var image: UIImage = UIImage(named: "news2.jpg")!;
imageView.image = image;
cell.addSubview(imageView);
return cell;
}
but now I have difficulties to translate this Obj-C code to Swift:
CSStickyHeaderFlowLayout *layout = (id)self.collectionViewLayout;
if ([layout isKindOfClass:[CSStickyHeaderFlowLayout class]]) {
layout.parallaxHeaderReferenceSize = CGSizeMake(320, 200);
}
In my opinion after that step my effect should works. Am I right? Or I have missed something?
Thanks for help,
m.af
You should be able to do it like this in Swift
if let layout = self.collectionViewLayout as? CSStickyHeaderFlowLayout {
layout.parallaxHeaderReferenceSize = CGSizeMake(320, 200)
}
You could try this:
var layout = CSStickyHeaderFlowLayout()
if (layout.isKindOfClass(CSStickyHeaderFlowLayout.self)) {
layout.parallaxHeaderReferenceSize = CGSizeMake(self.view.frame.size.width, 426)
layout.parallaxHeaderMinimumReferenceSize = CGSizeMake(self.view.frame.size.width, 110)
layout.itemSize = CGSizeMake(self.view.frame.size.width, layout.itemSize.height)
layout.parallaxHeaderAlwaysOnTop = true
// If we want to disable the sticky header effect
layout.disableStickyHeaders = true
}