Cannot Set Getters and Setters in Swift - swift

I have created a custom class and I want to add associated getters and setters. I have read the official documentation from Apple and notice that when setting a getter and setter, you actually create a separate variable, which seems really confusing. For instance, in the documentation linked above, getters and setters are applied to a new variable called perimeter to obtain values from another variable called sidelength. Below is my code:

Getters and setters like you are implementing them are only used for computed variables in Swift. A variable with a getter and setter doesn't actually store anything, but does something when assigned or used for its value with other variables. When appropriate to use, the usage would be more like this.
var _key: String?
var key: String? {
get {
return _key
}
set {
_key = newValue
}
}
You would rarely if ever use this on an identical data type though. I use these for communication with CoreData often, and setting things like dates as a string or back to a date. Occasionally I might use it to handle the change in an optional to a non optional.
Getters and setters are not needed in order to use the variable in Swift though. If you are used to languages with them, I can understand the confusion here, but forget the correlation and start over with how you think about it. I am sure after a short amount of time, you will like the way Swift works with its datatypes!
Edit:
In order to do what you want, all you need is this:
class PollCell: UICollectionViewCell {
var key: String?
}
Now you can assign any value you want to cell.key and retrieve any value you want from cell.key.

Related

How do we create custom getters and setters, and what’s the advantage of doing so in Flutter?

What is the reason of using custom getters and setters in an application.
That's fairly very simple
First let me show you a sample of how getters and setters in Dart look like, which is essentially the language behind Flutter
class Foo {
// Creating a field/instance variable
String _fooName; //Keeping it private always
// Using the getter
String get foo_name {
//We can do something else here, like saving the variable somewhere and then returning it to the caller function
return _fooName;// private variable return for use in outside class
}
// Using the setter method
set foo_name (String name) {
// We can do something else, like update another variable based on fooName
this._fooName = name;//private variable being assigned new value
}
}
From the name, setters are involved in setting the values to an instance variable in an object oriented programming paradigm whereas getters are involved in getting the value of an instance variable
Now you would ask why not return the instance variable directly and why having such a roundabout approach to setting and getting the value
Well the answer is while getting as well as setting, we might want to do some other operation too other than just setting or getting the value and it's always better not to give admin access to the variables and that's why they are private so as to promote consistency within the objects accessing the field
It's a matter of preference, but you really shouldn't needlessly create one for a single field
https://dart.dev/guides/language/effective-dart/usage#dont-wrap-a-field-in-a-getter-and-setter-unnecessarily
One use case for creating a setter would be to perform some type of validation
For a getter, it'd be useful for a calculated field based on other properties, rather than a single property alone

How to create multiple setters

I have a variable which I want to give the option to call the setter with multiple types, but I would set the variable with one type of course. For example, if I have a variable called list, I want to be able to call the setter using a single list item i.e. a string and then in the setter method I would add the string to the end of the list. Another way to set the variable would be through an actual list, and the setter, I would just set the list to the list passed in.
Here's an example of what I would like to do, but the second time I call the list setter method, I get an error saying The name 'list' is already defined:
List<String> _list = [];
List<String> get list => list;
set list(List<String> newList) {
_list = newList;
}
set list(String newListItem) {
_list = [..._list, newListItem];
}
As Remi mentioned, it is not possible to do so. I would argue that it would be best not to do so because it changes the expectation of the contract of the setter. That is, you expect a setter to replace the value of a variable. Having a setter that appends to it is counter-intuitive and will lead to confusion for other developers.
Generally, for the maintainability of a code base, it's better to have an explicit interface to your class's behavior than to provide terse shortcuts.
That is not possible.
In Dart you can have only one setter per variable.
You will need to rename one of your setters to use a different name.

Swift 4 statically get value of model property name

When using Swift 3, I was defining my model like so
class Model: NSObject {
var prop1: String
}
When I wanted to access the static string value of the property name prop1, I would use let sad = #keyPath(Model.prop1) and it would give me "prop1" printed out. Happy days.
The problem is, that since upgrading to Swift 4, I am having trouble doing the above. I see in other posts that we can use the new \Model.prop1 syntax but that seems to be providing the value of property rather than the string representation of the name.
I am also refactoring out the need for NSObject on my Swift models, but I would have thought I can still get this functionality.
Any help here would be appreciated!
Swift properties do not necessarily retain the strings of the property names at runtime. Therefore, if the Swift key path syntax were able to give you this string value, it would only be able to be used on NSObject-derived classes. The Swift key path syntax doesn't only work with those, though; it can also be used to refer to properties of non-#objc classes and structs. Therefore, this is not possible. The #keyPath syntax remains available, however, to get the string key path of an Objective-C property.

Different ways of making read public write private variables in swift?

