Inheritance, protocols and static fields - ios

How can I get rid of repetition here for the fields id and commonStaticField?
struct S1 {
let id: String //note - it's let
static let commonStaticField = "s1" //note - it's static
let someField1: String
let someField2: String
}
struct S2 {
let id: String
static let commonStaticField = "s2"
let someField3: String
let someField4: String
}
I've tried to use this with different variations:
protocol P1 {
let id: String
static let commonStaticField: String //static not allowed
}
but it didn't pan out. I'd like to be able to do this:
struct S1: P1 {
static let commonStaticField = "s1" //note - it's static and defined
let someField1: String
let someField2: String
}
let s1 = S1(id: "some id", someField1: "some field3", someField2: "some field2")

Related

How can I create a UITableView for each property in a model?

I have a struct that looks something like this:
internal class RemoteProfileModel: Decodable {
let userId: String
let company: String
let email: String
let firstName: String
let lastName: String
let department: String
let jobTitle: String
let pictureUri: URL?
let headerUri: URL?
let bio: String
let updatedDate: Date
}
I need to list out these properties in a UITableView. I also need to use different cell types for some of the properties.
I'm thinking perhaps I should convert this struct to a dictionary of key/value pairs, and use the key to determine the cell type.
Is this possible? Is there another way to achieve this? I am unsure if it possible to convert a struct to a dictionary so am not sure this is the best way?
to convert a class to a dictionary,
class RemoteProfileModel: Decodable {
let userId: String
let company: String
let email: String
let firstName: String
let lastName: String
let department: String
let jobTitle: String
let pictureUri: URL?
let headerUri: URL?
let bio: String
let updatedDate: Date
init() {
userId = "666"
company = "AAPL"
email = "hehe#163.com"
firstName = "user"
lastName = "test"
department = "guess"
jobTitle = "poor iOS"
pictureUri = URL(string: "wrong")
headerUri = URL(string: "none")
bio = "China"
updatedDate = Date()
}
func listPropertiesWithValues(reflect: Mirror? = nil) -> [String: Any]{
let mirror = reflect ?? Mirror(reflecting: self)
if mirror.superclassMirror != nil {
self.listPropertiesWithValues(reflect: mirror.superclassMirror)
}
var yourDict = [String: Any]()
for (index, attr) in mirror.children.enumerated() {
if let property_name = attr.label {
//You can represent the results however you want here!!!
print("\(index): \(property_name) = \(attr.value)")
yourDict[property_name] = attr.value
}
}
return yourDict
}
}
Call like this:
let profile = RemoteProfileModel()
profile.listPropertiesWithValues()
In Swift Debugging and Reflection,
A mirror describes the parts that make up a particular instance

how to pass value to struct dynamically

I am trying to form an URL dynamically.
where I am using Struct to construct it form resultant url
Constants.Swift
import Foundation
private struct Domains {
static let Local = "localhost IP"
static let QA = "QA.Environment"
static let UAT = "http://test-UAT.com"
}
// HardCoded URLRoutes
private struct URLRoutes{
static let query = "query=bitcoin&"
static let date = "date=2019-04-04&"
static let sortBy = "sortBy=Date&"
}
private static let constructionURL = Domain.local+URLRoutes.query + URLRoutes.date + URLRoutes.sortBy + API.Key
static var ResultantURL: String {
return constructionURL
}
I am trying to make this dynamic to pass value from other class to form the dynamic url.
private struct URLRoutes{
var query : String
var date : String?
var sortBy : String?
}
From another Class trying to access the resultant URL
url = URL(string: URLRoutes.ResultantURL)!
but how can I construct the formate of url from the another class?
static let query = "query=bitcoin&"
static let date = "date=2019-04-04&"
static let sortBy = "sortBy=Date&"
Your inputs will guide me.
Here's playground code that does what you want:
struct API {
static let Key = "ABC123"
}
struct URLRoutes{
var query : String
var date : String?
var sortBy : String?
var constructionURL: String {
return query + (date ?? "") + (sortBy ?? "") + API.Key
}
}
let query = "query=bitcoin&"
let date = "date=2019-04-04&"
let sortBy = "sortBy=Date&"
let myRoute = URLRoutes(query: query, date: date, sortBy: sortBy)
print(myRoute.constructionURL)
However, this isn't really ideal and doesn't use the constructs that Apple provides. Here's another approach:
struct URLRoute {
var queryItems:[URLQueryItem]
init(query: String, date:String?, sortBy:String?) {
queryItems = [
URLQueryItem(name: "query", value: query),
URLQueryItem(name: "date", value: date),
URLQueryItem(name: "sortBy", value: sortBy),
URLQueryItem(name: "api_key", value: API.Key)
]
}
var constructionURL:String {
get {
var component = URLComponents(string: "")
component?.queryItems = queryItems
return component?.string ?? ""
}
}
}
let betterRoute = URLRoute(query: "bitcoin", date: "2019-04-04", sortBy: "Date")
print(betterRoute.constructionURL)
You can use URLComponents to do lots of heavy lifting for you in creating valid URLs.

how to add information in an array with a class Swift

