flex: referencing class variables - apache-flex

I have a bunch of variables in a class. There are situations when I want to set then to null/ "temp" etc as per a well defined logic. The challenge is to list out the variables at multiple places- tedious and error-prone.
classname.speed=NaN
classname.speedtype="not_set"
classname.distance=NaN
classname.distancetype="not_set"
Ideally, would prefer a way to refer to these variables programatically and set something like
"for all class variables- if variable ends in type, set as "not_set"; for other variables set as NaN
How can I achieve this? Any pointers will help

The simplest approach would be just write function to clear them all.
If you want something more automatic, it will requre efforts - look at introspection api. Basically, you call describeType on your class and it returns XML description. All variables will be listed there, along with other info. Then you can parse returned XML and set all variables to needed value, accessing them dynamically with square bracket syntax:
var myClass:MyClass = new MyClass();
myClass["varName"] = "new value";

It can be achieved through Inheritance i.e. implementing interface or extending class
which contains common fields
public class MyClass
{
public a:String = null;
public b:String = null;
public function MyClass()
{
}
}
which contains common var and Child Class could be
public class MyClassChild extends MyClass
{
public var c:String = null;
public function MyClassChild()
{
super();
this.a ="";
this.b ="";
}
}
and you can cast or use for each loop to set values
var temp:MyClassChild = new MyClassChild ();
MyClass(temp).a = "Hello World";
Hopes that helps

Related

Share data in paged based interface in Watchkit

I need to share a string with all the pages from the first page.
I was trying to do this with didDeactive() but its not working.
Is it possible to even do this?
It's a bit difficult to tell what you are really trying to do, so I'm going to infer a bit. I "think" you are trying to set some shared value from the first page and be able to use that value in other pages. If that's the case, then you could do something like the following:
class SharedData {
var value1 = "some initial value"
var value2 = "some other initial value"
class var sharedInstance: SharedData {
struct Singleton { static let instance = SharedData() }
return Singleton.instance
}
private init() {
// No-op
}
}
class Page1InterfaceController: WKInterfaceController {
func buttonTapped() {
SharedData.sharedInstance.value1 = "Something new that the others care about"
}
}
class Page2InterfaceController: WKInterfaceController {
#IBOutlet var label: WKInterfaceLabel!
override func willActivate() {
super.willActivate()
self.label.setText(SharedData.sharedInstance.value1)
}
}
The SharedData object is a singleton class that is a global object. Anyone can access it from anywhere. In the small example I provided, the Page1InterfaceController is handling a buttonTapped event and changing the value property of the SharedData instance to a new value. Then, when swiping to Page2InterfaceController, the new value is being displayed in label.
This is a super simple example of sharing data between objects. Hopefully that helps get you moving in the right direction.

Flex combo box labelfunction

I have two questions regarding the Flex combo box.
The string representing the function name will be read from xml # run time.
var combo:ComboBox = new ComboBox();
combo.labelFunction = "functionName";
How can I achieve this?
So the first name, which is to be displayed in the combo box, can be only retrieved by accessing another DTO, called person and then its first name.
var combo:ComboBox = new ComboBox();
combo.labelField= "person.firstName";
My class looks like this,
public class Test
{
public var person:PersonDTO;
}
public class PersonDTO
{
public var firstName:String;
}
Is it possible to access any multi-level text using the combo box label field ?
You need to pass the function not the name.
Doing this
combo.labelFunction = "functionName";
Is passing a string.
The only work around I can think of is to make a switch statement with one case for each function you may have. Then call that with "case" from within your xml.
switch( xml.#labelfunction ){
case 'func1':
combo.labelFunction = this.func1;
break;
case 'func2':
combo.labelFunction = this.func2;
break;
}
Its hacky but should work.
ad 1) labelFunction
Calling functions when you know only the name as String is quite easy. The following snippets shows how you can execute a function that is a member of the same class. In case you need to call a function from another class replace this with the according variable name.
private function comboBox_labelFunction(item:Object):String
{
var functionName:String = myXml.#labelFunctionName;
return this[functionName](item);
}
ad 2) labelField
It's normally not possible to use "person.firstName" as labelField. However, you should be able use it within your labelFunction. Something like this should work...
private function comboBox_labelFunction(item:Object):String
{
var labelField:String = "person.firstName";
var attributeNames:Array = labelField.split(".");
for each (var attributeName:String in attributeNames)
{
if (item && item.hasOwnProperty(attributeName))
item = item[attributeName];
else
return null;
}
return item;
}

