Can I use classes with the javascript module pattern? - module-pattern

I have a bunch of "modules" which follow the "JavaScript Module Pattern" as described in this popular article. To my understanding these modules are a way to aggregate various bits of behavior into neat namespaces.
But what if I want to be able to create a unique object instance which accepts arguments? As it stands, I can't do that as all the data is shared/static. I want to be able to do this:
var foo = new Some.Namespace.Whatever.Foo(config);
I can't change the structure of the pattern as we've been using it for a while and it works very well. I just want to tweak it so I can throw some "classes" into it which work with non-static data.

Why not try this?
var MODULE = (function () {
var my = {};
my.SomeClass = SomeClass;
function SomeClass(six) {
this.six = six;
}
SomeClass.prototype.five = 5;
return my;
})();
When you call var obj = new MODULE.SomeClass(6) it will give you a new object. obj.five is shared between all instances of SomeClass because it is attached to the prototype. However, obj.six is specific to that instance, because it is attached to obj.
Alternatively, you may not need for your class to be inside a module. You could use a class to replace the module where appropriate, because both modules and classes in this case have some overlapping functionality.

This is probably overuse of the module pattern, but is this what you mean?:
var Some = (function() {
var util = { /* ... */ };
return {
Namespace: (function() {
return {
Whatever: (function() {
var Foo = function(config) {
this.foo = config.foo || "foo";
this.bar = config.bar || "bar";
};
var Bar = function() {};
Foo.prototype.toString = function() {
return this.foo + " " + this.bar;
};
return {
Foo: Foo,
Bar: Bar
}
}())
};
}())
};
}());
var foo = new Some.Namespace.Whatever.Foo({foo: "hello", bar: "world"});
foo.toString() // "hello world"

Related

How do you access a KrollCallback in swift?

I have implemented a custom framework and it is integrated into a hyperloop enabled project.
I am passing function definitions as arguments to a swift function that takes a protocol.
Javascript:
var customListener = {};
customListener.onPayEvent = function(event) {
console.log("moop");
};
var PayView = require('Pay/PayView');
var payView = PayView.alloc().initWithPayEventListener(customListener);
This javascript function definition comes in as a KrollCallback.
Swift Code:
class PayListener: NSObject, WootPayEventListener {
let payEventListener: PayEventListener
init(payEventListener: PayEventListener) {
self.payEventListener = payEventListener
}
public func onPayEvent(PayEvent: PayEvent) {
os_log("calling payEventListener.onPayEvent")
os_log("listener description = %{public}#", self.payEventListener.description)
os_log("listener debugDescription = %{public}#", self.payEventListener.debugDescription ?? "")
// self.payEventListener.onPayEvent(payEvent: "woo dogggy")
}
}
How do I call methods on this object so that I can return the result from swift back to javascript?
I was able to do this by building the TitaniumKit framework locally and then importing it into my project.
The TitaniumKit source code is here: https://github.com/appcelerator/titanium_mobile/tree/master/iphone/TitaniumKit
The current build steps for the framework are below
carthage build --archive
Once I imported it into the project I was able to use KrollCallback like this:
class SimplePayListener: NSObject, SimplePayEventListener {
let payEventListener: PayEventListener
init(payEventListener: PayEventListener) {
self.payEventListener = payEventListener
}
public func onPayEvent(payEvent_ payEvent: String) {
os_log("SimplePayListener event description = %{public}#", fivestarsPayEvent.description)
let appceleratorCallback:KrollCallback = self.payEventListener as! KrollCallback
appceleratorCallback.call([payEvent], thisObject: self.payEventListener)
}
}

use of abstract as enumerated type?

I am looking at the following Haxe source code from the "Pattern Matching - Array Matching" example at try.haxe.org -
class Test {
static function main() {
var playerA = {
name: "Simn",
move: Move.Paper
}
var playerB = {
name: "Nicolas",
move: Move.Rock
}
// a switch can directly return something
var winner = switch ([playerA.move, playerB.move]) {
case [Move.Rock, Move.Paper]: playerB;
case [Move.Scissors, Move.Paper]: playerA;
default: null;
}
if (winner != null) {
trace('The winner is: ${winner.name}');
} else {
trace('Draw!');
}
}
}
#:enum
abstract Move(Int) {
var Rock = 1;
var Paper = 2;
var Scissors = 3;
}
my questions are:
what does the notation #:enum signify?
Why did they create the enumerated type this way instead of simply doing:
enum Move
{
Rock;
Paper;
Scissors;
}
The #enum metadata informs the compiler to treat an abstract class as an enumeration. The main advantage is to be able to define values to each constant.
In the case of the example, the array [Move.Rock, Move.Paper] would be the same as [1,2] but the compiler will ensure that each value comes from the enum type.
You can find more here
http://haxe.org/manual/types-abstract-enum.html

