Swift : CGRect interactive? - swift

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.

Related

Using TVPosterImage in TVUIKit for tvOS 12

tvOS 12 has a new framework TVUIKit, which introduces the lockup views. The class I am interested in is TVPosterView, which is basically designed as such:
Swift 4.2
open class TVPosterView : TVLockupView { // One may use UIControl to implement it in iOS
public init(image: UIImage?)
open var image: UIImage? // default is nil
open var title: String?
open var subtitle: String?
}
In my storyboard I have added an UIView element, and rightly (at least I hope so. Yesterday the IB agent kept crashing!) changed its class to TVPosterView in Identity Inspector. then in my UIViewController I have defined:
#IBOutlet var aPosterView: TVPosterView!
override func viewDidLoad() {
super.viewDidLoad()
if let myIcon = UIImage(named: "icon.png") {
self.aPosterView = TVPosterView(image: myIcon)
self.aPosterView.title = "My Title"
self.aPosterView.subtitle = "A Sub Title"
}
else {
print("ERROR: I couldn't load the icon!")
}
}
}
It compiles without any warning. When I run it, it just shows the UIView white background, nothing changes. I did some tests trying to add an UIImageView, but they were all inconclusive (apart, off course, when I did set the image of UIImageView to self.aPosterView.image).
I am far from being an expert, I just started learning a couple of weeks ago. Any idea about what I am missing? I thought the concept was that once I initiated the class the framework was taking care of displaying the poster with the (optional) title and subtitles, also taking care of all nice animations!
Eventually I managed to make it working programmatically. I tested both TVPosterView and TVMonogramView (basically a round button). The following code works with Xcode 10 beta 5, on tvOS 12 beta 5:
Swift 4.2
import UIKit
import TVUIKit
class SecondViewController: UIViewController {
var myPoster = TVPosterView()
var myMonogram = TVMonogramView()
override func viewDidLoad() {
super.viewDidLoad()
myPoster.frame = CGRect(x: 100, y: 100, width: 550, height: 625)
myPoster.image = UIImage(named: "image1.png")
myPoster.imageView.masksFocusEffectToContents = true
myPoster.title = "Poster"
myPoster.subtitle = "This is the poster subtitle"
self.view.addSubview(myPoster)
var myName = PersonNameComponents()
myName.givenName = "Michele"
myName.familyName = "Dall'Agata"
myMonogram.frame = CGRect(x: 700, y: 100, width: 500, height: 475)
myMonogram.image = UIImage(named: "image2.png")
myMonogram.title = "Monogram"
myMonogram.subtitle = "This is the Monogram subtitle"
myMonogram.personNameComponents = myName
self.view.addSubview(myMonogram)
print(myMonogram.personNameComponents)
}
}
I didn't manage to scale the poster's image with scaleAspectFit, though. Also my first image was rounded with a transparency, and only choosing a frame size that perfectly fit the squared image plus the titles (so no aspect fit needed), the glowing effect became transparent on the corners. Otherwise the whole image was opaque, using its own (quite small) rounded corners.

use SnapKit make constraint to a UIView but show nothing

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)
}

How to control one IB custom view with mouseEntered/-Exited in another IB custom view