Having a issue casting a object from an ArrayCollection to an instance of my Custom Class

I am using Flex 4 and for whatever reason I cannot get the following code to work which happens inside of a ListEvent handler for a dataGrid:
_tempRule = DataGrid(event.currentTarget).selectedItem as Rule;
Rule is a custom class, and the above code always returns null. The dataprovider for the datagrid is an ArrayCollection. If I try to wrap the above code to make it like the following:
DataGrid(event.currentTarget).selectedItem as Rule
I get this error:
TypeError: Error #1034: Type Coercion failed: cannot convert Object#e15a971 to com.mycompany.arcc.business.Rule
Now I know I have done this before with native Flex classes like Button, etc, but it my case it will not work.
Here is the Rule class:
package com.mycompaany.arcc.business
{
import flash.utils.describeType;
import mx.collections.ArrayCollection;
[Bindable]
public class Rule extends Object
{
public static const RANGE:String = "Range";
public static const SINGLE:String = "Single";
public static const LIST:String = "List";
/*name of the rule*/
private var _name:String;
/*rule group, like a radio group, only 1 rule from a group can be selected*/
private var _group:String;
/*Description of the group for the rule*/
private var _groupDescription:String;
/*Description of the rule*/
private var _description:String;
/*arry of values for this rule, based on the control type*/
private var _values:ArrayCollection;
/*min num of values*/
private var _numValues:int;
/*type of control to build, if range, 2 inputs, single, 1 , list 1 or more*/
private var _type:String;
public function Rule(name:String=null, group:String=null, description:String=null, values:ArrayCollection=null, numValues:int=0, type:String=null)
{
super();
_values = new ArrayCollection();
this._name = name
this._group = group;
this._description = description;
if (values)
{
this._values = values;
}
this._numValues = numValues;
this._type = type;
}
}
}
So what am I missing?
The quick and easy solution was to add the [RemoteClass] metatag at the top my custom class.
I found this solution on Adobe's website, livedocs.adobe.com/flex/3/html/…. It seems that using the native drag and drop capabilities between list-based components causes custom classes to lose their type during copying. Thanks to everyone for the assistance.
the errormessage is the result of an failed casting.
The better way is to use the cast like this,
Rule((event.currentTarget).selectedItem);
In this case, you will receive an exception, when the cast fails and not a null reference
BR
Frank

Returning different sub-classes from a function?

