Value type of string? Has no member components. (Struct) [closed] - swift

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 5 years ago.
Improve this question
I look at each thread but can't find any solution for my case.
I have a model:
import Foundation
public struct Destinos: Data {
public var idDestino : Int?
public var desDestino : String?
public func dictionary() -> NSDictionary {
let dictionary = NSMutableDictionary()
dictionary.setValue(self.idDestino, forKey: "idDestino")
dictionary.setValue(self.desDestino, forKey: "desDestino")
return dictionary
}
}
So I want to change the desDestino "string" to [String] to use later and show in at tableView. For this.I write this line of code in another file.swift:
var cadena = Destinos()
cadena.desDestino = "HOLA, nada, algo, otra, cosa, mas que eso"
let array = cadena.desDestino.components(separatedBy: ", ") // in this line i get the error: value type of string? has no member components.
so... what is the problem?

There's no reason to use NSDictionary here. Just use a native Swift dictionary (with a literal).
public struct Destinos {
public let idDestino : Int?
public let desDestino : String?
public func toDictionary() -> [String: Any?] {
return [
"idDestino": idDestino,
"desDestino": desDestino
]
}
}
As for generating your array, you have two issues:
1. components(seperatedBy:) is misspelt
2. cadena.desDestino is an is a String? (Also known as a Optional<String>) which hasn't been unwrapped. The nicest way to take care of this is to use optional chaining, and then use nil coalescence (??) to make it an empty array in the case cadena.desDestino is nil.
var cadena = Destinos(
idDestino: 123,
desDestino: "HOLA, nada, algo, otra, cosa, mas que eso"
)
let array = cadena.desDestino?.components(separatedBy: ", ") ?? []

Related

