Initialize a Child Class from an instance of Parent class Swift - ios

I am kind of new to OOP (I think I understand the basics now), so I'm struggling with something:
I am currently making a personal iOS app that involves using events from the iPhone Calendar. I wanted to add properties to the built in EKEvent class but I read that's not possible with extensions.
So I decided to make my own Class, called Event, that will inherit from EKEvent and add the properties I want.
But I'm struggling with the initialization for this class: I would like to initialize Event from an instance of EKEvent since I'm getting EKEvents when I fetch the events of my Calendar, but I can't find a way to do it. I looked but didn't find a similar questions for Swift, they are using super.init() which is not what I want to do.
Here's my class, I found a workaround as you can see but I'd like to understand how to do it with inheritance if it's possible ^^
class Event { // Deleted the : EKEvent here to test my workaround
public var matiere: String = ""
public var matiereId: String = ""
public var prof: String = ""
public var salle: String = ""
public var type: String = ""
public var ekEvent: EKEvent
public var duration: DateInterval
public var hoursDuration: Int
public var minutesDuration: Int
init(ekEvent: EKEvent) {
/* Here is my workaround, if I need to access properties from EKEvent I'll use
self.ekEvent.startDate (for example) */
self.ekEvent = ekEvent
self.duration = DateInterval(start: ekEvent.startDate, end: ekEvent.endDate)
self.hoursDuration = Int(duration.duration) / 3600
self.minutesDuration = (Int(self.duration.duration) - (3600 * self.hoursDuration)) / 60
}
}
Thanks in advance and excuse my English I'm French =D

glad to hear you're getting into OOP!
So the way you've seen people doing this using super.init() is the most common and accepted way to achieve what you want, but in this case, the init function that you would want to override hasn't been marked as open.
This essentially means you can't override it and init your own variables, then call super.init. So your approach is completely fair in this case.
Streamline the process
so, as an idea, if you're aiming to try and make this a little more streamline, you could do something like this:
extension EKEvent {
func createEvent() -> Event {
.init(ekEvent: self)
}
}
This will allow you to now do this: ekEvent.createEvent() and then this will return an event object which you can use.

Related

Update jetpcak composable when a static class member changes

I have a Paho MQTT connection, with a callback updating a object and i need to update a coposable..
I can see the in Logcat that i receive information, but the composable is not updated.
I am suspecting that the issue is that i am using a static object and it is not mutable. What is the practice on this scenario? I did not implement a ViewModel. It could be done with a timer, but i think it is not an elegant solution.
snippet:
object MyCallBack : MqttCallback {
public var message = ""
override fun messageArrived(topic: String?, message: MqttMessage?) {
this.message = message.toString()
Log.e(ContentValues.TAG,"mqtt Arrived: $message")
}
......
}
and a composable function used to display the information:
#Composable
fun ShowMessage() {
var myCallBack = MyCallBack //here i can access the updated information
var message by remember {
mutableStateOf(myCallBack.message)
Text("Changed ${myCallBack.message}", color = Color.White)
}
}
Thank you!
i have tried to use mutableStateOf() but it did not called for composition, i think it is not observable.

Can't save data from 2 custom classes with userDefaults

In my app I have 2 custom classes (super class and subclass) and based on them data is created and deleted from the user dynamically and I want to be able to save the data permanently with UserDefaults and I'm not sure how.I tried looking the answers like this one - Saving custom SWIFT class with NSCoding to UserDefaults and I fint it hard to understand.
My first class(super class):
class Day {
var dayName: String
var subjects: [Subject]?
init(dayName: String) {
self.dayName = dayName
}
}
My second class(subclass):
class Subject: Day {
var subjectName: String
var startsAt: String?
init(dayName: String,subjectName: String) {
self.subjectName = subjectName
super.init(dayName: dayName)
}
}
Thanks for helping me.

How to prevent object construction in Swift [duplicate]

