I want to set a string variable and want to keep it always lowercase.
This is my code :
var alwaysLowercaseString : String? {
didSet{
alwaysLowercaseString = alwaysLowerCaseString!.lowercaseString
}
}
But when I use it, it goes into a infinite loop. How can I solve this problem?
I stand corrected, this is the correct approach. LeoDabus deserves the credit for this answer:
var alwaysLowercaseString : String? {
didSet{
alwaysLowercaseString = alwaysLowercaseString?.lowercaseString
print(alwaysLowercaseString)
}
}
var alwaysLowercaseString : String? {
didSet{
if alwaysLowercaseString != alwaysLowerCaseString!.lowercaseString {
alwaysLowercaseString = alwaysLowerCaseString!.lowercaseString
}
}
}
This checks so if the lowercase string is already lowercase it won't change the value of alwaysLowercaseString again so you won't call didSet infinitely. It will break after alwaysLowercaseString is set to lowercase.
Since Swift 5.1 there's a possibility to use property wrappers. Roughly speaking, this mechanics allows us to modify the value each time it is set
#propertyWrapper struct Lowercased {
var wrappedValue: String {
didSet { wrappedValue = wrappedValue.lowercased() } // here the magic happens
}
init(wrappedValue: String) {
self.wrappedValue = wrappedValue.lowercased() // we have to do it manually here because in init property observers are not triggered
}
}
final class Test {
#Lowercased var cantMakeMeUpperCase = ""
}
let test = Test()
test.cantMakeMeUpperCase = "CAN I?"
print(test.cantMakeMeUpperCase) // prints "can i?"
Related
Is it possible to initialize a swift struct without any values?
To summarize the idea, I'm creating a struct with two attributes, those attributes were filled when I called the init() method, as it should, but the problem is, I have a function inside this struct and I need to use it, in some cases, without filling the fields in the struct initializer.
I've tried adding the init(){} function, hoping that somehow it would work like the empty constructors in java, but I've got no success.
struct Quiz {
var pergunta: String
var resposta: Bool
init(pergunta: String, resposta: Bool) {
self.pergunta = pergunta
self.resposta = resposta
}
//Something like that
init(){}
func popularQuiz() -> Array<Quiz> {
...
}
}
Is there a way to do it or swift doesn't have the option to create a empty structure?
The big question is why do you want to have an empty Quiz? What does an empty Quiz mean?
Those questions aside, you can only create an initializer with no parameters if all of the properties can be given default values or if the properties are optional.
struct Quiz {
var pergunta: String = ""
var resposta: Bool = false
init(pergunta: String, resposta: Bool) {
self.pergunta = pergunta
self.resposta = resposta
}
init(){}
}
Now your empty init will work because all properties are fully initialized. But is that what you really want?
Another way to get the same result is to use default values on the parameters of the main initializer.
struct Quiz {
var pergunta: String
var resposta: Bool
init(pergunta: String = "", resposta: Bool = false) {
self.pergunta = pergunta
self.resposta = resposta
}
}
Now you can call:
Quiz()
Quiz(pergunta: "Some question", resposta: "Some Answer")
Quiz(pergunta: "Question with no answer")
Any of these still result in all properties being initialized.
The last option would be to make the properties optional instead of using special default values. But this adds more headache later.
struct Quiz {
var pergunta: String?
var resposta: Bool?
init(pergunta: String, resposta: Bool) {
self.pergunta = pergunta
self.resposta = resposta
}
init(){}
}
The empty init will leave the properties as nil. But now you need to properly handle the optional values everywhere. Again, is that what you really want?
I want that whenever there is any string type variable, trimmingCharacters function show run on it, and also if it's changed.
I have written String extension but still, I need to call it manually.
extension String
{
func trim() -> String
{
return self.trimmingCharacters(in: .whitespacesAndNewlines)
}
}
I want when I do var x=" hello". x should automatically be hello or when change x = "jello ", it should still return jello only.
You cannot achieve that on the built-in String type, but you can create your own TrimmedString type with a single String property and make sure that you trim the property during initialisation and in the property observer as well.
extension String {
func trimmed() -> String {
return self.trimmingCharacters(in: .whitespacesAndNewlines)
}
}
struct TrimmedString {
var value: String {
didSet {
value = value.trimmed()
}
}
init(string: String) {
value = string.trimmed()
}
}
If you want to trim UITextField.text, you'll need to extend UITextField with a computed property.
extension UITextField {
var trimmedText: String? {
return text?.trimmed()
}
}
Then whenever you would be calling textField.text, call textField.trimmedText instead.
I would like to add an additional property to the Swift String. I used this approach few times on objects, but it seems that it does not work on struct. Although, I don't get any error...
This is what I tried:
var str = "Hello, StackOverflow"
fileprivate struct AssociatedKeys {
static var myBool = "myBool"
}
extension String {
public var myBool: Bool {
get {
guard let myBoolObject = objc_getAssociatedObject(self, &AssociatedKeys.myBool) as? NSNumber else {
return false
}
return myBoolObject.boolValue // execution never reaches this line
}
set(value) {
let object = NSNumber(value: value)
objc_setAssociatedObject(self, &AssociatedKeys.myBool, object, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
}
}
str.myBool = true
print(str.myBool) // prints "false"
It prints out that it is false.
At first, I tried it without wrapping the Bool into NSNumber, but the result was the same.
Is this even possible to add an associated object to a struct at all? If not, can anyone tell me why?
Based on #Hamish's comment, I created the following solution to workaround the issue.
Preconditions:
Have a framework which proposes prefilled objects, the app works on these objects and the framework should know which of the properties are modified during the processing of this object later.
Not using looooong initializers to setup all properties of MyObject is a design decision.
In my example, the usage of the myObject is a dummy and shows what happens in the framework and what happens in the app.
// protocol is used, as we could handle more modifiable structs/classes in a common way
protocol PropertyState {
var isModified: Bool {get set}
}
internal struct ModifiableString : PropertyState {
var string: String
var isModified: Bool
}
class MyObject: PropertyState {
internal var _name = ModifiableString(string: "", isModified: false)
public var name: String {
get {
return _name.string
}
set(value) {
_name.string = value
_name.isModified = true
}
}
// + N similar properties (they can be other types than String, by implementing other structs, like ModifiableBool)
var isModified: Bool {
get {
return _name.isModified // || _myAnotherProperty.isModified
}
set(value) {
_name.isModified = value
// _myAnotherProperty.isModified = value
}
}
}
// internal filling of the object inside of the framework
let myObject = MyObject()
myObject.name = "originalValue"
print(myObject.isModified) // true
// filling the object with values ended, so we can set the state
myObject.isModified = false
print(myObject.isModified) // false
// the app can work with the object
// let myObject = Framework.getObject()
myObject.name = "modifiedValue"
// now the framework should now which properties are modified
print(myObject._name.isModified) // true
I'd like to implement such property, that it's value is available for reading only one time, and then the property should be set to nil.
I've implemented it in such way:
private var _readOnce: String?
var readOnce: String? {
get {
let value = _readOnce
_readOnce = nil
return value
}
set {
_readOnce = newValue
}
}
readOnce = "Andrej"
print("read once = \(readOnce)") // prints read once = Optional("Andrej")\n"
print("read once = \(readOnce)") // prints read once = nil\n"
But I'feel like using a separate property _readOnce is not the "swifty" / "most elegant" way to do it.
Does anyone know of a different way, that wouldn't require to use a separate property?
I can confirm that the above code works, it's only that I feel it could be more elegant with less lines to achieve the same behaviour.
I don't know that there's a way to avoid having a backing property, but what I'd probably do is to make a helper type to wrap up the behavior. Something like this:
struct OneTimeValue<T>
{
private var isUnread = true
private let value : T
init(_ value: T)
{
self.value = value
}
func get() -> T?
{
guard isUnread else {
return nil
}
self.isUnread = false
return self.value
}
}
You could also write this a little differently if you prefer, by nilling out value inside of get(), for example, but the general plan holds.
Then your class becomes:
class Miser
{
var readOnce : String?
{
return self._readOnce.get()
}
private let _readOnce = OneTimeValue("Can't touch this (twice)")
}
I've also used this pattern for a UserDefaultsValue (storage to/from user defaults) and a SynchronizedValue (read-write lock on a property) and I think it works well.
As far as I know it is not possible without a second variable. This is because computed properties do not store any data for the variable they represent:
In addition to stored properties, classes, structures, and
enumerations can define computed properties, which do not actually
store a value.
For non-computed properties, the only observers you can have are based upon the setting of the variable, not the getting (i.e. willSet and didSet)
Hope that helps!
EDIT:
It can be done with closures and property observers if you're careful:
This requires no other variables (instead the value is captured by the closure), but it is rather unclear — I wouldn't recommend it.
var readOnce: () -> String? = {nil} {
didSet{
readOnce = { [weak self, readOnce] in
self?.readOnce = {nil}
return readOnce()
}
}
}
readOnce() // returns nil
readOnce = {"Hi"}
readOnce() // returns optional wrapped "Hi"
readOnce() // returns nil
A more 'Swifty' answer for you :D
After Swift 5.1, We can use Property Wrapper
#propertyWrapper
struct ReturnAndFree<T> {
private var value: T?
init(wrappedValue: T?) {
value = wrappedValue
}
var wrappedValue: T? {
mutating get {
defer { value = nil }
return value
}
set {
value = newValue
}
}
}
I'm new here and I'm doing some exercise in Swift and I found this problem:
When I try to execute this code I get a Segmentation Fault and I can't figure out why.
class Persona{
private var nome:String?
private var cognome:String?
private var eta:Int?
public var Sesso:String{
get{
return Sesso
}
set{
if newValue=="M" || newValue == "m" {
Sesso="Maschio"
}
else{
Sesso="Femmina"
}
}
}
init(nome:String, cognome:String, eta:Int)
{
self.nome=nome
self.cognome=cognome
self.eta=eta
}
init(){}
func getNome()->String{ return nome! }
func getCognome()->String{ return cognome! }
func getEta()->Int{ return eta! }
func setNome(nome:String)->(){ self.nome=nome }
func setCognome(cognome:String)->(){ self.cognome=cognome }
func setEta(eta:Int)->(){ self.eta=eta }
}
var p1 = Persona(nome:"AAAA",cognome:"BBBB",eta:22)
p1.Sesso = "M"
p1.setEta(eta:44)
print("\(p1.getNome()) \t \(p1.getCognome()) \t \(p1.getEta()) \t \(p1.Sesso)")
p1.setEta(eta:22)
You are basically trying to use a computed property
In addition to stored properties, classes, structures, and enumerations can define computed properties, which do not actually store a value. Instead, they provide a getter and an optional setter to retrieve and set other properties and values indirectly.
The key here is "which do not actually store a value". That can be seen clearer when you try to use the getter since print(p1.Sesso) causes a crash as well since you end up in an infinite loop of the getter calling itself over and over again. What you should do is define the computed property but at the same time define another stored property which actually holds the data:
private var _sesso:String = ""
public var Sesso:String{
get{
return _sesso
}
set{
if newValue=="M" || newValue == "m" {
_sesso="Maschio"
}
else{
_sesso="Femmina"
}
}
}
The Problem is you can't access a variable in its own getter and setter.
Instead you can use didSet
public var Sesso : String{
didSet {
if Sesso == "M" || Sesso == "m" {
Sesso = "Maschio"
}
else{
Sesso = "Femmina"
}
}
}
and you can know more about getters and setters from this answer and can also check apple documentation on Properties for more clarification.