I've got a problem for adding some informations in an array.
My class Flights is define by the following :
class Flight{
let date: String
let type: String
let regi: String
let totalTime: String
let depTime: String
let depPlace: String
let arrTime: String
let arrPlace: String
init(from dat: String, _ typ: String, _ reg: String, _ totaltim: String, _ depTim: String, _ depPlac: String, _ arrTim: String, _ arrPlac: String) {
self.date = dat
self.type = typ
self.regi = reg
self.totalTime = totaltim
self.depTime = depTim
self.depPlace = depPlac
self.arrTime = arrTim
self.arrPlace = arrPlac
}}
In my main code I've got declare my array like this :
var datas: [Flight] = []
And finally I've this code to add some informations coming from firebase :
(I add some comment to show you what print() result)
if let user = Auth.auth().currentUser{
// user is connect
let ref = Database.database().reference()
let userID = Auth.auth().currentUser?.uid
let ev = ref.child("flights").child(userID!)
ev.observe(.childAdded, with: { (snapshot) -> Void in
let flightKey = snapshot.key
ref.child("flights").child(userID!).child(flightKey).observeSingleEvent(of: .value) {(snapshot) in
let value = snapshot.value as? NSDictionary
let date = value?["Date"] as? String ?? "no date"
let type = value?["aircraft-model"] as? String ?? "no type"
let registration = value?["aircraft-registration"] as? String ?? "no callsign"
let totalTime = value?["TOTAL-TIME"] as? String ?? "no total Time"
let deppartTime = value?["departure-time"] as? String ?? "no departure Time"
let deppartPlace = value?["departure-place"] as? String ?? "no departure Place"
let arrivalTime = value?["arrival-time"] as? String ?? "no arrival Time"
let arrivalPlace = value?["arrival-place"] as? String ?? "no arrival Place"
print("Date : \(date) - type : \(type) - registration : \(registration) - Etc ...")// Give me exactly the value I requested
self.datas.append(Flight(from: date, type, registration, totalTime, deppartTime, deppartPlace, arrivalTime, arrivalPlace))
print(self.datas)// Give me "MyProjectName.Flight ...
}
})
}else{
// si non connecté alors DECONNEXION !!!!
fatalError("error ...")
}
So I don't understand why if I print the received value from firebase it work but if I print the array value which is completed by the firebase received value it didn't work ?
Thanks for your help !
Flyer-74
Welcome :)
I think all is as expected and you're just seeing this because Swift doesn't know how to describe your objects.
To fix this, you should implement the CustomStringConvertible protocol in your Flight class (https://developer.apple.com/documentation/swift/customstringconvertible)
So something like
extension Flight: CustomStringConvertible {
var description: String {
var description = ""
description.append("date: \(date)\n")
description.append("type: \(type)\n")
description.append("regi: \(regi)\n")
//and so on
return description
}
}
Should give you what you are looking for.
Hope that helps you
You can try to adopt CustomStringConvertible protocol
class Flight : CustomStringConvertible {
var description: String {
return "\(date) \(type)" // add here any variable you want it to be printed
}
let date: String
let type: String
let regi: String
let totalTime: String
let depTime: String
let depPlace: String
let arrTime: String
let arrPlace: String
init(from dat: String, _ typ: String, _ reg: String, _ totaltim: String, _ depTim: String, _ depPlac: String, _ arrTim: String, _ arrPlac: String) {
self.date = dat
self.type = typ
self.regi = reg
self.totalTime = totaltim
self.depTime = depTim
self.depPlace = depPlac
self.arrTime = arrTim
self.arrPlace = arrPlac
}
}
You could add a custom debug description for your object by adding an extension to Flight, and make it conform to the CustomDebugStringConvertible protocol. Conformance to this protocol requires that you provide a property: var debugDescription: String { get }. Inside this string is where you have full control over the debug values for your custom Object.
extension Flight: CustomDebugStringConvertible {
var debugDescription: String {
return "Date: \(date), Type: \(type), Registartion: \(regi)"
}
}

Storing values locally using NSUserDefaults

I have the following block of code
let defaults = NSUserDefaults.standardUserDefaults()
let username = self.emailText.text
let password = self.passwordText.text
defaults.setValue(username, forKey: defaultsKeys.userKey)
defaults.setValue(password, forKey: defaultsKeys.passwordKey)
var u = defaults.stringForKey(defaultsKeys.userKey)
var p = defaults.stringForKey(defaultsKeys.passwordKey)
username and password are correct when setting. However, when I pull them back u and p have the same value, and it's the password value.
I declare defaultKeys at the top of the page this way.
struct defaultsKeys {
static let userKey = ""
static let passwordKey = ""
}
I'm assuming there's a simple syntax error that I'm not seeing, because this seems like it should work.
Set different key names:
struct defaultsKeys {
static let userKey = "userKey"
static let passwordKey = "passwordKey"
}
You have the same key for both, just set a different key for each one:
struct defaultsKeys {
static let userKey = "USER_KEY"
static let passwordKey = "PWD_KEY"
}
struct defaultsKeys
{
static let userKey = "userKey"
static let passwordKey = "passwordKey"
}

What does contextual type 'MGTransitioningOptions' cannot be used with array literal mean?

At one point I'm guessing before Swift 3 the following line of code used to compile but now it does not:
var directions: MGTransitioningOptions = [.DirectionUp]
It gives the following error: "contextual type 'MGTransitioningOptions' cannot be used with array literal"
Here is the code for the struct where MGTransitioningOptions is created:
struct MGTransitioningOptions: OptionSet {
internal let rawValue: Int
init(rawValue: Int) {self.rawValue = rawValue}
static let DirectionUp = MGTransitioningOptions(rawValue: 1<<1)
static let DirectionDown = MGTransitioningOptions(rawValue: 1<<2)
static let DirectionLeft = MGTransitioningOptions(rawValue: 1<<3)
static let DirectionRight = MGTransitioningOptions(rawValue: 1<<4)
static let AlphaChange = MGTransitioningOptions(rawValue: 1<<5)
static let BlurBackground = MGTransitioningOptions(rawValue: 1<<5)
static let Dissolve = MGTransitioningOptions(rawValue: 1<<6)
static let Interactive = MGTransitioningOptions(rawValue: 1<<7)
}

Resources