I am currently creating my first Swift / Mac application and I have the problem of sharing a model (in the MVC sense) between several controllers.
In C# for example one would first create a model, then a number of view models, and then plug that model into them like this:
var gameEngine = new MyGameEngine()
var vm1 = new ViewModelCockpit(gameEngine);
var vm2 = new ViewModelOptionsDialog(gameEngine);
However, in XCode it seems that my controllers I am supposed to place into the .xib, which are, in turn, automatically instantiated.
What is given Swift's language features and XCode / Objective-C existing standards the best and most professional way have a number of heavyweight models that can be shared and accessed from several controllers? (Heavyweight in the sense that they take some time, memory or complex logic / dependencies) to load and might not easily be put into the .xib themselves.
Potential answers could be: global variables, some magic / static properties, ... Ideally the solution should feel solid in a software engineering sense and take Swift's language features into account.
Depending on how complex your data model is, here are some things to consider:
For complex data models, consider using Core Data
Create a singleton DataController class that gives you access to your models from any controller in your app. In Swift it could be done like this: Using a dispatch_once singleton model in Swift
You only use XIBs/Storyboards for the UI, never for your models.
I like to create the model(s) first, then pass them into each view's initialiser code, very similar to what you describe in C#. It's also similar to how you would do this in JavaScript (for example, in Backbone JS).
let gameEngine = MyGameEngine()
let vm1 = ViewModelCockpit(nibName: "ViewModelCockpit", bundle: NSBundle.mainBundle(), gameEngine: gameEngine)
let vm2 = ViewModelOptionsDialog(nibName: "ViewModelOptionsDialog", bundle: NSBundle.mainBundle(), gameEngine: gameEngine)
class ViewModelCockpit: NSViewController {
var myGameEngineModel: GameEngineModel
init(nibName nibNameOrNil: String!, bundle nibBundleOrNil: NSBundle!, myGameEngineModel: GameEngineModel) {
self.myGameEngineModel = myGameEngineModel
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
}
}
Note — you have to call the super.init() of the parent class, and if you forget, Xcode very nicely reminds you! I use Xcode's autocompletion to provide me with the usual init function and its exact args.
Related
In my application that uses Typhoon library, I've created an AppAssembly that is being initialized in SceneDelegate like this:
self.appAssembly = [[AppAssembly new] activated];
my appAssembly looks like this
- (Person *)me;
- (Dog *)dog;
- (Cookie *)cookie;
- (DogInteractionVC *)dogVC;
- (HowManyCookiesVC *)howManyCookiesVC;
From SceneDelegate I want to transit to dogVC,
Then, from the dogVC, I want to transit to howManyCookiesVC
Calling the instance of dogVC from SceneDelegate is quite easy as I do have an access to it:
self.viewController = [self.appAssembly dogVC];
I do not understand how to pass the very same appAssembly instance to a dogVC and then to howManyCookiesVC. When I try to create an instance of AppAssembly in the dogVC, I come across the issue that I believe is called circular dependency.
There is a guide on GitHub about injecting Assembly itself. So I created a property appAssembly in a dogVC of type TyphoonComponentFactory. Here is how my initializing method inside my appAssembly for a dogVC looks like:
- (DogInteractionVC *)dogVC {
return [TyphoonDefinition withClass:[DogInteractionVC class]
configuration:^(TyphoonDefinition *definition) {
[definition useInitializer:#selector(initWithPerson:)
parameters:^(TyphoonMethod *initializer) {
[initializer injectParameterWith:[self me]];
}];
[definition injectProperty:#selector(appAssembly) with:self];
}];
}
I think the part injectProperty:#selector(appAssembly) is wrong, but I spent a long time understanding that, and I am afraid that I cannot go any further than this without some help from the community. Any help is appreciated. Thank you.
Side note:
Dear community, I am very close to being blocked from posting, as my last posts have not been well received. I believe that question has everything that it needs. If I am wrong, please let me know before putting your thumbs down so I can understand my mistakes. Thank you.
Dependency Injection:
Typhoon helps to apply the dependency injection pattern - an object oriented software approach whereby:
The key actors and their interactions with other core software components in a system a declared at the composition root.
In this way:
We can de-duplicate configuration of shared objects.
We can have the benefits of singletons without overly tight coupling.
Using Dependency Injection in a Mobile App:
When we use dependency injection in a mobile app, we start at the app delegate to launch a view controller.
The first controller will depend on some singleton services to do its job.
We may then wish to transition from one view controller to another. We can load an 'object graph' consisting of the view controller and it dependencies.
When the next controller is presented, we can release the current one.
Factory Pattern:
To transition from one controller to another we can use Typhoon as a factory for emitting built instances. The factory pattern allows us to:
Obtain an instance (ie a view controller) with a mix of runtime and static dependencies.
So to transition from one view controller to another we can inject Typhoon assembly to be used as a factory to obtain the next view controller. To inject the assembly as a factory, docs are here.
Scopes:
Depending on navigation style, controllers will typically retained in memory as long as used and then released. Meanwhile services or other shared infrastructure will be shared.
The default scope is TyphoonScopeObjectGraph
To create a shared class use definition.scope = TyphoonScopeSingleton as documented here.
Pilgrim:
Typhoon is, at least in my opinion, the best and most flexible DI library for objective-C. Meanwhile, if you use Swift you might like to try simpler and better: pilgrim.ph
While working to add cross-platform support to a NativeScript plugin, there are areas of the plugin that will need to preserve an Object state. This means that at a given time, the state of the data needs to be preserved and stored within NativeScript (TypesScript/JavaScript) and reinstated without data corruption.
While this seems to be a feat pretty straightforward in many JAVA libraries used for the Android side of the plugin, I am unsure how to replicate this for iOS development.
Researching this topic online can lead to various answers, most of which seem to require the developer to create specific methods on a given Object/Class in order to support serialization.
Option 1 - NSCoding Protocol
The NSCoding protocol — Source (Apple) — declares the two methods that a class must implement so that instances of that class can be encoded and decoded. This capability provides the basis for archiving (where objects and other structures are stored on disk) and distribution (where objects are copied to different address spaces).
The two methods mentioned are:
- (void) encodeWithCoder:(NSCoder*)encoder;
- (id) initWithCoder:(NSCoder*)decoder;
While this could work in most circumstances, this would require the NativeScript developer to figure out a way to create yet another wrapper for an iOS library (likely to be a pod package). This is more hands on than needs to be and may not be available in most situations.
Option 2 - NSKeyedArchiver/NSKeyedUnarchiver
The NSKeyedArchiver and companion NSKeyedUnarchiver protocols provide a way to encode/decode objects (and scalar values) into an architecture-independent suitable for storage in a file.
This option seems less intrusive and allows for the archived object to be turned into something sharable between environments such as base64:
declare var NSDataBase64EncodingEndLineWithLineFeed;
declare var NSDataBase64DecodingIgnoreUnknownCharacters;
// archive class instance as base64 string
const archivedObject = NSKeyedArchiver.archivedDataWithRootObject(someClassInstance);
const base64Archive = archivedObject.base64EncodedStringWithOptions(NSDataBase64EncodingEndLineWithLineFeed);
// unarchive back into a class instance
const rawData = NSData.alloc().initWithBase64EncodedStringOptions(base64Archive, NSDataBase64DecodingIgnoreUnknownCharacters);
const newClassInstance = NSKeyedUnarchiver.unarchivedObjectOfClassFromDataError(NSObject, rawData);
I was able to learn both of these concepts from an old article lost in time (but thankfully saved due to the WayBackMachine) — CocoaHeads - NSCoding
In addition to the information above, I believe one could also use NativeScript to extend an existing ObjC Class and add the required encodeWithCoder and initWithCoder methods. While I have not needed to do this or try this out, if myself or someone else happens to experiment with this with a good result please let me know and I'll add that example here.
For more information about creating a subclass by extending Objective-C classes in NativeScript, please check out this source:
https://docs.nativescript.org/core-concepts/ios-runtime/how-to/ObjC-Subclassing
For more information about Objective-C classes in NativeScript, please read up here: https://docs.nativescript.org/core-concepts/ios-runtime/types/ObjC-Classes
Let's say I have a few controllers. Each controller can at some point create new objects which will need to be stored on the server. For example I can have a RecipeCreationViewController which manages a form. When this form is submitted, a new Recipe object is created and needs to be saved on the server.
What's the best way to design the classes to minimize complexity and coupling while keeping the code as clean and readable as possible?
Singleton
Normally I would create a singleton NetworkAdapter that each controller can access directly in order to save objects.
Example:
[[[NetworkAdapter] sharedAdapter] saveObject:myRecipe];
But I've realized that having classes call singletons on their own makes for coupled code which is hard to debug since the access to the singleton is hidden in the implementation and not obvious from the interface.
Direct Reference
The alternative is to have each controller hold a reference to the NetworkAdapter and have this be passed in by the class that creates the controller.
For example:
[self.networkAdapter saveObject:myRecipe];
Delegation
The other approach that came to mind is delegation. The NetworkAdapter can implement a "RemoteStorageDelegate" protocol and each controller can have a remoteStorageDelegate which it can call methods like saveObject: on. The advantage being that the controllers don't know about the details of a NetworkAdapter, only that the object that implements the protocol knows how to save objects.
For example:
[self.remoteStorageDelegate saveObject:myRecipe];
Direct in Model
Yet another approach would be to have the model handle saving to the network directly. I'm not sure if this is a good idea though.
For example:
[myRecipe save];
What do you think of these? Are there any other patterns that make more sense for this?
I would also stick with Dependency Injection in your case. If you want to read about that you will easily find good articles in the web, e.g. on Wikipedia. There are also links to DI frameworks in Objective C.
Basically, you can use DI if you have two or more components, which must interact but shouldn't know each other directly in code. I'll elaborate your example a bit, but in C#/Java style because I don't know Objective C syntax. Let's say you have
class NetworkAdapter implements NetworkAdapterInterface {
void save(object o) { ... }
}
with the interface
interface NetworkAdapterInterface {
void save(object o);
}
Now you want to call that adapter in a controller like
class Controller {
NetworkAdapterInterface networkAdapter;
Controller() {
}
void setAdapter(NetworkAdapterInterface adapter) {
this.networkAdapter = adapter;
}
void work() {
this.networkAdapter.save(new object());
}
}
Calling the Setter is where now the magic of DI can happen (called Setter Injection; there is also e.g. Constructor Injection). That means that you haven't a single code line where you call the Setter yourself, but let it do the DI framework. Very loose coupled!
Now how does it work? Typically with a common DI framework you can define the actual mappings between components in a central code place or in a XML file. Image you have
<DI>
<component="NetworkAdapterInterface" class="NetworkAdapter" lifecycle="singleton" />
</DI>
This could tell the DI framework to automatically inject a NetworkAdapter in every Setter for NetworkAdapterInterface it finds in your code. In order to do this, it will create the proper object for you first. If it builds a new object for every injection, or only one object for all injections (Singleton), or e.g. one object per Unit of Work (if you use such a pattern), can be configured for each type.
As a sidenote: If you are unit testing your code, you can also use the DI framework to define completely other bindings, suitable for your test szenario. Easy way to inject some mocks!
I'm developing an application for transferring databases and directories of user-uploaded images/documents from our production server to the development server. The application is written in Coldfusion, but I don't think the language is relevant to this question - it's more of a structural/architecture question than a question specific to the language.
I'll be writing pseudo code for my examples, so please don't pick apart the syntax.
When I've seen class inheritance demonstrated, it's usually something simple like class Student extends Person() {}. Obviously, a Student is a more specialized Person, so this makes sense.
In my application, I have a class Site() which contains relevant information such as the DSN, file upload directory, etc. I perform my SQL exports in one class and my file upload exports in another class, both of which are called from within the site class(pseudo-code):
class Site {
public function exportSql() {
sqlExport = new sqlExport(this.dsn);
sqlExport.createDumpAndZipItAndStuff();
}
public function exportUploads() {
uploadsExport = new uploadsExport(this.uploadDirectory);
uploadsExport.copyAndZipFilesAndStuff();
}
}
The Site class doesn't do anything other than control the flow of traffic that is requested from the front-end of the application, everything else is handed off to one of the export classes.
This works fine for me, but I'd like to structure it properly. Right now, I have to pass Site's properties to the constructor of the export classes, and then set the export class's properties with those arguments. This causes a lot of duplication.
Would it be appropriate to have my export classes inherit the Site class so that I could access the properties directly? The export classes are not a more specialized Site, as in the Person/Student example I gave earlier. Rather, they just perform the heavy lifting for the Site class.
If this is not an appropriate situation for inheritance, how should I structure the application? As I said earlier, the way I'm doing it right now works, but I would like to take this opportunity to learn more about design patterns and write my code in a way that makes sense.
Inheritance should be use when something is a kind of another thing.
Like a dog is kind of animal, therefor it should inherit from animal.
Export is not a kind of Site, so it shouldn't inherit from it.
What you're looking for is Composition. Export should hold a reference to a Site which it exports. Then you can pass the Site object to it on contruction, and it can get the data from the site whenever you need.
Export shouldn't extend your Site class, since things that are Exports are not members of a subset of things that are Sites. Inheritance is overused, and Composition makes more sense in this case as you have done. One way you can refine your existing object model and improve testability is by using Dependency Injection.
Calling "new" inside an object instance makes your object model more brittle and harder to test. You could inject the instances of your exporters into the Site class.
Side note: I named the export classes a little more obviously as nouns (SQLExporter, not SQLExport). This is a stylistic thing, but I think it communicates the role of the class better: it is an object that has been delegated the role of exporting data.
public setSQLExporter( SQLExporter exporter )
{
variables.sqlExporter = arguments.exporter;
// set some properties on exporter here, like the DSN
variables.sqlExporter.dsn = this.dsn;
}
public setUploadsExporter( UploadsExporter exporter )
{
variables.uploadsExporter = arguments.exporter;
// set some properties on exporter here, like the upload directory
variables.uploadsExporter.uploadDirectory = this.uploadDirectory;
}
public function exportSql() {
variables.sqlExporter.createDumpAndZipItAndStuff();
// or maybe your generalize the interface to these exporters and do something like
// variables.sqlExporter.export();
}
public function exportUploads() {
variables.uploadsExporter.copyAndZipFilesAndStuff();
// or maybe your generalize the interface to these exporters and do something like
// variables.uploadsExporter.export();
}
Then, in your main application (or whatever was instantiating the Site object in the first place):
thisSite = new Site(...);
// Get some Exporters
thisSite.setSQLExporter( new SQLExporter() );
thisSite.setUploadsExporter( new UploadsExporter() );
// Trigger exports
thisSite.exportSql();
thisSite.exportUploads();
This opens the door to using Mock Objects to directly test Site without it needing to have a database or a filesystem to talk to. If you use a DI framework like ColdSpring, the framework could do this wiring for you.
What is the standard way of incorporating helper/utility functions in Obj-C classes?
I.e. General purpose functions which are used throughout the application and called by more than 1 class.
Can an Obj-C method exist outside of a class, or does it need to be a C function for it to have this kind of behaviour?
I would group similar functions as static methods in a helper class. These can then be called using the classname rather the instance name. Static methods are defined with a + instead of the usual -.
like so:
#interface HelperClass: superclassname {
// instance variables - none if all methods are static.
}
+ (void) helperMethod: (int) parameter_varName;
#end
This would be called like so.
[HelperClass helperMethod: 10 ];
As this is static you do not init/alloc the class. This has the advantage of clearly grouping like Helper functions. You could use standalone C functions but as your Application gets larger it can become a right mess! Hope this helps.
Tony
I don't see why people are avoiding creating functions. Objective-C is a superset of C, which means that C is part of it. Moreover, it's completely integrated—there's no wall between them.
Create functions! It's fine! Foundation does it. Application Kit does it. Core Animation does it. Core Media does it.
I see no reason not to.
There are a number of options for this in Objective-C. First, since Obj-C is a strict superset of C, you can define all your library functions in a separate module (source file) and happily call them from any Obj-C object/code you already have. If you create an obj-c source file (.m file) you can then call back into/use objects.
If your generic functions are logically manipulating other, established objects (for instances, operates on an NSString), you can use categories to graph your functions on already existing classes (where that makes sense).
Finally, as Tony points out, you can create classes with static methods (although I like this option the least, personally). I tend to use a mix of one an two... adding categories where appropriate and using standard functions for others. I generally only make a new class where it makes sense to design a class.