Best Approach to Refresh a Class [closed] - ios

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 6 years ago.
Improve this question
Simply i want to know what is the Best Approach to refresh a class.Like when same class is used from diff-diff section of application where we pass some data to that class ,I can do it by simply taking a global variable and change it's value from other class's But i want to know some another approach which is best suitable for this kind of Things.

The best way to handle this kind of structure, where the class needs to be effectively shared between other MVCs, is to make the class a singleton. This means that only one instance of a class is ever used. That way if one MVC changes the class you don't need to sync the change because every MVC uses the same instance.
To make a class a singleton you do the following
Create a static var which is an instance of the class
Make the init function private so no other class can initialise it
Eg
class Singleton {
static var shared = Singleton()
var info = "singleton info variable"
private init() {}
func doSomething() {}
}
To access the class you do the following
Singleton.shared.doSomething()
or
let singletonInfo = Singleton.shared.info

You have two options:
(Simplified) - Either you create a new instance and pass it on:
class MyClass {
let name: String
init(name: String) { self.name = name }
}
class MyViewController: UIViewController {
let myClass = MyClass(name: "Hello World")
func actionThatCausesSegue() {
let copyOfMyClass = MyClass(name: self.myClass.name)
self.performSegueWithIdentifier(identifier: "MySegue", sender: copyOfMyClass)
}
}
Or you can use structs:
struct MyStruct {
let name: String
init(name: String) { self.name = name }
}
class MyViewController: UIViewController {
let myStruct = MyStruct(name: "Hello World")
func actionThatCausesSegue() {
// structs are always copied when passed around.
self.performSegueWithIdentifier(identifier: "MySegue", sender: self.myStruct)
}
}
Structs are always copied, when you pass them around. Here's the explanation from the Swift Programming Language Guide by Apple:
Structures and Enumerations Are Value Types
A value type is a type whose value is copied when it is assigned to a
variable or constant, or when it is passed to a function.
You’ve actually been using value types extensively throughout the
previous chapters. In fact, all of the basic types in Swift—integers,
floating-point numbers, Booleans, strings, arrays and dictionaries—are
value types, and are implemented as structures behind the scenes.
All structures and enumerations are value types in Swift.
You can read more about the differences here.

It depends on the situation, but I sometimes do this for views in iOS. For example when the data model changes you want the view to update, so I implement a method in the controller called configureThingyViewWithThingy which takes the new 'thingy' and updates the view. Then whatever mechanism you're using to monitor data model changes (KVO, notifications, etc.) will call this method to reconfigure the view with the new data.

Related

ios swift models structure with realm database

