Swift - Custom Setter on Property

How to create a custom getter method in Swift?

Create a backing ivar and add a custom setter:

private var _myProperty: String 
var myProperty: String {
get {
if CONDITION1 {
return CONDITION1_STRING
} else if CONDITION2 {
return CONDITION2_STRING
} else {
return _myProperty
}
}
set {
_myProperty = newValue
}
}

Property getters and setters

Setters and Getters apply to computed properties; such properties do not have storage in the instance - the value from the getter is meant to be computed from other instance properties. In your case, there is no x to be assigned.

Explicitly: "How can I do this without explicit backing ivars". You can't - you'll need something to backup the computed property. Try this:

class Point {
private var _x: Int = 0 // _x -> backingX
var x: Int {
set { _x = 2 * newValue }
get { return _x / 2 }
}
}

Specifically, in the Swift REPL:

 15> var pt = Point()
pt: Point = {
_x = 0
}
16> pt.x = 10
17> pt
$R3: Point = {
_x = 20
}
18> pt.x
$R4: Int = 10

Custom setter for tuple property (Swift)

use let to decompose a tuple

var iVal:Int?
var bVal:Bool?

var contents:(Int, Bool)? {
get {
if iVal != nil && bVal != nil {
return (iVal!, bVal!)
}
else {
return nil
}
}
set {
if newValue != nil {
let (i, b) = newValue! // decompose the tuple
iVal = i
bVal = b
}
else {
iVal = nil
bVal = nil
}
}
}

Custom setter for @property?

@property (getter=yourGetter,setter=yourSetter:) UIButton *but;

Swift Programming: getter/setter in stored property

Ok. Reading through Apples documentation on Swift I found this:

If you assign a value to a property within its own didSet observer,
the new value that you assign will replace the one that was just set.

So all you have to do is this:

var rank: Int = 0 {
didSet {
// Say 1000 is not good for you and 999 is the maximum you want to be stored there
if rank >= 1000 {
rank = 999
}
}
}

custom setter method for delegate gets called infinite times

here is your problem
self.delegate is actually a setter, that is why you have cycling.
You should use _delegate = del inside of your setter.

Can't set nil to an optional property with custom setter in Swift

What you have here is a computed property.

Swift properties can either be computed or stored. We can observe value changes in our stored properties by using didSet and willSet but here we still have a stored property.

In your case, since you have overridden set and get*, you don't have a stored property, you have a computed property. If you want a computed property to have a backing storage, you must create that independently.

So you may want something like this:

class FooClass {
private var storageProperty: String?
var accessProperty: String? {
get {
return self.storageProperty
}
set {
self.storageProperty = newValue
// or whatever logic you may like here
}
}
}

*: You can't override set without also overriding get. You can however override get without overriding set--this makes a readonly computed value.


Moreover, it's important that we implement our storage properties in this way over relying on key-value coding.

For starters, setObject(forKey:) approach doesn't even work on pure Swift types. This will only work on objects which inherit from Objective-C types. It's an inherited method from NSObject's compliance to NSKeyValueCoding protocol. Why the base object of Objective-C conforms to so many protocols is beyond me... but it does and there's nothing we can do about it.

If we have a code base in which some of our objects are inheriting from Objective-C objects (which basically any project will have, UIViewController, etc), and some of our objects are pure Swift objects (which you will tend to have when you're creating your own Swift classes from scratch), then our Swift objects will not be able to implement this same pattern. If we have some objects of both types, we'll either have to implement the pattern I show above for all of them (and then we have consistency) or we'll have to implement one pattern for some types and another for other types (Swift structs would definitely have to implement the above pattern, you can't just make them inherit from NSObject) (and then we have inconsistency, which we don't like).

But what's far worse about setObject(forKey:) is that the first argument of this method always will be of type AnyObject. There is no type safety to the method at all. Where things are stored via setObject(forKey:) is based purely on the key which we use. When we use setObject(forKey:), we take a pile of type-safety advantages that Swift gives us and we throw them out the window. If we don't care to leverage the advantages Swift gives us over Objective-C, why are we writing it in Swift at all?

We can't even make the stored property private when we use setObject(forKey:). Anyone who knows the key can call setObject(forKey:) and set that object to whatever they want. And that includes objects which are not strings. All we have to do to introduce a crash to this codebase is write a class extension or subclass which has a key collision on a different type other than what you've used (so maybe an NSData value for the same key). And even if it doesn't happen to be a different type, simply duplicating the same key for multiple properties is going to introduce bugs... and bugs that are hard to debug.

Custom setter for @property?

@property (getter=yourGetter,setter=yourSetter:) UIButton *but;


Related Topics



Leave a reply



Submit