I've completed a online course that taught us to write properties of classes as:
class bar {
private var _foo:Int
var foo {
return _foo
}
}
Since then i've seen
class bar {
private (set) var foo:Int
}
Is there any difference between these two ways of writing things, and which would be best practise?
The second option is simpler and clearer and it has the added benefit of still being able to add get, set, willSet, and didSet blocks on the property while still having clearly defined scope on the getter and setter. Of course you can still add those to the private property but I think the code starts to get less readable.
Also note that the first option is a public read-only computed property making use of a private stored property.
The second option can be either a computed or stored property.

Swift Instance Variable Underscore Prefix?

Did Swift drop the underscore-prefix convention for instance variables, e.g., _window? If so, why?
Apple still uses _ in its Xcode boilerplate code as a convention for a non-public variable. You'll see a pattern like such:
class Foo {
var _bar : Bar? = nil
var bar : Bar {
if _bar == nil {
/* compute some stuff */
_bar = Bar (/* ... */)
}
return _bar!
}
}
where access to the property is meant to be through the bar computed property. You find this in Apple CoreData templates.
In Objective-C when you declare a property #synthesize would create the getter and setters for you automatically since clang 3.2. So, the default #synthesize for a property "foo" would look like this:
#synthesize foo = _foo
because of that _foo would then be the iVar. In other words you could have done the #synthesize yourself and called the iVar whatever you liked:
#synthesize foo = myiVarFoo
so in this case there is no "_"
So now in Swift from the documentation:
Swift unifies these concepts into a single property declaration. A Swift property does not have a corresponding instance variable, and the backing store for a property is not accessed directly.
So from the documentation it's clear that swift does not have a corresponding instance variable thus no need to have the "_" around anymore.
The underscore prefix was meant not to confuse the instance variable _foo with its getter foo.
In swift there's not such distinction between ivars and getters. Instead you only have properties, making the _ convention non necessary.
The answer is no because there are no "instance variables" right now in Swift. Only properties (stored properties and computed properties).
I'd say this _underscoreName convention is dropped (although some Apple templates still have it).
Swift's "Lazy Stored Properties" make _these unnecessary. This post:
http://mikebuss.com/2014/06/22/lazy-initialization-swift/
explains it well.
I use a leading underscore to denote a private symbol.
Yes, the underscores do hamper readability at first, but there is a valuable payoff in comprehension and maintainability.
e.g.:
final class SomeClass
{
fileprivate let _kMagicNumber: CGFloat = 3.14
fileprivate struct _PrivateInfo
{
let foo: Int
let bar: String
}
fileprivate var _privateInfo: _PrivateInfo
fileprivate func _setup(with info: _PrivateInfo) { ... }
}
etc.
At a glance, you can see which elements belong where.
You don't need to option-click or do the "who does this belong to?" dance.
Code comprehension shouldn't rely on an IDE's features. And there are times (GitHub, raw text files) where an IDE isn't available.
I understand the "it's not convention" argument. But conventions aren't written on stone tablets. Swift is rapidly evolving, as is our usage of it.
If the Swift team were to produce an annotation syntax for private symbols tomorrow, I'd use it. But until then...
Since I've got my soapbox out, please prefix your extensions.
Consider this snippet:
let color = "#ff7733".hexColor
Where does the "hexColor" come from? Your own code? The Swift standard library? Foundation? UKit? (Hah!) A CocoaPod? Who knows?
(Seasoned CocoaPods users will know that every second open-source library implements a "hexColor" property. With all the problems that entails.)
So, given a company or project name like "Double Secret Probation", consider using:
let color = "#ff7733".dsp_hexColor
Finally, I strongly recommend the books "Writing Solid Code" and "Code Complete".
The convention of a prefixing private vars long preceeded that of ObjCs (weird) property synthesis concept. Clarity was the original reason for such a prefix, not differentiation though it was useful and common to expose a public getter without the underscore...for obvious reasons. IMO, ObjC prop synthesis just put a big fat monkey wrench in the works confusing the h*** out of everyone...
What if you wanted a private synthesized property? In order to underscore-prefix your private synthesized property, you'd need a double underscore backing var. Apple specifically warned against double underscores and this created confusion. Should we bother to use synth'ed properties internally or stick with the backing var (which still had an underscore and was clearly private)? Should we just stop differentiating between private and public vars? Why??
In practice people would use the synthesized version internal to a class as a kind of smart setter, if and only if they wanted the smarts – but that broke down the ideal of encapsulation – choosing whether to use the synth'ed setter required apriori knowledge of what happened behind the scenes.
Meanwhile, as pointed out above, apple's internal code still used the convention, sometimes for synthesized properties too IIRC. And they still do for swift properties! But not consistently...The biggest evidence your language design policy is confusing is when your own devs aren't using it consistently!
Clarity was the original motive and it worked well. I say:
BRING BACK THE UNDERSCORE!
...for private vars and methods :)
(P.S. Dart even has this as an actual language convention in lieu of a private keyword!)