Clearing out shared instance in swift while logging out - ios

I have a shared instance user profile class which I'm using to maintain the user details throughout the app, now when I log out I want to clear out all the data in this shared instance class. Below is my sample declaration of current class
class UserProfile: NSObject {
static let sharedUserInstance = UserProfile()
var firstName: String?
var lastName: String?
var userType = UserType.student
var email: String!
var zipCode: String!
var profileImage: UIImage = Constants.defaultProfilePic
var hobbies: [String]?
var userPreferences: UserPreferences?
}
I would like to clear out all the variables in the shared instance at once. One way to go about would be to declare a clear function and set nil to each object for eg:
func clear() {
firstName = nil
lastName = nil
so on...
}
Is there any better or easier way to do this so that my UserProfile.sharedUserInstance gets resets at once ?

You can create a sigleton class for the entire project and save user information in that class and at logout time assign nil to that object
class Singleton {
private init() {}
static let shared = Singleton()
var userInfo:UserInfo?
}
on login just assign user information object to this from your viewController like this
Singleton.shared.userInfo = your_object_to_save
and on logout just assign it nil value
Singleton.shared.userInfo = nil

This is one way to do it.
I created a second class called user, which will only be accessed by UserProfile.
Each UserProfile object has a User instance variable.(I don't know how, but if you can figure out a way to make the User class private to UserProfile, that would be ideal)
In swift, variables can have getters and setters so you can have matching variables in UserProfile and have their getters and setters access the variables in User.
When done this way, you can access the variables in UserProfile without needing any knowledge of the User class.
Then in the UserProfile clear function you can just do self.user = User()
I reduced your variables down to just first name and last name for a simpler answer.
class User: NSObject {
var firstName: String?
var lastName: String?
}
class UserProfile {
static var userProfile = UserProfile()
var user = User()
var firstName: String? {
get{return user.firstName}
set{user.firstName = newValue}
}
var lastName: String? {
get{return user.lastName}
set{user.lastName = newValue}
}
func clear(){
self.user = User()
}
}

Related

Create an app lifetime object (not possible to be deallocated) in Swift

I want to create an object from a class. And I want it life time to be the app life time. I mean I want it not be deallocated since the app is running.
the class that I want to make an instance from:
extension Post {
#NSManaged var userId: Int
#NSManaged var id: Int
#NSManaged var title: String
#NSManaged var body: String
}
class Post: NSManagedObject {
// Insert code here to add functionality to your managed object subclass
override func awakeFromInsert() {
super.awakeFromInsert()
title = ""
userId = 0
id = 0
body = ""
}
}
An object that keeps a strong pointer to itself cannot be deallocated:
class Permanent {
private var ref: Permanent?
init() {
ref = self
}
deinit {
// This will never be called
print("Permanent deinit")
}
}
func test() {
var a = [Permanent(), Permanent()]
print(a.count)
print("free the items")
a = []
print("end of test")
}
test()
Output:
2
free the items
end of test
If you comment out the ref = self line:
Output:
2
free the items
Permanent deinit
Permanent deinit
end of test

How to create an interface for a CoreData model (NSManagedObject)?

I'm trying to migrate from CoreData to FireBase. Hence the need for a shared interface across the app for my model.
I have a FTEvent class...
#objc(FTEvent)
public class FTEvent: FTEventBase {
}
that inherits from FTEventBase
#objc(FTEventBase)
public class FTEventBase: NSManagedObject {
}
Now I have a new class called FTRecord, which should share an interface with FTEvent above.
class FTRecord {
let key: String
var notes: String
var rating: Int
var time: String
var timestamp: Double
}
This is now where the problem begins. I could obviously create a protocol as interface for both FTRecord and FTEvent.
protocol IEvent {
var is_deleted: Bool? { get set }
var notes: String? { get set }
var date: Date? { get set }
var timestamp: Double? { get set }
var rating: Int? { get set }
}
But this becomes very hard since Bool in CoreData is actually a NSNumber. The Date is NSDate. Because of these type differences, I have no way to create a common interface.
Is there any advice, how I could achieve that?

Why I can't access an element of a class instance in Swift

I'm currently writing an iPhone application in Swift. I have a global class instance of my user database, like this:
var currentUser = UserDB()
class UserDB: Object {
dynamic var id:String = "0"
override class func primaryKey() -> String {
return "id"
}
var userName: String?
var firstName: String?
var lastName: String?
}
Then I try to print my user info with a print in another class:
UserDB {
id = 56826e22971f34731a07ba09;
userName = aze;
firstName = (null);
lastName = (null);
}
But if I try to print a single value, it won't works:
print(currentUser.userName)
Will print:
nil
Do you have any idea why?
By the way, is it a good idea to deal with user info like this? I put these info inside a Realm database on exit, when going to background, or after account upgrade.
You need to declare the properties as dynamic if you want Realm to map them. It seems that you did this only for the id property.
dynamic var userName: String?
dynamic var firstName: String?
dynamic var lastName: String?

Way to use inherited objects in swift

I have an object that might look something like this...
class User {
var username: String?
}
I'd like to have users that could either be a student or a teacher. At the moment, I've added in properties to the User class like this...
class User {
var username: String?
// student properties
var year: Int?
// teacher properties
var department: String?
}
I'm sure I should be using inheritance here, but I'm worried that's going to make the control flow a bit complicated. For example, as part of the login function, I do this...
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
appDelegate.user = User(delegate: self)
appDelegate.user!.load_from_user_defaults()
Or to get something from the current user, I would do this...
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
var username = appDelegate.user.username
How would I use inheritance, in this situation, given that I wouldn't know if it was a teacher or a student logging in? Is it easier to stick to the way I'm doing it?
Some options:
Super/Sub class pattern (inheritance) where you use downcast to check if it is a Student or a Teacher.
Protocols work the same as the Super/Sub pattern but a type can conform to many protocols but can only inherit from one super.
if both Student and Teacher have the same properties you can also just add a property (a bool or an enum) to determine which is which.
create an enum instead of a protocol or super class that has a rawValue of User and has cases for both Teacher and Student. (this is complicated)
Use an enum with associated values.
Every method has it's own benefits and drawbacks.
If you want to be able to pass a User object to different functions in your app, you want to have some conformance/inheritance.
If you have some conformance/inheritance, you can load the user with a method of your choosing and then downcast as such:
if let student = user as? Student {
// do student stuffs
} else if let teacher = user as? Teacher {
// do teacher stuffs
}
Option 1, regular inheritance :
class User {
var username: String?
}
class Student : User {
// student properties
var year: Int?
}
class Teacher : User {
// teacher properties
var department: String?
}
Option 2, conform to instead of inherit from, AKA Protcols :
protocol User : class {
var username: String? { get set }
}
class Student : User {
var username: String?
// student properties
var year: Int?
}
class Teacher : User {
var username: String?
// teacher properties
var department: String?
}
Option 3, UserType property:
enum UserType {
case Student
case Teacher
}
class User {
var username: String?
// student properties, if it is a teacher we leave this blank
var year: Int?
// teacher properties,, if it is a student we leave this blank
var department: String?
var type : UserType?
}
Option 4, enum with User as rawValue:
class User: Equatable,StringLiteralConvertible {
var username: String?
// student properties
var year: Int?
// teacher properties
var department: String?
var type : String?
init(withType type:String) {
self.type = type
}
required convenience init(stringLiteral value: String) {
self.init(withType: value)
}
required convenience init(extendedGraphemeClusterLiteral value: String) {
self.init(withType: value)
}
required convenience init(unicodeScalarLiteral value: String) {
self.init(withType: value)
}
}
func ==(lhs:User,rhs:User) -> Bool {
if lhs.username == rhs.username && lhs.department == rhs.department && lhs.year == rhs.year && lhs.type == rhs.type {
return true
} else {
return false
}
}
enum UserType : User {
case Student = "Student"
case Teacher = "Teacher"
}
let user = UserType.Teacher
Option 5, enum with associated values:
class User {
var username: String?
}
class Student {
// student properties
var year: Int?
}
class Teacher {
// teacher properties
var department: String?
}
enum UserType {
case student(Student)
case teacher(Teacher)
}
"Could be either this or that": In Swift, you use an enumeration. One class for student, one class for teacher, one enumeration for "student or teacher".

Usage NSManagedObject model in code

I have a User model class (generated by XCode with Swift):
#objc(User)
class User: NSManagedObject { }
And it's extension:
extension User {
#NSManaged var id: NSNumber?
#NSManaged var firstName: String?
#NSManaged var lastName: String?
#NSManaged var birthYear: NSNumber?
}
I can save/fetch data from CoreData.
But can I use this class for object management without CoreData things? Or i need to create other class/struct for this?
For example, create User object (without ObjectContext), set his attributes and send it as property in some func? Maybe i can create some struct in class User (like struct {var firstNameData, secondNameData,...}) and use it in code?
I updated class:
struct User {
var id: Int!
var firstName: String!
var lastName: String!
var birthYear: UInt?
}
#objc(UserManagedObject)
class UserManagedObject: NSManagedObject {
func toStruct() -> User {
var userData = User()
userData.id = Int(self.id)
userData.firstName = self.firstName
userData.lastName = self.lastName
if let by = self.birthYear {
userData.birthYear = UInt(by)
}
return userData
}
}
Now for object management i use struct User and UserManagedObject for CoreData in/out

Resources