Making a Swift class conform to a protocol that requires an init

I have the following protocol in Swift:
protocol FooConvertible{
typealias FooType
init(foo: FooType)
}
I can make Swift classes conform to it in the class definition:
class Bar: FooConvertible {
var baz: String = ""
required init(foo: String){
baz = foo
}
}
So far so good. However, the problem arises when I try to make a class conform to it in an extension (With Cocoa classes, it's my only option, as I don't have the source):
class Baz {
var baz = ""
}
extension Baz: FooConvertible{
required convenience init(foo: String) { // Insists that this should be in the class definition
baz = foo
}
}
extension NSURL: FooConvertible{
required convenience init(foo: String) { // this also fails for the same reason
}
}
This used to be possible, in previous versions of the language
What's the reason it was removed?
That would mean that all the XXXLiteralConvertible Protocols are banned from Cocoa classes!
Any chance you are trying to create something like this:
protocol FooConvertible : class {
typealias FooType
var baz : String { get set } // protocol extensions inits may need to know this
init(foo: FooType) // this is your designated initializer
}
extension FooConvertible {
// init(foo: String) {
// self.init(foo: foo)
// baz = foo
// }
// you can't do this because it could call it self recursively
init(num: Int) { // this init will call your designated init and can instantiate correctly
self.init(foo: "\(num)")
}
}
class Baz {
var baz = ""
}
class Bar: FooConvertible {
var baz: String = ""
required init(foo: String) { // designated initializer
baz = foo
}
}
Baz will now know about all inits of FooConvertible.
If so, I'm glad I could help. :)

Access objects inside another function

Essentially, I have one function wherein several objects have been created, and another function where I am trying to access these objects. As seen below:
func createButtons() {
var myButton01 = BigButton.createbutton()
var myButton02 = BigButton.createbutton()
}
As you can see I am trying to access the objects to pair them up with keys in a dictionary.
func setupConstraints() {
var myButtonDictionary = ["myButton01": myButton01, "myButton02": myButton02]
...
}
How would I go about making them accessible without having to move the second function into the first function. Is there any way to make the objects accessible to other functions?
Make myButton01 and myButton02 properties of the class you're working in, or if there is no class, just put the variables outside the functions.
This is how you would do it if there was no class:
var myButton01: BigButton? = nil
var myButton02: BigButton? = nil
func createButtons() {
var myButton01 = BigButton.createbutton()
var myButton02 = BigButton.createbutton()
}
func setupConstraints() {
var myButtonDictionary = ["myButton01": myButton01!, "myButton02": myButton02!]
...
}
Typically you would have these functions in some other construct, like a class and those objects would be instance variables.
class BigButton {
class func createButton() -> BigButton {
return BigButton()
}
}
class Foo {
var myButton01: BigButton?
var myButton02: BigButton?
func createButtons() {
myButton01 = BigButton.createButton()
myButton02 = BigButton.createButton()
}
func setupConstraints() {
var myButtonDictionary = ["myButton01": myButton01, "myButton02": myButton02]
}
}

Class variables not yet supported