Say I have four sub-classes of 'Car'. One for each color. I want to have one function that can build and return a 'color-car' sub-class based on the passed value. This is a dumb example, I know, but it is precisely what I am trying to do only on a smaller scale.
public class Car
{
}
public class BlueCar extends Car
{
}
You get it.
Then, in another (helper) class, I have a function which takes in a string of the color and returns the correct sub-class.
public function GetCarFromColor(_color:String):Car
{
if (_color == "blue")
{
var myCar:BlueCar = new BlueCar;
return myCar;
} else if (_color == "red")
{
var myCar:RedCar = new RedCar;
return myCar;
}
Ok. You get it. This doesn't work for a reason unknown to me. I get 1118 errors which complain about conversion of BlueCar into Car, etc...
Can someone help me out here? Thanks!
Make the return variable to be of the supertype:
public function GetCarFromColor(_color:String):Car
{
var myCar:Car
if (_color == "blue")
{
myCar = new BlueCar;
return myCar;
} else if (_color == "red")
{
myCar = new RedCar;
return myCar;
}
This should now compile ok.
You should try casting your derived class to the base class before returning it back.
Not sure about actionscript but in C++ you could do it like this
Base *GetCarFromColor()
{
Base *b1;
b1 = new D1;
return b1;
}
Maybe you should use an interface instead?
public interface ICar
{
}
public class BlueCar implements ICar
{
}
public function GetCarFromColor(_color:String):ICar
{
}
The reason you were getting errors is because you have two local variables of the same name with different types in one function:
var myCar:BlueCar = new BlueCar;
var myCar:RedCar = new RedCar;
The variable myCar is typed as both BlueCar and RedCar. In ActionScript 3, variables are always scoped to the entire function. In other languages, like Java, I know that if statements and loops create a new block-level scope, but that's not the case here.
As Matt Allen suggested, typing myCar as the superclass, Car, should stop these compiler errors.

Is it possible to define a generic type Vector in Actionsctipt 3?

Hi i need to make a VectorIterator, so i need to accept a Vector with any type. I am currently trying to define the type as * like so:
var collection:Vector.<*> = new Vector<*>()
But the compiler is complaining that the type "is not a compile time constant". i know a bug exists with the Vector class where the error reporting, reports the wrong type as missing, for example:
var collection:Vector.<Sprite> = new Vector.<Sprite>()
if Sprite was not imported, the compiler would complain that it cannot find the Vector class. I wonder if this is related?
So it looks like the answer is there is no way to implicitly cast a Vector of a type to valid super type. It must be performed explicitly with the global Vector.<> function.
So my actual problem was a mix of problems :)
It is correct to use Vector. as a generic reference to another Vector, but, it cannot be performed like this:
var spriteList:Vector.<Sprite> = new Vector.<Sprite>()
var genericList:Vector.<Object> = new Vector.<Object>()
genericList = spriteList // this will cause a type casting error
The assignment should be performed using the global Vector() function/cast like so:
var spriteList:Vector.<Sprite> = new Vector.<Sprite>()
var genericList:Vector.<Object> = new Vector.<Object>()
genericList = Vector.<Object>(spriteList)
It was a simple case of me not reading the documentation.
Below is some test code, I would expect the Vector. to cast implicitly to Vector.<*>.
public class VectorTest extends Sprite
{
public function VectorTest()
{
// works, due to <*> being strictly the same type as the collection in VectorContainer
var collection:Vector.<*> = new Vector.<String>()
// compiler complains about implicit conversion of <String> to <*>
var collection:Vector.<String> = new Vector.<String>()
collection.push("One")
collection.push("Two")
collection.push("Three")
for each (var eachNumber:String in collection)
{
trace("eachNumber: " + eachNumber)
}
var vectorContainer:VectorContainer = new VectorContainer(collection)
while(vectorContainer.hasNext())
{
trace(vectorContainer.next)
}
}
}
public class VectorContainer
{
private var _collection:Vector.<*>
private var _index:int = 0
public function VectorContainer(collection:Vector.<*>)
{
_collection = collection
}
public function hasNext():Boolean
{
return _index < _collection.length
}
public function get next():*
{
return _collection[_index++]
}
}
[Bindable]
public var selectedItems:Vector.<Category>;
public function selectionChange(items:Vector.<Object>):void
{
selectedItems = Vector.<Category>(items);
}
I believe you can refer to an untyped Vector by just calling it Vector (no .<>)
With Apache Flex 4.11.0, you can already do what you want. It might have been there since 4.9.0, but I have not tried that before.
var collection:Vector.<Object> = new Vector.<Object>()
maybe?
But i'm just speculating, haven't tried it.
var collection:Vector.<Object> = new Vector.<Object>()
but only on targeting flash player 10 cs4

Resources