Providing a default binding to String of an enum with rawValue type of String [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 days ago.
Improve this question
enum Tab : String {
case front, back
}
I would like to extend any enum that has raw value type of String to have an easily accessible bindingToString. Is there a way? Probably a protocol would have to be declared on any enum with String raw value type, but I have no idea how to do that. I'm looking for something like this:
enum Tab : String, BindableToString {
case front, back
}
var tab : Tab = .front
TextField(tab.bindingToString, ...)
However, we can create a Binding<Tab> extension to create a conversion to/from String:
extension Binding where Value == Tab {
var bindingToString : Binding<String> {
.init(get: { self.wrappedValue.rawValue }, set: { v in
if let newValue = Tab.init(rawValue: v) {
self.wrappedValue = newValue
}
})
}
}
This is almost fine, but first we need to explicitly create binding to Tab and then a binding to String, and we need to define this on every enum out there.
I was hoping we could somehow generalize this further so that we don't need to define explicitly a bindingToString on every such enum that has a raw value type of String; a protocol or a generic extension would do.
A solution utilizing the RawRepresentable idea from #loremipsum based on the proxy() func:
extension Binding where Value : RawRepresentable<String> {
var bindingToString : Binding<String> {
.init {
self.wrappedValue.rawValue
} set: { value in
if let newValue = Value(rawValue: value){
self.wrappedValue = newValue
}
}
}
}

Am I able to add a member-wise initializer to a Codable-conforming object? [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
I currently have a class that conforms to Codable and has an initializer like so
public class A: Codable {
var aString: String?
public init(input: String?) {
self.aString = input
}
}
When I try to create an instance of it, I get an error
let myA = A(input: "Goodbye world")
Incorrect argument label in call (have 'input:', expected 'from:')
Am I restricted to only the init(from decoder: Decoder) throws initializer for Codable classes?
Your code is correct, double check whether you actually have a public initializer not a private one.
I put this into my Xcode Playground and everything works as expected:
public class A: Codable {
var aString: String?
public init(input: String?) {
self.aString = input
}
}
let a = A(input: "123")

Swift - Merging 2 arrays of objects with a key [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
I'm new to Swift programming and been working on an app fir a couple of weeks now, and I'm stuck at a crucial moment in the development.
I'm fetching data from a URL that returns a JSON. It is decoded and the data o is stored in an array.
I do the same thing with another URL.
Now I'm trying to initialize my final object wich will be a combination of 2 objects contained in each of the arrays.
Each array is a dictionary and each objects has a property call id.
I can't figure how I can go through each arrays to check for the id of each objects to match and then initialize a new object by combining the data from each object (look at the code below, it will make more sense hopefully)
I tried a for ... in but I couldn't access the id property and compare it. I tried to do a for ... in inside a for ... in to compare the id value: no success too.
On top of this, the initialization is also a challenge. I tried to implement something like this:
self.mergedList = (//result of the loops).map(MergedViewModel.init)
Here an example of the 2 objects
class MergeInformationViewModel {
var id = "1234"
var information = "This Is My Name"
}
class MergeDataViewModel {
var id = "1234"
var data = "Some very important data"
}
The object I'm trying to initialize
class MergedViewModel {
let mergedViewData: MergeDataViewModel
let mergedViewInformation: MergeInformationViewModel
init(data: MergeDataViewModel, information: MergeInformationViewModel) {
self.mergedViewData = data
self.mergedViewInformation = information
}
var id: String {
return self.mergedViewData.id
}
var information: String {
return self.mergedViewInformation.information
}
var data: String {
return self.mergedViewData.data
}
}
Finally the class handling the initialization. I'm working on a SwiftUI project
class MergedListViewModel: ObservableObject {
init() { mergingAndInit() }
#Published var mergedList = [MergedViewModel]()
var mergeInformationList = [MergeInformationViewModel]()
var mergeDataList = [MergeDataViewModel]()
func mergingAndInit() {
//...
}
}
the final result would look something like this
class MergedViewModel {
var id = "1234"
var information = "This Is My Name"
var data = "Some very important data"
}
How can I implement the func mergingAndInit() into my code?
Thanks in advance.
I figure it out!
for mergedI in mergeInformationList {
for mergedD in mergeDataList {
if mergedI.id == mergedD.id {
self.mergedList.append(MergedViewModel(data: mergedD, information: mergedI))
}
}
}

Get a Swift class's property name as a String [duplicate]

This question already has answers here:
Get a Swift Variable's Actual Name as String
(7 answers)
Closed 5 years ago.
How do I get the property name as a string?
class Person {
var firstName: String
var lastName: String
var downloading: Bool
func excludePropertiesFromCloud() -> [String] {
return //here I want to return ["downloading"]
}
}
I would like to avoid having to type return ["downloading"] to prevent errors if the name of the variable changes later on.
To get the class name you can use String(describing: Person.self), so I am looking at something similar for properties.
Note:
Although the title of the question is very similar to Get a Swift Variable's Actual Name as String, it is clear that the accepted answer in the original question returns the value of the property and does not answer this straightforward question. The original question is the first to come up on any google search with "Swift get property name", and the answer answers something else, as pointed to by #MarqueIV. This is why I created this question
If you are ok with making your properties #objc you can get the property name like so:
class Person {
#objc var firstName: String
var lastName: String
var downloading: Bool
func excludePropertiesFromCloud() -> [String] {
return [#keyPath(firstName)]
}
}

Type *My Custom Class* has no subscript members

This is a question I was just about to post my finished answer to, but it seems that the author just at that moment deleted the question, possibly as the only reply was a comment saying it was not possible. I myself found the technical aspect of the question somewhat interesting, so I'm adding the same question and the answer here, in case someone else finds this of interest.
Feel free to edit this post/topic as well as its answer. Also, I've looked in the meta for guidelines regarding re-posting a deleted question in this fashion, however without finding any explicit non-advice for doing so. Please let me know if I'm in the wrong here.
(Original question from SO user Jaime)
Type My Custom Class has no subscript members
I'm trying to do some javascript-esque code and it's blowing up.
class Product {
var name : String!
var type: String!
var description: String!
var taste: String!
var picturePath: String!
var pairings: [String]
var similar: [String]
init(dict: Dictionary<String, AnyObject>) {
let props = ["name", "type", "description", "taste", "pairings", "similar"]
for prop in props {
self[prop] = dict[prop]
}
}
}
Is there a way to do what I'm trying to do here, or do I have to manually initialize all the properties of the class e.g.
if let title = dict["name"] as? String {
self.title = title
}
//... and so on
First of all: as Alex wrote in his comment to the original question, this should generally be avoided.
It feels to weird to answer a question with "no"; even if it is
possible, it would either not be type-safe, or it would require so
much boilerplate that you'd be better off just writing the initializer
by hand. Swift is very often not conducive to writing Javascript-esque
code, since it's staticly, strongly typed.
Anyway, you can do this with the help of Mirror (reflecting upon self) and a tidy bit of obj-c; letting your class inherit from NSObject
class Product : NSObject {
var varDump: AnyObject?
var name : String?
var type: String?
// ...
init(dict: Dictionary<String, AnyObject>) {
super.init()
let a = Mirror(reflecting: self).children.filter { $0.label != nil }
for b in a {
self.setValue(dict[(b.label ?? "")], forKey: (b.label ?? "varDump"))
}
}
}
var propertyInit = [String:AnyObject]()
propertyInit["name"] = "John"
propertyInit["type"] = "Human"
var a = Product(dict: propertyInit)
print(a.name ?? "Not initalized") // John
print(a.type ?? "Not initalized") // Human
In addition to the NSObject inheritance, you see that all properties that you wish to initialize in this fashion have been set to optional above. This is naturally because swift cannot know until runtime if you actually initialize these properties or not, hence yielding a compile time error if you mark them as non-optional.
Finally, again note what Alex wrote in his comment (quoted), and take this answer as a technique to do something, but not actually something that is to be recommended if you want to follow common Swift convention. This code will easily break at runtime if you're not very careful in you dict initialization, as you fully loose type safety.