I am developing my iOs App and I am using Realm database. As I am totally new to ios developing (also swift and xcode) I have question about structuring data (I've already read some general project structure guidelines but couldn't find the answer). My thinking is connected with Java structures
For Realm databases (RealmSiwft) I created a model like this:
#objcMembers class Patient: Object {
dynamic var patientId:Int = 0
dynamic var refNumber:String = ""
convenience init(id:Int, refNumber:String){
self.init()
self.patinetID = id
self.refNumber = refNumber
}
}
Now, it looks just like a POJO class in Java. But as I learned, this model structure is made that way so it can be able to use Realm.
So the question is, if I need somewhere else in my project to use Patient objects, is this Realm-POJO-model good to use? I mean, should I use it just like a normal Model even when I dont need to make database operations on it? Or should I make this Realm model alike DAO class for databases operations and make another model class like Patient.swift for whenever I want to play with Patient without using databases (I hope not, cause it's so much code duplicating)
And what if I need variables in that Patient Model that won't be stored in database? Can I make it without dynamic? What about init than? That blows my mind, as far as I learn swift it seems so ugly and unstructured, or I just can't switch to it yet...
if I need somewhere else in my project to use Patient objects, is this
Realm-POJO-model good to use?
even when I dont need to make database operations on it?
You can use your Patient object without savings to the DB, move them to different controllers and so on.
what if I need variables in that Patient Model that won't be stored
in database?
Look to ignoredProperties() method.
Can I make it without dynamic?
No you can't because of Realm based on Objective-C object, so this is necessary type.
What about init than?
You can create different Constructors methods, look to the Initialization doc. In case with Realm you should setup values to noticed variables (if you don't give them Default Property Values)
Your class should look like this:
class Patient: Object {
// MARK: - Properties
#objc dynamic var patientId: Int = 0
#objc dynamic var refNumber: String = ""
// MARK: - Meta
// to set the model’s primary key
override class func primaryKey() -> String? {
return "patientId"
}
//Ignoring properties
override static func ignoredProperties() -> [String] {
return ["tmpID"]
}
//It's ok
convenience init(id:Int, refNumber:String){
self.init()
self.patientId = id
self.refNumber = refNumber
}
}
All other detail information you can find in: realm docs
Also you can extend you base code with swift extension:
extension Patient {
var info: String {
return "\(patientId) " + refNumber
}
func isAvailableRefNumber() -> Bool {
return refNumber.length > 6
}
}

Array Data Through Different View Controllers Swift

Hey guys I'm working on my first ever app and need some help. My workout tracker app has two classes which you can find below. I have two view controllers hooked up to their own swift files.
Heres my first view controller
Basically what it does is takes the data in the text fields and steppers and turns it into a "Workout" object then appends it to the "WorkoutList" class array.
I've got a print statement setup that prints the Array.count. It shows the correct number in the debug but when I switch views it gets reset to zero.
#IBAction func addToWorkoutList(_ sender: UIButton) {
let workout = Workout(name: workoutName.text!, description: workoutDescription.text!, sets: Int(setStepper.text!)!, reps: Int(repStepper.text!)!)
workoutArrayList.append(workout)
print(workoutArrayList.count)
}
The second view inherits the first views class so that is how I access the "WorkoutArrayList"
class OverViewViewController: NewWorkoutViewController, UITableViewDelegate, UITableViewDataSource {
My app basically allows you to add a workout then produces a graph based on the data you provided. This can make it easy to visualize your gains in the gym. I'm doing this as a learning project so any help on what I should do to build this app would also be greatly appreciated.
Workout Object Class
import Foundation
class Workout {
let workoutName : String
let workoutDescription : String
let numberOfSets : Int
let numberOfReps : Int
init(name : String, description : String, sets : Int, reps : Int) {
workoutName = name
workoutDescription = description
numberOfSets = sets
numberOfReps = reps
}
}
WorkoutList Class
import Foundation
class WorkoutList {
let workoutArray : [Workout] = []
}
Inheriting the class is not what you want to do here. An easy fix for you would be to make workoutArray a static variable so any class can access it at any given time.
static var workoutArray : [Workout] = []
Here is why just inheriting the class doesn't work. When the OverViewViewController loads in to the app, it creates a new instance of the class OverViewViewController and since it inherits NewWorkoutViewController, it also creates a new instance of the NewWorkoutViewController class. You have 2 different instances of NewWorkoutViewController, changing a variable in one of those instances won't change it for any other instances of the class. A static variable, however, is what you are looking for. The array can be changed and accessed any time from any class, you don't even need to inherit. It would work whether you made workoutArray static or workoutArrayList static.
If you have any other questions, feel free to leave a comment.

Save EVObjects with CoreData

I need to save some data with CoreData. Generally thats not a problem at all. The problem is, that the data is created with EVReflection an therefore inherits the class EVObject. To save the gathered data to CoreData they have to also inherit NSManagedObject. The problem is that swift does not allow you to inherit multiple classes. Would appreciate any tips.
class Device : EVObject
{
var channel : [Channel] = [Channel]()
var name : String = ""
var ise_id : Int = 0
var unreach : Bool = false
var sticky_unreach : Bool = false
var config_pending : Bool = false
override internal func propertyMapping() -> [(String?, String?)] {
return [("name", "_name"), ("ise_id", "_ise_id"), ("unreach", "_unreach"), ("sticky_unreach", "_sticky_unreach"), ("config_pending", "_config_pending")]
}
}
You don't have to inherit. You can extend them. Example:
class User : NSManagedObject{
#NSManaged .....
}
//Extension
import EVReflection
extension User : EVReflectable { }
https://github.com/evermeer/EVReflection#extending-existing-objects
Note I'm not aware of EVReflection but I think this answer can generally apply.
Don't use multiple inheritance. Have two separate classes and a mechanism for creating/loading/updating one object from the other. Protocols may allow it to be done in a way that minimises translation boilerplate (possibly using valueForKey(_:) and setValue(_:forKey) if you can know the key names in a safe manner.
It may not even be even be necessary to have an NSManagedObject subclass but just have an instance of NSManagedObject in all your classes that is loaded/created/saved as necessary.
It depends on what functionality you want to use from EVReflection. Since NSManagedObject also has NSObject as it's base class you could use most functions by just setting NSManagedObject as your base class instead of EVObject.
The only thing you have to do is instead of calling EVObject functions directly, you have to implement the code snippets that are in that EVObject method. Almost any function there is just a convenience method that will call the corresponding EVReflection function.
If you have any questions in the future, then please also report this as an issue on GitHub.

initializing class properties before use in Swift/iOS

I'm having trouble grasping the proper way of instantiating variables that always need to be set before an object is fully functional but may need to be instantiated after the constructor. Based on Swift's other conventions and restrictions it seems like there is a design pattern I'm unaware of.
Here is my use case:
I have a class that inherits from UIViewController and will programmatically create views based on user actions
I need to attach these views to this class, but to do so I need to retrieve their content based on configuration data supplied by another controller
I don't care if this configuration data is passed to the constructor (in which case it would always be required) or supplied by a secondary call to this object before it is used
My problem seems to be that both of the approaches in bullet 3 seem flawed.
In the first case, there is only one legitimate constructor this class can be called with, yet I'm forced to override other constructors and initialize member variables with fake values even if the other constructors are never intended to be used (I'm also trying to keep these variables as let types based on Swift's best practices).
In the second case, I'm effectively splitting my constructor into two parts and introduce an additional point of failure in case the second part fails to be called prior to class being used. I also can't move this second part to a method that's guaranteed to be called prior to usage (such as viewDidLoad) because I still need to pass in additional arguments from the config. While I can make sure to call the initPartTwo manually, I'd prefer to have a mechanism that better groups it with the actual constructor. I can't be the first one to run into this and it seems like there is a pattern I'm not seeing to make this cleaner.
UPDATE:
I ended up going with a modified version of the pattern matt suggested:
struct Thing {
let item1: String
let item2: String
struct Config {
let item3: String
let item4: String
}
var config:Config! {
willSet {
if self.config != nil {
fatalError("tried to initialize config twice")
}
}
}
init() {
self.item1 = ...
self.item2 = ...
...
}
public func phaseTwoInit(item3: String, item4: String) {
self.item3 = item3
self.item4 = item4
...
}
}
var t = Thing()
...
t.phaseTwoInit(...)
...
// start using t
If an initial instance variable property value can't be supplied at object initialization time, the usual thing is to declare it as an Optional. That way it doesn't need to be initialized by the class's initializers (it has a value - it is nil automatically), plus your code subsequently can distinguished uninitialized (nil) from initialized (not nil).
If the Optional if an implicitly unwrapped Optional, this arrangement need have no particular effect on your code (i.e. it won't have to be peppered with unwrappings).
If your objection is that you are forced to open the door to multiple settings of this instance variable because now it must be declared with var, then close the door with a setter observer:
struct Thing {
var name:String! {
willSet {
if self.name != nil {
fatalError("tried to set name twice")
}
}
}
}
var t = Thing()
t.name = "Matt" // no problem
t.name = "Rumplestiltskin" // crash

Passing Data Between .Swift Files in Xcode [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 7 years ago.
Improve this question
i'm new to swift, i have a project in Xcode 7 Beta, and i have extension files and etc. i have 3 .swift files (not for view controllers) in my project, and i want to define a variable or constant in one of them and access that , all over the project. for example define a var in First.swift , and access to that in Second or Third.swift files. i know about NSUserDefaults in Xcode, but i don't want to use that.
Also i know that how i can pass data between viewcontrollers (using prepareforsegue and etc.)
but i want to pass data between .swift files.
One way to do it is you can encapsulate them in struct and can access anywhere.
You can define static variables or constant in swift also.Encapsulate in struct
struct MyVariables {
static var yourVariable = "someString"
}
You can use this variable in any class or anywhere:
let string = MyVariables.yourVariable
println("Global variable:\(string)")
//Changing value of it
MyVariables.yourVariable = "anotherString"
Or you can declare global variables which you can access anywhere.
Reference from HERE.
Take a look at http://www.raywenderlich.com/86477/introducing-ios-design-patterns-in-swift-part-1
The idea is to create one instance of a class and access it anywhere in your files/classes.
If you just need to share constants, the Dharmesh's solution is simpler.
You can create custom subclass of NSObject class. Declare all variables there. Create single instance of object of that class and access variables through the object of that class in any view controller.
class Singleton {
class var sharedInstance: Singleton {
struct Static {
static var onceToken: dispatch_once_t = 0
static var instance: Singleton? = nil
static var yourVariable = "someString"
}
dispatch_once(&Static.onceToken) {
Static.instance = Singleton()
}
return Static.instance!
}
}
then in any viewController, you can access the variables.

Resources