How can I replace class_createInstance in arc? - xcode4

I have this code and need to port it to arc but I dont know how:
case FIELDTYPE_OBJECT:
className = [fieldType substringWithRange:NSMakeRange(2, [fieldType length]-3)];
rel = class_createInstance(NSClassFromString(className), sizeof(unsigned));
Class theClass = [rel class];
if ([rel isKindOfClass:[DbObject class]]) {
//Load the record...
NSInteger Id = [rs intForColumn:[theClass relationName]];
if (Id==0) {
fieldValue = [rel init];
} else {
Db *db = [Db currentDb];
fieldValue = [db loadById: theClass theId:Id];
}
}
break;
The error is:
error: 'class_createInstance' is unavailable: not available in automatic reference counting mode
How replace it?
I need to build class objects in runtime.

The most straightforward solution is to add another file which has -fno-objc-arc set on it, and which has a function which calls class_createInstance() as above.

Try this:
#include <objc/objc-runtime.h>
id object = [[NSClassFromString(#"TheClassName") alloc] init];

Create a separated .h/.c files and put something like this.
id const
MyCreateInstanceOfClass(Class const class)
{
id instance = class_createInstance(class, 0);
return instance;
}
#include the .h, and call it. No need to put -fno-bjc-arc switch for each file.

Related

Check if QAction is initialized

I have in my header file the definition:
QAction actionPlay;
In my cpp file I have a function:
myFunc()
{
actionPlay = new QAction();
}
I want to make a change in my UI only the first time I enter the function myFunc().
I thought about checking if actionPlay has been initialized or not (if we have already called the line actionPlay = new QAction(); )
How can I do this ?
Thanks
The line:
actionPlay = new QAction()
is attempting to assign a pointer to a non pointer variable declared in
QAction actionPlay
so wont works as is.
If you changed the code to:
QAction * actionPlay = 0;
It would work, and you could then check if it was initialized:
if(!actionPlay) actionPlay = new QAction();
If you want to init action for every object:
QACtion *actionPay = nullptr; // *.h file
if(!actionPay) { actionPay = new QAction(); ..... } // *.cpp file
or don't use pointer
if(!actionPay.isEnabled()) { ... enable actionPay ...} // *.cpp file
if you want do one action:
//in your function *.cpp file
static bool once = true;
if(once) {
once = false;
... some code executed in the first call ...
}

NSInvocation invoke giving bad access in iOS 8

I'm trying to run this code in iOS 8 but I'm getting a bad access error in the method called, this runs ok in iOS 7. Does anyone has a clue about this?
-(double) calcularColumna:(int ) anio :(int) mes :(NSString * ) columna {
NSInvocation * invocation = [selectores objectForKey:columna];
if(!invocation){
NSString * metodo = [NSString stringWithFormat:#"fondo%#:anio:mes:",columna];
SEL selector = NSSelectorFromString(metodo);
if( ![self respondsToSelector:selector]) {
return -1;
}
invocation = [NSInvocation invocationWithMethodSignature:[[self class] instanceMethodSignatureForSelector:selector]];
invocation.selector = selector;
invocation.target = self;
[invocation setArgument:(__bridge void *)(self.valoresEntrada) atIndex:2];
[selectores setObject:invocation forKey:columna];
}
double valor = 0;
[invocation setArgument:&anio atIndex:3];
[invocation setArgument:&mes atIndex:4];
[invocation invoke];
[invocation getReturnValue:&valor];
/* }else {
valor = -1;
}*/
return valor;
}
Thanks for your comments.
[invocation setArgument:(__bridge void *)(self.valoresEntrada) atIndex:2];
is wrong. You need to pass a pointer to the value being passed. Something like
// I don't know the type of self.valoresEntrada, but you can use the type directly
typeof(self.valoresEntrada) temp = self.valoresEntrada;
[invocation setArgument:&temp atIndex:2];
Also, if you are going to store the invocation in a collection for use after the scope where it's created, you need to do [invocation retainArguments];
p.s. [[self class] instanceMethodSignatureForSelector:selector] can be written as [self methodSignatureForSelector:selector]
p.p.s. If the method signature is known and fixed at compile-time, you can use objc_msgSend directly, if you are brave.

Qt: How to delete locally created multiple QIntValidator pointer object implemented on QlineEdit?

As per the Title, How to delete mulitple QIntValidator pointer Object created locally.I am stuck with an issue of memory leak.
I have a function as below:
void ABC::setTableDataItems(QStringList headerData)
{
int row = headerData.size();
int column = 0;
if (_txtLineEdit != NULL) {
delete _txtLineEdit;
_txtLineEdit = 0;
}
for (int i = 0; i < row ; i++)
{
_txtLineEdit = new QLineEdit();
_txtLineEdit->setMaxLength(_pktStruct[i].ItemDataLength);
_txtLineEdit->setText(headerData.at(i));
_pktStruct[i].currentLine = _txtLineEdit;
QString regExp = "[01]{1,";
regExp.append(QString("%1").arg(_pktStruct[i].ItemDataLength)).append("}");
long maxDigit = getMaxValueForDigit( _pktStruct[i].ItemDataLength );
QIntValidator* decValidator = new QIntValidator( 0, maxDigit, _txtLineEdit );
QRegExpValidator* binValidator = new QRegExpValidator(QRegExp(regExp),_txtLineEdit);
switch (_pktStruct[i].ItemDataType)
{
case DATA_TYPE_ASCII:
break;
case DATA_TYPE_HEX:
break;
case DATA_TYPE_NUM:
_txtLineEdit->setValidator(decValidator);
break;
case DATA_TYPE_BINARY:
_txtLineEdit->setValidator(binValidator);
break;
case DATA_TYPE_MAX:
break;
}
ui->pcusim_cmd_task_tableWidget->setCellWidget(i, column, _txtLineEdit);
connect(_txtLineEdit, SIGNAL(textChanged(QString)), this, SLOT(on_pcusim_cmd_task_tableWidget_linedit_cellChanged(QString)));
}
}
In above function, I need to delete all multiple QIntValidator created dynamically (inside For Loop ) every time before the loop when the above function is called.
Don't know the way. Please give some suggestions / idea to proceed further ??
Thanks in advance
Why don't you do
QValidator* pValidator = NULL;
switch (_pktStruct[i].ItemDataType)
{
case DATA_TYPE_NUM:
// create the proper int validator here
// ...
pValidator = new QIntValidator(0, maxDigit, _txtLineEdit);
break;
case DATA_TYPE_BINARY:
// create the proper regexp validator here
// ...
pValidator = new QRegExpValidator(QRegExp(regExp),_txtLineEdit);
break;
}
_txtLineEdit->setValidator(pValidator);
That way you don't create validators that are not used.
Since you pass _txtLineEdit as parent on construction of validators, they will be deleted when their parent QLineEdit object is destroyed.
By the way, setCellWidget() takes ownership of the widget, so you don't need to delete _txtLineEdit; (assuming this is the one you passed to it, you should have created a list of them in this case)

X++ passing current selected records in a form for your report

I am trying to make this question sound as clear as possible.
Basically, I have created a report, and it now exists as a menuitem button so that the report can run off the form.
What I would like to do, is be able to multi-select records, then when I click on my button to run my report, the current selected records are passed into the dialog form (filter screen) that appears.
I have tried to do this using the same methods as with the SaleLinesEdit form, but had no success.
If anyone could point me in the right direction I would greatly appreciate it.
Take a look at Axaptapedia passing values between forms. This should help you. You will probably have to modify your report to use a form for the dialog rather than using the base dialog methods of the report Here is a good place to start with that!
Just wanted to add this
You can use the MuliSelectionHelper class to do this very simply:
MultiSelectionHelper selection = MultiSelectionHelper::createFromCaller(_args.caller());
MyTable myTable = selection.getFirst();
while (myTable)
{
//do something
myTable = selection.getNext();
}
Here is the resolution I used for this issue;
Two methods on the report so that when fields are multi-selected on forms, the values are passed to the filter dialog;
private void setQueryRange(Common _common)
{
FormDataSource fds;
LogisticsControlTable logisticsTable;
QueryBuildDataSource qbdsLogisticsTable;
QueryBuildRange qbrLogisticsId;
str rangeLogId;
set logIdSet = new Set(Types::String);
str addRange(str _range, str _value, QueryBuildDataSource _qbds, int _fieldNum, Set _set = null)
{
str ret = _range;
QueryBuildRange qbr;
;
if(_set && _set.in(_Value))
{
return ret;
}
if(strLen(ret) + strLen(_value) + 1 > 255)
{
qbr = _qbds.addRange(_fieldNum);
qbr.value(ret);
ret = '';
}
if(ret)
{
ret += ',';
}
if(_set)
{
_set.add(_value);
}
ret += _value;
return ret;
}
;
switch(_common.TableId)
{
case tableNum(LogisticsControlTable):
qbdsLogisticsTable = element.query().dataSourceTable(tableNum(LogisticsControlTable));
qbrLogisticsId = qbdsLogisticsTable.addRange(fieldNum(LogisticsControlTable, LogisticsId));
fds = _common.dataSource();
for(logisticsTable = fds.getFirst(true) ? fds.getFirst(true) : _common;
logisticsTable;
logisticsTable = fds.getNext())
{
rangeLogId = addrange(rangeLogId, logisticsTable.LogisticsId, qbdsLogisticsTable, fieldNum(LogisticsControlTable, LogisticsId),logIdSet);
}
qbrLogisticsId.value(rangeLogId);
break;
}
}
// This set the query and gets the values passing them to the range i.e. "SO0001, SO0002, SO000£...
The second methods is as follows;
private void setQueryEnableDS()
{
Query queryLocal = element.query();
;
}
Also on the init method this is required;
public void init()
{
;
super();
if(element.args() && element.args().dataset())
{
this.setQueryRange(element.args().record());
}
}
Hope this helps in the future for anyone else who has the issue I had.

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