This question already has an answer here:
No more `private init` in Swift?
(1 answer)
Closed 6 years ago.
What ways do you know to prevent an object construction using Swift programming language?
In C++ I can simply make the constructor private like this:
struct A {
private:
A() {};
};
int main()
{
// Doesn't compile because the constructor is private.
A obj;
return 0;
}
When I do a similar thing in Swift (I tried it in playground) the code compiles just fine:
class A {
private init() {}
}
let obj = A()
UPDATE:
Ok, this question is marked as a duplicate. But I think this is a misunderstanding. What I'm asking about is what are the best practices you know to prevent object construction in Swift. All I want to achieve is to make it clear to the users of my class that it should not be constructible.
UPDATE 2:
As this question is still here, I think, it needs some more clarifications for those who still can't comprehend what I really want.
Given a class that is used as a wrapper for some useful constants such as the following:
class Constants {
static let someConstant1 = "CONSTANT_VALUE1"
static let someConstant2 = "CONSTANT_VALUE2"
//....etc...
}
what option can be considered as a best practice:
Leave it as is and don't worry about the possibility of objects creation outside this class;
Add private init() {} to prevent creation of the objects outside the current file;
Use init? and return nil to indicate that the objects must not be created as was suggested in the comments.
Hope the question is more clear now.
From Apple's guide to Swift:
Private access restricts the use of an entity to its own defining
source file. Use private access to hide the implementation details of
a specific piece of functionality.
Your playground file is all one file, so privacy is not enforced.
For instance, if you create a new project and add a file called Dog.swift to the project that looks like this:
import Foundation
class Dog {
private init() {
print("hello")
}
}
class Cat {
var d = Dog()
}
in ViewController.swift, you can write:
override func viewDidLoad() {
let c = Cat() //=>hello
}
But, if you try:
override func viewDidLoad() {
let d = Dog()
}
Xcode will flag that as an error before you even compile the program:
'Dog' cannot be constructed because it has no accessible initializers
Response to comment:
class A {
init?() {
return nil
}
func greet() {
print("hello")
}
}
let x = A()
if let x = x {
x.greet()
}
else {
print("nice try") //=> nice try
}
i tried this, hope this is what you want
private class My {
static var singletonObj = My()
}
let obj = My() // error
let obj1 = My.singletonObj

The use of singleton class in objective c and swift

I have a project implemented in both Objective C and Swift classes and I need to have global variables to be shared among these classes .
I have two variables currentUsername and currentUsernumber , I need to use these two in each view in the project, what is the best way to implement that ?
I have tried to implement singleton class and here is my code :
class curentUserSingleton {
static var instance: curentUserSingleton!
var currentUsername: String = ""
var currentUsernumber: String = ""
// SHARED INSTANCE
class func sharedInstance(Name : String , Number : String) -> curentUserSingleton {
self.instance = (self.instance ?? curentUserSingleton(uName: Name , uNumber: Number))
return self.instance
}
// METHODS
init(uName : String , uNumber : String) {
self.currentUsername = uName
self.currentUsernumber = uNumber
}}
But I don't know how to use this class safely in the OC and Swift and I am a little confused since I get declaration errors when I use the class in my code!
Is this the right way to write a singleton class and how to call it in both languages ?
I'd be inclined to do something like:
class User: NSObject {
static let sharedInstance = User()
var name: String?
var number: String?
}
Then you can set and retrieve name and number like so in Swift:
User.sharedInstance.name = "Foo"
User.sharedInstance.number = "42"
print(User.sharedInstance.name)
print(User.sharedInstance.number)
Obviously, to access this from Objective-C .m file, you have to have to include the system generated header like so:
#import "ModuleName-Swift.h" // obviously, replace `ModuleName` with the name of your module
But then the syntax for setting and retrieving these properties is similar as it was in Swift:
[User sharedInstance].name = #"Foo";
[User sharedInstance].number = #"42";
NSLog(#"%#", [User sharedInstance].name);
NSLog(#"%#", [User sharedInstance].number);
To me it seems you do not need a singleton at all. I suggest you would be best of redesigning the architecture to have a user class that can store the information you are needing (and more if you finds the need in the future).
Then you could either pass that user object around between the view controllers as they need or perhaps easier define a currentUser property for the app delegate class.
That way each view controller can obtain the app delegate from the NSApp global reference to the application object and then get the current user object from there. With this pattern the app delegate acts as the globally accessible singleton you need without any need to manage it yourself.

Get and Set on each field like in Java

I tried to look all over the internet to find out what is the best practice of encapsulating data in Swift. I only found some information about get and set method of an instance variables. They used to work pretty much like C#'s did set, but now they work as computed properties and one can't set them in their setters and can't get them in their getters. The question is: do people still create getter and setter for each property in the class in swift ? Like:
private var age: Int = 0
public func getAge() -> Int {
return age
}
public func setAge(newAge: Int) {
self.age = newAge
}
If not, then what is considered to be the best practice ?
Thank You.
I use this type of syntax with computed vars to expose the getter and setters when the internals are more complex than what is shown here:
internal var _age: Int = 0
var age: Int {
get {
return _age
}
set {
_age = newValue
}
}
Plenty of syntaxic sugar to make it easy to hide complexity in some expressions.
But most of the time I am happy with just exposing the plain var and be done with it:
var age: Int = 0
The advantage of this is that both ways are easily swappable when you want to do more work inside the getters and setters.
I don't think you need to create getX/setX methods, because you can always change from a stored to a computed property without having to change the source code of the clients. Just like you could change the bodies of your getAge & setAge methods, so I do not see what is gained in swift by not letting clients use age.
if you want to access the property (Age) itself, you can always get/set it directly.
let theGirlsAge = Age; // Get
Age = theBoysAge; // Set
Getters and Setters are used for define relationship between the property and other properties.
public func getAge() -> Int {
return theBoysAge
}
public func setAge(newAge: Int) {
theGirlsAge = newAge
}

Resources