I'm sorry for my incompetence, but I'm new to Cocoa, Swift, and object-oriented programming, in general. My primary sources have been Cocoa Programming for OS X (5th ed.), and Apple's jargon- and Objective-C-riddled Developer pages. But I'm here because I haven't seen (or didn't realize that I saw) anything that speaks to this problem.
I want to change the contents of one IB-created custom view, LeftView, by mouseEntered/-Exited actions in another IB-created custom view, RightView. Both are in the same window. I created a toy program to try to figure things out, but to no avail.
Here's the class definition for RightView (which is supposed to change LeftView):
import Cocoa
class RightView: NSView {
override func drawRect(dirtyRect: NSRect) {
// Nothing here, for now.
}
override func viewDidMoveToWindow() {
window?.acceptsMouseMovedEvents = true
let options: NSTrackingAreaOptions =
[.MouseEnteredAndExited, .ActiveAlways, .InVisibleRect]
let trackingArea = NSTrackingArea(rect: NSRect(),
options: options,
owner: self,
userInfo: nil)
addTrackingArea(trackingArea)
}
override func mouseEntered(theEvent: NSEvent) {
Swift.print("Mouse entered!")
LeftView().showStuff(true)
}
override func mouseExited(theEvent: NSEvent) {
Swift.print("Mouse exited!")
LeftView().showStuff(false)
}
}
And here's the class definition for LeftView (which is supposed to be changed by RightView):
import Cocoa
class LeftView: NSView {
var value: Bool = false {
didSet {
needsDisplay = true
Swift.print("didSet happened and needsDisplay was \(needsDisplay)")
}
}
override func mouseUp(theEvent: NSEvent) {
showStuff(true)
}
override func drawRect(dirtyRect: NSRect) {
let backgroundColor = NSColor.blackColor()
backgroundColor.set()
NSBezierPath.fillRect(bounds)
Swift.print("drawRect was called when needsDisplay was \(needsDisplay)")
switch value {
case true: NSColor.greenColor().set()
case false: NSColor.redColor().set()
}
NSBezierPath.fillRect(NSRect(x: 40, y: 40,
width: bounds.width - 80, height: bounds.height - 80))
}
func showStuff(showing: Bool) {
Swift.print("Trying to show? \(showing)")
value = showing
}
}
I'm sure I'm missing something "completely obvious," but I'm a little dense. If you could tell me how to fix the code/xib files, I would very much appreciate it. If you could explain things like when talking to a child, I would be even more appreciative. When I take over the world (I'm not incompetent at everything), I will remember your kindness.
I came up with a workaround that is much simpler than my prior strategy. Instead of having mouseEntered/-Exited actions in one custom view try to control what is displayed in another custom view, I simply put the mouseEntered/-Exited code into the view that I wanted to control, and then I altered the location of rect: in NSTrackingArea.
Before moving code over by for that approach, I had tried changing the owner: in NSTrackingArea to LeftView() and just moving over the mouseEntered/-Exited code. That generated lots of scary error messages (naive newbie talking here), so I gave up on it. It would be nice to know, though, how one can correctly assign an owner other than self.
In any case, any further thoughts or insights would be appreciated.

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.

How can I make a vertical slider in swift?

I was wondering how I can create a vertical slider in swift.
I have tried using .transform and then adding a rotate but this returned an exception and rotated the whole screen. I just need a vertical slider.
I was wondering if anyone know of a way to rotate a slider in swift?
Thanks
Assuming you are talking about UISlider :
You were looking in a right direction but probably applied AffineTransformation to the wrong item... You should use UISlider.transform to change it orientation.
Here is working code (I did add UISlider using InterfaceBuilder):
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var verticalSlider: UISlider!{
didSet{
verticalSlider.transform = CGAffineTransform(rotationAngle: CGFloat(-M_PI_2))
}
}
}
Options 1:
In Swift 4:
-M_PI_2 is deprecated so Use Double.pi / 2
verticalSlider.transform = CGAffineTransform(rotationAngle: CGFloat(-Double.pi / 2))
OR
Options 2: for All Objective C and Swift
Key path = layer.transform.rotation.z
Type = String
Value = -1.570795
Most Imp Note: before and After keypath No Space
Use OOP. If you define this rotation as an Extension on UIView, then not only the UIView but also all subclasses that inherit from UIView can be rotated. This of course includes UISlider, but also UILabel, UIButton and about 200? other subclasses... see here
list of subclasses for UIView
extension UIView
{
func makeVertical()
{
transform = CGAffineTransform(rotationAngle: -CGFloat.pi / 2)
}
}
// usage example:
sldBoilerTemperature.makeVertical()
It's good to be aware of inheritance, saves a lot of work. For many Swift extensions to make, it might be a good idea trying to move it upwards in the class hierarchy, like in this example.
Swift-5 Vertical slider with constraints
func transformSlider(){
var constraints = [NSLayoutConstraint]()
ControlSlider.transform = CGAffineTransform(rotationAngle: CGFloat(-Double.pi/2))
ControlSlider.translatesAutoresizingMaskIntoConstraints = false
constraints.append(ControlSlider.widthAnchor.constraint(equalTo: self.heightAnchor, multiplier: 0.8))
constraints.append(ControlSlider.centerYAnchor.constraint(equalTo: self.centerYAnchor))
let sliderWidth = (ControlSlider.frame.height * 0.8)/2
print(sliderWidth)
constraints.append(ControlSlider.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: (20-sliderWidth)))
NSLayoutConstraint.activate(constraints)
}