assigning willSet block to iOS isResting property - ios

I would like to set a willSet statement to isResting property. Whenever isResting is changed some function is called. This is what I mean:
starNode.physicsBody?.isResting: Bool = false{
willSet{
if newValue == true{
print("GOOGOO")
}else{
print("STOP")
}
}
}
This is not working. Can you assign a willSet or didSet to an already defined iOS property? If not, how do I get similar effect?
This is the documentation:
https://developer.apple.com/library/mac/documentation/SceneKit/Reference/SceneKit_Framework/index.html#//apple_ref/doc/uid/TP40012283
https://developer.apple.com/library/prerelease/ios/documentation/SceneKit/Reference/SCNPhysicsBody_Class/index.html#//apple_ref/occ/instp/SCNPhysicsBody/isResting

If not read-only:
One option would be to subclass the library object and override the property you'd like to set. Then, you can implement willSet within your subclass:
class Object {
var property: Float = 0.0
}
class ChildObject: Object {
override var property: Float {
willSet {
print("Set in child class")
}
}
}
This is the way that Apple recommends in the documentation (see "Overriding Property Observers"):
You can use property overriding to add property observers to an
inherited property. This enables you to be notified when the value of
an inherited property changes, regardless of how that property was
originally implemented.
If read-only:
You might be able to use Key-Value Observing, if the object inherits from NSObject, or if it has been marked dynamic in Swift.

Is this property an IBInspectable property?
In Objetive-C this is automatically if this is a property trough getter and setter, but in Swift it isn't. You can make this property as private and create methods for set this property and inside this method, add a call for another method.
func setResting(resting:Bool) {
self.isResting = resting
//call another method here
}

Related

Are the outlets set when self.isViewLoaded returns true?

I have a property that I want to use a property observer on. This property is set using segues. I want to avoid the property observer being triggered when the outlets are not set yet. I noticed self having a property named isViewLoaded. When this property returns true does this also necessarily imply the outlets were set? This is true for viewDidLoad() but is it also true for the property isViewLoaded?
var property: Property? {
didSet {
if self.isViewLoaded {updateUI()}
}
}

Enabling two-way communication between two classes

So I have a custom view touchableView inside a ViewController.
touchableView informs ViewController of changes in its properties through a delegate protocol (ViewController being the delegate).
What is the best method to change properties of touchableView from ViewController (so the other way around)?
Is there a way to create a two-way delegate relationship between two classes?
Simply:
Assuming that you are already have touchableView instance in the ViewController, you should be able to set -or get-/call its properties and methods.
For instance, assume that you have the following method in touchableView class:
class func fromNib() -> TouchableView {
return Bundle.main.loadNibNamed(String(describing: self), owner: nil, options: nil)![0] as! TouchableView
}
You should simply be able to:
let touchableView = TouchableView.fromNib()
thus:
// for example
touchableView.myProperty = "Hello"
I assumed that TouchableView has a string property called myProperty...
Remark:
For some reason, I suggest to implement some of property observers in TouchableView:
Property observers observe and respond to changes in a property’s
value. Property observers are called every time a property’s value is
set, even if the new value is the same as the property’s current
value.
They might be -somehow- useful to be implemented in your custom class. For clarity, let's consider -for instance- that if editing the value of myProperty should be effecting the background color of the view, it might be implemented as:
var myProperty: String = "Initial Value" {
willSet {
print("About to set value to: \(newValue)")
}
didSet {
backgroundColor = UIColor.red
}
}
Further Reading:
If you are looking for an advanced approach for two way bindings (Implementing MVVM), you might want to check this article.
I would also suggest to take a look at some frameworks that will be so helpful for such an approach, such as RxSwift, for a more simple framework, you might want to check ReactiveKit/Bond.

Swift: property observers for computed properties