I begin my project with a split view controller as initial view controller and start it automatically from storyboard.
Generally, an app with this UI have one and only one split view controller as root, so I create a static variable in the subclass and set it when initialisation was done.
So I want try this behaviour with swift.
I read the Swift programming language guide book on iBook about Type properties (with static and class keyword) and trying a piece of code to the job:
import UIKit
class SplitViewController: UISplitViewController {
class func sharedInstance() -> SplitViewController {
return SplitViewController.instance
}
class let instance: SplitViewController = nil
init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
self.initialization()
}
init(coder aDecoder: NSCoder!) {
super.init(coder: aDecoder);
self.initialization()
}
func initialization() {
SplitViewController.instance = self;
}
}
but I figured out when Xcode say the class keyword for type properties wasn't supported yet.
Did you have a solution to do this ?
Embedding a struct can work just fine as a workaround:
class SomeClass
{
// class var classVariable: Int = 0
// "Class variables not yet supported." Weird.
// Workaround:
private struct SubStruct { static var staticVariable: Int = 0 }
class var workaroundClassVariable: Int
{
get { return SubStruct.staticVariable }
set { SubStruct.staticVariable = newValue }
}
}
The SomeClass.workaroundClassVariable computed type property can then be used as if it were a stored type property.
Swift now has support for static variables in classes. This is not exactly the same as a class variable (because they aren't inherited by subclasses), but it gets you pretty close:
class X {
static let y: Int = 4
static var x: Int = 4
}
println(X.x)
println(X.y)
X.x = 5
println(X.x)
It seems to be possible to declare variables with static storage duration in file scope (as in C):
var sharedInstance: SplitViewController? = nil
class SplitViewController: UISplitViewController {
....
func initialization() {
sharedInstance = self
}
}
My preferred method is to just use a private file scope var outside of the class and then implement class/static getters and setters:
private var _classVar: Int = 0;
class SomeClass
{
public class var classVar: Int
{
get { return _classVar }
set { _classVar = newValue }
}
}
As of Swift 1.2 (available with Xcode 6.3b1 and onwards), static class properties and methods are supported.
class SomeClass
{
static var someVariable: Int = 0
}
Using a dispatch_once singleton model in Swift
Seems to be the best answer so far, avoiding the use of a global variable.
A solution enough similar than var in file scope but more customisable and near singleton is to use a struct which support static var as property of class
struct PersonSharedData {
static var backstore = ""
var data: String {
get { return PersonSharedData.backstore }
set { PersonSharedData.backstore = newValue }
}
}
class Person {
var shared=PersonSharedData() //<< pseudo class var
var family: String {
get { return shared.data }
set { shared.data=newValue }
}
var firstname = ""
var lastname = ""
var sexe: Sexe = .Unknown
}
Ok, with the solution of Nikolai that do the work. I post my changes in this thread for information
var instance: SplitViewController? = nil
class SplitViewController: UISplitViewController {
class func sharedInstance() -> SplitViewController? {
return instance;
}
init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
self.initialization()
}
init(coder aDecoder: NSCoder!) {
super.init(coder: aDecoder);
self.initialization()
}
func initialization() {
instance = self
}
}
and for example, in my appDelegate, I can access this static method like this
SplitViewController.sharedInstance()!.presentsWithGesture = false
The wording in the error heavily implies this will be a language feature in the future.
You may want to resort temporarily to declaring a property variable in the Application Delegate and retrieve it from there. Not ideal, definitely an anti-pattern, but would give you a central place to retrieve the UISplitViewController when needed.
You have to wrap the class variables inside an inner struct variable
class Store{
var name:String
var address:String
var lat:Int
var long:Int
init(name:String, address:String, lat:Int, long:Int){
self.name = name
self.address = address
self.lat = lat
self.long=long
}
private struct FACTORY_INITIALIZED_FLAG { static var initialized: Bool = false
static var myStoreList:[Store]?
static func getMyStoreList()->[Store]{
if !initialized{
println("INITIALIZING")
myStoreList = [
Store(name: "Walmart", address: "abcd", lat: 10, long: 20),
Store(name: "JCPenny", address: "kjfnv", lat: 23, long: 34)
]
initialized = true
}
return myStoreList!
}
}
}
var a = Store.FACTORY_INITIALIZED_FLAG.getMyStoreList()
var b = Store.FACTORY_INITIALIZED_FLAG.getMyStoreList()
// only prints INITIALIZING once
Try this:
class var instance: SplitViewController {
return nil
}
It is called Type Property in Swift.
You define type properties with the static keyword. For computed type properties for class types, you can use the class keyword instead to allow subclasses to override the superclass’s implementation. The example below shows the syntax for stored and computed type properties:
struct SomeStructure {
static var storedTypeProperty = "Some value."
static var computedTypeProperty: Int {
return 1
}
}
enum SomeEnumeration {
static var storedTypeProperty = "Some value."
static var computedTypeProperty: Int {
return 6
}
}
class SomeClass {
static var storedTypeProperty = "Some value."
static var computedTypeProperty: Int {
return 27
}
class var overrideableComputedTypeProperty: Int {
return 107
}
}
Read more at link below,
https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Properties.html#//apple_ref/doc/uid/TP40014097-CH14-ID254

Resources