Hide scrollers while leaving scrolling itself enabled in NSScrollView - objective-c

I'd like to hide the NSScrollers of NSScrollView. I'm aware of the methods setHasHorizontalScroller: and setHasVerticalScroller:. However, if I disable the scrollers, scrolling in that direction gets disabled as well. I'd like to only hide the scrollers while maintaining the possibility to scroll. Any thoughts on this?

I was able to do this by doing:
[labelsScrollView setHasHorizontalScroller:YES];
[[labelsScrollView horizontalScroller] setAlphaValue:0];

The trick of setting alphaValue to zero has issue as invisible scroller still receives touches. Here is what we did in order to solve this (Swift 4).
class InvisibleScroller: NSScroller {
override class var isCompatibleWithOverlayScrollers: Bool {
return true
}
override class func scrollerWidth(for controlSize: NSControl.ControlSize, scrollerStyle: NSScroller.Style) -> CGFloat {
return CGFloat.leastNormalMagnitude // Dimension of scroller is equal to `FLT_MIN`
}
public override init(frame frameRect: NSRect) {
super.init(frame: frameRect)
setupUI()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
setupUI()
}
private func setupUI() {
// Below assignments not really needed, but why not.
scrollerStyle = .overlay
alphaValue = 0
}
}
Usage:
private class TabBarScrollView: NSScrollView {
private func setupUI() {
borderType = .noBorder
backgroundColor = .clear
drawsBackground = false
horizontalScrollElasticity = .none
verticalScrollElasticity = .none
automaticallyAdjustsContentInsets = false
horizontalScroller = InvisibleScroller()
}
}

if collectionView.enclosingScrollView?.hasHorizontalScroller == true {
collectionView.enclosingScrollView?.horizontalScroller?.scrollerStyle = .overlay
collectionView.enclosingScrollView?.horizontalScroller?.alphaValue = 0.0
} else {
print("horizontalScroller")
}
Make sure horizontal scroller is selected:

I'm looking for an answer to this as well since setting hasVerticalScroller = false disables trackpad scrolling for me. In the meantime, my horrible hack is to use the following in my NSScrollView subclass:
self.hasVerticalScroller = true
self.scrollerInsets.right = -999999
The scroller is technically visible, it is just way off the edge of the view. :(

Have you checked the NSScrollView Class Reference ?
[scrollView setHasVerticalScroller:NO];
this method doesn't disable scrolling.
If you still do not want to use that method you can also:
[scrollView setHorizontalScroller:nil];

This is my solution from sam's answer above:
[myNSScrollView setHasVerticalScroller:YES];
[_myNSScrollView setScrollerInsets:NSEdgeInsetsMake(0, 0, 0, -99999)];
The scroller will be hidden even during the scrolling process.

Related

Autosizing Cells in UICollectionView (all in code)

Using Swift-5.0, Xcode-10.2, iOS-12.2,
There is an issue in my code while trying to achieve "autosizing" of cells in a UICollectionView (using UICollectionViewFlowLayout as its layout).
The height of the cell is content-based (and unknown upfront) - therefore I try to get the cell's height to autosize (the "width" I don't care for now and can, for example, be set to frame.width).
Even tough, I only use one large UICollectionView-Cell for the example below, I would still like to keep "dequeueing" of the cells alive since later on, there will be many more cells that need to be filled with large content. Therefore, to make this example more simple, I keept the numberOfItemsInSection at 1.
Moreover, for the below example, each custom CollectionViewCell is filled with a vertical StackView (vertically adding-up a couple of Labels and ImageViews). The StackView is not important here, but I made it as a quick example. Again, the content of the custom CollectionViewCell will change later on (especially it will change to a content-dependent height). The fixed-height cell-content in the code below is just for example reasons...
But what I would still like to get out of this, is the question on how to make the CollectionViewCell autosize its height according to the content (whether fixed-height like in the below example or dynamic content-based-height like in the future implementation) ???
I keep getting the following Constraint-error:
Unable to simultaneously satisfy constraints.
Probably at least one of the constraints in the following list is one
you don't want.
Try this:
(1) look at each constraint and try to figure out which you don't expect;
(2) find the code that added the unwanted constraint or constraints and fix it.
Everyting works, if I give the Cell a very large fixed height using the method sizeForItemAt inside my UICollectionViewController. (i.e. with "very large" I mean much bigger than the cell's height turns out when dequeueing of the cell takes place).
But as explained above, I do not want to set the cell's height to a fixed value (using the UICollectionViewController's method sizeForItemAt - but rather achieve the desired autosizing.
To autosize the cell, I tried the following:
Approach A)
Use collectionViewFlowLayout.estimatedItemSize = CGSize(...)
(and don't use sizeForItemAt method)
--> Again same thing: If the estimated-size is set large enough, no error occurs. If I set it too small, then I get the same Constraint-error...
Approach B)
Use collectionViewFlowLayout.estimatedItemSize = UICollectionViewFlowLayout.automaticSize
(and use or don't use sizeForItemAt method - does not make a difference)
--> Again same error: As soon as I start scrolling on the UICollectionView-cell, it throws the same Constraint-error...
Somewhat promising is the observation that using UICollectionViewFlowLayout.automaticSize makes the App work as desired (except that the above error is still thrown - but strange-enough, the App continues somehow to run anyway). For me it is not acceptable that the App works and an error is thrown. The question is, how to get rid of the Constraint-error ??
Here is all the code that I use:
class TestViewController: UICollectionViewController, UICollectionViewDelegateFlowLayout {
let cellId = "cellID"
override func viewDidLoad() {
super.viewDidLoad()
collectionView.backgroundColor = .yellow
collectionView.register(MyCollectionViewCell.self, forCellWithReuseIdentifier: cellId)
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 1
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as! MyCollectionViewCell
return cell
}
// func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
// return .init(width: view.frame.width, height: 4000)
// }
init() {
let collectionViewFlowLayout = UICollectionViewFlowLayout()
// collectionViewFlowLayout.estimatedItemSize = CGSize(width: UIScreen.main.bounds.width, height: 4000)
collectionViewFlowLayout.estimatedItemSize = UICollectionViewFlowLayout.automaticSize
super.init(collectionViewLayout: collectionViewFlowLayout)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
Here is the CustomCollectionViewCell:
import UIKit
class MyCollectionViewCell: UICollectionViewCell {
let titleLabel1 = UILabel(text: "Title 123", font: .boldSystemFont(ofSize: 30))
let titleLabel2 = UILabel(text: "Testing...", font: .boldSystemFont(ofSize: 15))
let imgView1 = UIImageView(image: nil)
let imgView2 = UIImageView(image: nil)
let imgView3 = UIImageView(image: nil)
let imgView4 = UIImageView(image: nil)
let imgView5 = UIImageView(image: nil)
let imageView: UIImageView = {
let imgView = UIImageView()
imgView.backgroundColor = .green
return imgView
}()
override init(frame: CGRect) {
super.init(frame: frame)
backgroundColor = .yellow
titleLabel1.constrainHeight(constant: 50)
titleLabel1.constrainWidth(constant: 250)
titleLabel2.constrainHeight(constant: 50)
titleLabel2.constrainWidth(constant: 250)
imgView1.constrainHeight(constant: 100)
imgView1.constrainWidth(constant: 200)
imgView1.backgroundColor = .green
imgView2.constrainHeight(constant: 100)
imgView2.constrainWidth(constant: 200)
imgView2.backgroundColor = .green
imgView3.constrainHeight(constant: 100)
imgView3.constrainWidth(constant: 200)
imgView3.backgroundColor = .green
imgView4.constrainHeight(constant: 100)
imgView4.constrainWidth(constant: 200)
imgView4.backgroundColor = .green
imgView5.constrainHeight(constant: 100)
imgView5.constrainWidth(constant: 200)
imgView5.backgroundColor = .green
let stackView = UIStackView(arrangedSubviews: [titleLabel1, imgView1, titleLabel2, imgView2, imgView3, imgView4, imgView5])
addSubview(stackView)
stackView.anchor(top: safeAreaLayoutGuide.topAnchor, leading: leadingAnchor, bottom: bottomAnchor, trailing: trailingAnchor)
stackView.spacing = 20
stackView.axis = .vertical
stackView.alignment = .center
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
Needed extensions are defined as such:
extension UILabel {
convenience init(text: String, font: UIFont) {
self.init(frame: .zero)
self.text = text
self.font = font
self.backgroundColor = .red
}
}
extension UIImageView {
convenience init(cornerRadius: CGFloat) {
self.init(image: nil)
self.layer.cornerRadius = cornerRadius
self.clipsToBounds = true
self.contentMode = .scaleAspectFill
}
}
To abstract away the anchoring and height-definitions of the autolayout-constraints of the cell's components (i.e. a bunch of labels and imageViews that fill the cell), I used the following UIView extension...:
(The extension has been published by Brian Voong - see video link)
// Reference Video: https://youtu.be/iqpAP7s3b-8
extension UIView {
#discardableResult
func anchor(top: NSLayoutYAxisAnchor?, leading: NSLayoutXAxisAnchor?, bottom: NSLayoutYAxisAnchor?, trailing: NSLayoutXAxisAnchor?, padding: UIEdgeInsets = .zero, size: CGSize = .zero) -> AnchoredConstraints {
translatesAutoresizingMaskIntoConstraints = false
var anchoredConstraints = AnchoredConstraints()
if let top = top {
anchoredConstraints.top = topAnchor.constraint(equalTo: top, constant: padding.top)
}
if let leading = leading {
anchoredConstraints.leading = leadingAnchor.constraint(equalTo: leading, constant: padding.left)
}
if let bottom = bottom {
anchoredConstraints.bottom = bottomAnchor.constraint(equalTo: bottom, constant: -padding.bottom)
}
if let trailing = trailing {
anchoredConstraints.trailing = trailingAnchor.constraint(equalTo: trailing, constant: -padding.right)
}
if size.width != 0 {
anchoredConstraints.width = widthAnchor.constraint(equalToConstant: size.width)
}
if size.height != 0 {
anchoredConstraints.height = heightAnchor.constraint(equalToConstant: size.height)
}
[anchoredConstraints.top, anchoredConstraints.leading, anchoredConstraints.bottom, anchoredConstraints.trailing, anchoredConstraints.width, anchoredConstraints.height].forEach{ $0?.isActive = true }
return anchoredConstraints
}
func fillSuperview(padding: UIEdgeInsets = .zero) {
translatesAutoresizingMaskIntoConstraints = false
if let superviewTopAnchor = superview?.topAnchor {
topAnchor.constraint(equalTo: superviewTopAnchor, constant: padding.top).isActive = true
}
if let superviewBottomAnchor = superview?.bottomAnchor {
bottomAnchor.constraint(equalTo: superviewBottomAnchor, constant: -padding.bottom).isActive = true
}
if let superviewLeadingAnchor = superview?.leadingAnchor {
leadingAnchor.constraint(equalTo: superviewLeadingAnchor, constant: padding.left).isActive = true
}
if let superviewTrailingAnchor = superview?.trailingAnchor {
trailingAnchor.constraint(equalTo: superviewTrailingAnchor, constant: -padding.right).isActive = true
}
}
func centerInSuperview(size: CGSize = .zero) {
translatesAutoresizingMaskIntoConstraints = false
if let superviewCenterXAnchor = superview?.centerXAnchor {
centerXAnchor.constraint(equalTo: superviewCenterXAnchor).isActive = true
}
if let superviewCenterYAnchor = superview?.centerYAnchor {
centerYAnchor.constraint(equalTo: superviewCenterYAnchor).isActive = true
}
if size.width != 0 {
widthAnchor.constraint(equalToConstant: size.width).isActive = true
}
if size.height != 0 {
heightAnchor.constraint(equalToConstant: size.height).isActive = true
}
}
func centerXInSuperview() {
translatesAutoresizingMaskIntoConstraints = false
if let superViewCenterXAnchor = superview?.centerXAnchor {
centerXAnchor.constraint(equalTo: superViewCenterXAnchor).isActive = true
}
}
func centerYInSuperview() {
translatesAutoresizingMaskIntoConstraints = false
if let centerY = superview?.centerYAnchor {
centerYAnchor.constraint(equalTo: centerY).isActive = true
}
}
func constrainWidth(constant: CGFloat) {
translatesAutoresizingMaskIntoConstraints = false
widthAnchor.constraint(equalToConstant: constant).isActive = true
}
func constrainHeight(constant: CGFloat) {
translatesAutoresizingMaskIntoConstraints = false
heightAnchor.constraint(equalToConstant: constant).isActive = true
}
}
Finally, after some more digging, I've found a solution:
Four things are important if you want to autosize your custom UICollectionViewCell:
when creating your UICollectionViewController instance, make sure you pass a FlowLayout having set the estimatedItemSize property to some educated-guess value (in my case with a height = 1 [since unknown])
let collectionViewFlowLayout = UICollectionViewFlowLayout()
collectionViewFlowLayout.estimatedItemSize = CGSize(width: UIScreen.main.bounds.width, height: 1)
let vc = TestViewController(collectionViewLayout: collectionViewFlowLayout)
.
create a property inside your custom UICollectionViewCell that keeps track of the cell's height
(i.e. inside your UICollectionViewCell class, you will always know what the cell's height is (even if dynamically changed later on). Again, I wanted to get rid of the fact that I needed to define this height already at the UICollectionViewController's sizeForItemAt method before dequeueing the cell)
Don't forget to add the preferredLayoutAttributesFitting method inside your custom UICollectionViewCell :
let myContentHeight = CGFloat(720)
// in my above code-example, the 720 are the sum of 2 x 50 (labels) plus 5 x 100 (imageViews) plus 6 x 20 (spacing)
override func preferredLayoutAttributesFitting(_ layoutAttributes: UICollectionViewLayoutAttributes) -> UICollectionViewLayoutAttributes {
setNeedsLayout()
layoutIfNeeded()
var newFrame = layoutAttributes.frame
// myContentHeight corresponds to the total height of your custom UICollectionViewCell
newFrame.size.height = ceil(myContentHeight)
layoutAttributes.frame = newFrame
return layoutAttributes
}
Of course, whenever your custom CollectionViewCell changes its height dynamically, you also need to change the myContentHeight property again...
(the calling of preferredLayoutAttributesFitting you don't need to care yourself in code, this method will be called automatically whenever the user enters the view, scrolls or does anything else. The OS takes more or less care of this...).

Sprite button and icon hover animation

I'm trying to create an effect over my custom buttons (SKSpriteNodes) and other UI objects that are also SKSpriteNode subclasses so that when the mouse hovers over them, they expand slightly to indicate that the user is hovering over them. Once the mouse leaves the vicinity of the sprite, the sprite should go back to normal size.
I initially tried this with the mouseMoved method, but undoing the scaling effect is proving to be an issue. Is there a better way to handle this maybe in the subclasses themselves? Ideas?
One way to do this is to simply keep track of the currently hovered node (if any). Something like this.
I've added a method to recursively search a nodes parents to try and find a suitable hoverable parent. SKSpriteNode in my example, but Producer in your case unless I'm mistaken.
class GameScene: SKScene {
var hoverNode: SKSpriteNode?
//Setup
override func mouseMoved(theEvent: NSEvent) {
let location = theEvent.locationInNode(self)
if let node = findHoverable(self.nodeAtPoint(location)) {
if (node == hoverNode) { return }
node.removeAllActions()
node.runAction(SKAction.scaleTo(1.2, duration: 0.5))
hoverNode = node
} else {
if let hoverNode = hoverNode {
hoverNode.removeAllActions()
hoverNode.runAction(SKAction.scaleTo(1.0, duration: 0.5))
self.hoverNode = nil
}
}
}
private func findHoverable(node: SKNode) -> SKSpriteNode? {
if let node = node as? SKSpriteNode {
return node
}
if let parent = node.parent {
if let parent = parent as? SKSpriteNode {
return parent
} else {
return findHoverable(parent)
}
} else {
return nil
}
}
}

SFSafariViewController status bar style

My app's statusbar style is UIStatusBarStyleLightContent and it's set in my rootViewController as preferredStatusBarStyle.
Now I have a problem that when opening SFSafariViewController from within my app, it has inherited statusbar style that is light and invisible on the white background of SFSafariViewController.
Is there a way to set statusbar style for SFSafariViewController?
P.S. I tried to subclass SFSafariViewController and override this method but it doesn't help.
- (UIStatusBarStyle)preferredStatusBarStyle {
return UIStatusBarStyleDefault;
}
Update:
[[UIApplication sharedApplication] setStatusBarStyle:] does the trick, but this method is deprecated in iOS 9.
You don't have to subclass SFSafariViewController at all.
Just set modalPresentationCapturesStatusBarAppearance = true on your instance of SFSafariViewController and it will handle the rest on its own.
This works because its own default preferredStatusBarStyle is, you guessed it, .default. The view hierarchy is still relying on the presenting view controller for status bar appearance, so by setting modalPresentationCapturesStatusBarAppearance to true, it will be the receiver asked for status bar appearance.
TL;DR
safariViewController.modalPresentationCapturesStatusBarAppearance = true
(This behavior is overridden, doesn't work, when UIViewControllerBasedStatusBarAppearance is set to NO in your Info.plist)
It is not the best solution, but it works.
class MySafariViewContoller: SFSafariViewController {
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(true)
UIApplication.sharedApplication().statusBarStyle = .Default
}
override func viewWillDisappear(animated: Bool) {
super.viewWillAppear(false)
UIApplication.sharedApplication().statusBarStyle = .LightContent
}
}
Change .Default and .LightContent as you prefer.
You can use extensions.
extension SFSafariViewController {
override open func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(true)
UIApplication.shared.statusBarStyle = .default
}
override open func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(true)
UIApplication.shared.statusBarStyle = .lightContent
}
}
How about that?
class MyCustomSafariViewController: SFSafariViewController {
override func preferredStatusBarStyle() -> UIStatusBarStyle {
return .LightContent
}
}
Or private API - if you can use it.

setStatusBarHidden is deprecated in iOS 9.0

I am upgrading my code from iOS 8 to iOS 9. I have a code snippet in my program
[[UIApplication applicationName] setStatusBarHidden:YES];.
I am getting the warning "setStatusBarHidden is deprecated in iOS 9.0, Use -[UIViewController prefersStatusBarHidden". If I just replace 'setStatusBarHidden' with 'prefersStatusBarHidden', I get 'instance method not found'.
Can someone please suggest me how to solve this problem?
Add below code to your view controller..
- (BOOL)prefersStatusBarHidden {
return NO;
}
Note :
If you change the return value for this method, call the
setNeedsStatusBarAppearanceUpdate method.
For childViewController, To specify that a child view controller
should control preferred status bar hidden/unhidden state, implement
the childViewControllerForStatusBarHidden method.
prefersStatusBarHidden is available from iOS 7+.
Use this in Your UIViewController class
var isHidden = true{
didSet{
self.setNeedsStatusBarAppearanceUpdate()
}
}
override var prefersStatusBarHidden: Bool {
return isHidden
}
If you change the return value for this method, call the
setNeedsStatusBarAppearanceUpdate() method. To specify that a child
view controller should control preferred status bar hidden/unhidden
state, implement the childViewControllerForStatusBarHidden method.
you have to add method in yourViewController.m
- (BOOL)prefersStatusBarHidden {
return NO;
}
Swift 3.1 Xcode 8.2.1
Change in info.plist the row View controller-based status bar appearance and set it to NO
In your target settings tick "Hide Status bar"
Both steps are required
Here is my swift code for setting status bar hidden and style.
extension UIViewController {
public var privateStatusBarHidden: Bool {
return statusBarHidden
}
public var privateStatusBarStyle: UIStatusBarStyle {
return statusBarStyle
}
public func setStatusBarHidden(hidden: Bool, animated: Bool = false) {
statusBarHidden = hidden
if animated {
UIView.animate(withDuration: 0.25, animations: {
self.setNeedsStatusBarAppearanceUpdate()
})
} else {
self.setNeedsStatusBarAppearanceUpdate()
}
}
public func setStatusBar(style: UIStatusBarStyle) {
statusBarStyle = style
self.setNeedsStatusBarAppearanceUpdate()
}
public static func swizzleStatusBarHiddenPropertyForViewController() {
var original = class_getInstanceMethod(UIViewController.self, #selector(getter: UIViewController.prefersStatusBarHidden))
var changeling = class_getInstanceMethod(UIViewController.self, #selector(getter: UIViewController.privateStatusBarHidden))
method_exchangeImplementations(original, changeling)
original = class_getInstanceMethod(UIViewController.self, #selector(getter: UIViewController.preferredStatusBarStyle))
changeling = class_getInstanceMethod(UIViewController.self, #selector(getter: UIViewController.privateStatusBarStyle))
method_exchangeImplementations(original, changeling)
original = class_getClassMethod(UIViewController.self, #selector(UIViewController.swizzleStatusBarHiddenPropertyForViewController))
changeling = class_getClassMethod(UIViewController.self, #selector(UIViewController.emptyFunction))
method_exchangeImplementations(original, changeling)
}
#objc private static func emptyFunction() {}
}
Usage
in lauching function
UIViewController.swizzleStatusBarHiddenPropertyForViewController()
for hide/show statusBar, in UIViewController
. self.setStatusBar(hidden: true/false)
Swift 3 with Xcode 8.3.3
1) Add a row in you Info.plist.
2) In your ViewController ViewDidLoad() override add:
UIApplication.shared.isStatusBarHidden = true

Swift unique property in multiple instances

I know that theoretically it's possible to create multiple instances of the same class with a property that would have a different value for each instance.
The thing is, I can't make it happen.
Each time I'm creating a new instance, it gets the property's value of the other instances, and when I'm changing one value for an instance, it changes the other's too.
So my guess is that I'm doing something wrong (obviously), like accessing the class property value instead of the instance property value... Here's the code.
class CustomUIImageView: UIImageView {
var someParameter: Bool = false // This is the property I want to be different in each version of the instance.
}
class ClassSiege: UIViewController, UIGestureRecognizerDelegate {
var myView: CustomUIImageView! //the instance declaration.
// I use this gesture recognizer to find out the value of the instance I'm tapping on.
func handleTap (sender: UITapGestureRecognizer) {
print("value of someParameter \(self.myView.someParameter)")
}
func handlePan(recognizer: UIPanGestureRecognizer) {
let iv: UIView! = recognizer.view
let translation = recognizer.translationInView(self.view)
iv.center.x += translation.x
iv.center.y += translation.y
recognizer.setTranslation(CGPointZero, inView: self.view)
var centerBoardX = BlackBoard.center.x // 'Blackboard' is a fixed image on the screen.
var centerBoardY = BlackBoard.center.y
var centerRondX = iv.center.x
var centerRondY = iv.center.y
if centerRondY - centerBoardY < 100 {
self.myView.someParameter = true // If the distance between myView and the blackboard is under 100 I want the instance's property to become true.
} else {
self.myView.someParameter = false // On the other hand, if the distance is greater than 100, I want it to be false.
}
}
// When the user pushes a button, it triggers this method that creates a new instance of myView and add it to the screen.
#IBAction func showContent(sender: AnyObject) {
// some code...
// Here I'm creating the instance of the view and I give it the gesture recognizer parameters. I don't think that relevant to the issue, so I'm not adding the code.
}
}
So clearly that's not the good way to do it, but what's wrong, and how can it be solved?
Basing my answer on your related question.
If what you want to achieve is initializing a property with a value that you provide, just add a new parameter to the initializer. If for instance you are using the initializer with a CGRect passed in, then you can implement an initializer like this:
class CustomUIImageView : UIImageView {
let someParameter : Bool
required init(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
init(frame: CGRect, someParameter: Bool) {
self.someParameter = someParameter
super.init(frame: frame)
}
}
I hope that this is what you are looking for - let me know otherwise.
I've found the solution, and if you've been facing the same issu, here's how to deal with it.
The secret is to downcast the recognizer.view to take the parameter of the subclass CustomUIImageView.
here's how :
func handleTap (sender: UITapGestureRecognizer) {
println("value of someParameter \(self.myView.someParameter)") //I use this gesture recognizer to find out the value of the instance I'm tapping on.
}
func handlePan(recognizer:UIPanGestureRecognizer) {
let iv : UIView! = recognizer.view
let translation = recognizer.translationInView(self.view)
iv.center.x += translation.x
iv.center.y += translation.y
recognizer.setTranslation(CGPointZero, inView: self.view)
var centerBoardX = BlackBoard.center.x //blackboard is a fixed image on the screen.
var centerBoardY = BlackBoard.center.y
var centerRondX = iv.center.x
var centerRondY = iv.center.y
var myParameter = recognizer.view as CustomUIImageView //<- this is the key point. Downcasting let you access the custom subclass parameters of the object that is currently moved
if centerRondY - centerBoardY < 100 {
myParameter.someParameter = true //so now I'm really changing the parameter's value inside the object rather than changing a global var like I did before.
} else {
myParameter.someParameter = false
}
}
//when user pushes a button, it triggers this func that creates a new instance of myView and add it to the screen.
#IBAction func showContent(sender: AnyObject) {
some code...
//here I'm creating the instance of the view and I give it the gesture recognizer parameters. I don't think that relevant to the issue, so I'm not adding the code.
}