As far as I know, Swift allows us to set property observers for either stored and computed properties. But if computed property value depends on some backing store, property observers are not fired when these backing store values are changed:
public class BaseClass {
private var privateVar1: Int = 0
private var privateVar2: Int = 0
public var property: Int {
get {
return privateVar1 * privateVar2
}
set {
print("some setter without effect")
}
}
private func changeSomeValues() {
privateVar1 = 1
privateVar2 = 2
}
}
public class SubClass : BaseClass {
override var property: Int {
didSet {
print("didSet \(property)")
}
}
}
didSet of SubClass isn't called when changeSomeValues is called.
Let's consider a case: we have such BaseClass in a third-party framework. We define SubClass in our app. The question is: how can we rely on SubClass observers without knowledge about property nature: is it stored (and we can rely on observers) or computed (and then we can't expect firing observers each time when we expect it)? Is it possible? If no, is it an incapsulation violation?
That behaviour is perfectly normal. There is no way for the compiler to know which backing store really corresponds to which computed property. Your backing store in this case is made up of private variables that will not be accessible outside the class itself. So the only place where an "under the hood" change can occur is in the base class. It is that class's prerogative to use its calculated properties (which will trigger the observers) or the backstore (which will not).
In your example, assuming you never want to allow "invisible" changes, the changeSomeValues() function is breaking its own rules and not respecting the contract it promised to its subclasses and callers.

How can I use willSet in a UIViewController property

I'm trying to play a little bit with swift and iOS 8.
The question is, I'm trying to create this setter in a view controller:
- (void)setViewController:(UIViewController *)viewController
{
_viewController = viewController;
method do something
}
This code below is in Objective-C so I'd like to create it in swift.
I think, I should use willSet, but I know how do it if it's defined when you have your own variable, how can I define that willSet method if that property is a ViewController property.
Thanks
Something like this:
var viewController: UIViewController? {
willSet {
//method to do something
}
}
You can actually access what viewController will be set to with the variable "newValue" if you need that in the method call.
Note: I made the property optional here just to get rid of compiler warnings about needing initialization
An alternate way different from #Eric's answer is by using a computed property, which mimics objective-c properties more closely, consisting on defining a pseudo-private data member and a computed property implementing a getter and a setter:
class MyClass {
var _viewController: UIViewController?
var viewController : UIViewController? {
get {
return self._viewController
}
set {
self._viewController = newValue
// Do something else
}
}
}
I defined the property pseudo-private because swift doesn't have access modifiers (yet), so everything is public - but when I see an underscore prefixing a variable or property name, that to me means private (It's a convention I use it a lot in javascript for instance).

Swift: 'var' declaration without getter/setter method not allowed here

I've tried to declare IBOutlet property on extension of class. But it give error as
'var' declaration without getter/setter method not allowed here
class ExampleView : UIView
{
}
extension ExampleView
{
#IBOutlet var btn1, btn2 : UIButton // here I got error.
}
Please any one suggest me correct way to do it?
From Extensions -> Computed Properties in The Swift Programming Language
NOTE
Extensions can add new computed properties, but they cannot add stored
properties, or add property observers to existing properties.
Addition in response to twlkyao's comment: Here is my implementation of the absoluteValue property of a Double
extension Double {
var absoluteValue: Double {
if self >= 0 {
return self
} else {
return -self
}
}
}
// Simple test -> BOTH println() should get called.
var a = -10.0
if (a < 0) {
println("Smaller than Zero")
}
if (a.absoluteValue > 5) {
println("Absolute is > 5")
}
From The Swift Programming Language:
Extensions in Swift can:
Add computed properties and computed static properties
Define instance methods and type methods
Provide new initializers
Define subscripts
Define and use new nested types
Which means you can't add IBOutlets and other stored properties.
If you really want to cheat, you can create global vars or a bookkeeping object which would allow you to query these vars or the object in order to add those properties (and have them be computed properties).
But it seems like it would go against the best practices. I would only do it if there's absolutely no other way.

Resources