My logic of performSelectorOnMainThread:withObject:waitUntilDone: - objective-c

This code here is js-ctypes. The code is crashing and I think it's to my misunderstanding of reading about doing stuff on the main thread from other threads.
My end goal is to set a window always on top from a secondary thread, so I have to run performSelectorOnMainThread:withObject:waitUntilDone:
What I am doing is:
Create a class named setWinAlwaysOnTop_class with objc_allocateClassPair
Write my methods in javascript and convert to C (currently i wrote them to just log to console but after I get it working ill update to do NSWindow stuff)
Register unique selector name for my method with sel_registerName
Use class_addMethod to add my C methods from step 2 to class from step 1
objc_registerClassPair on the class from step 1
Allocation my class with alloc
Create instance of class with init
Do performSelectorOnMainThread:withObject:waitUntilDone: on my instance of class created in step 7 with first argument being the unique selector name from step 3, setting 2nd arg withObject to nil, and final arg waitUntilDone to YES
Is this logic correct? And my crash is not due to my logic? Code is below:
var NSObject = ostypes.HELPER.class('NSObject');
if (!OSStuff.setWinAlwaysOnTop_class) {
throw new Error('setWinAlwaysOnTop_class was not previously cleaned up!!')
}
var needsRegistration = true;
OSStuff.setWinAlwaysOnTop_class = ostypes.API('objc_allocateClassPair')(NSObject, 'setWinAlwaysOnTop_class', 0);
if (OSStuff.setWinAlwaysOnTop_class.isNull()) {
console.info('setWinAlwaysOnTop_class:', class_NoitOnScrnSvrDelgt.toString());
throw new Error('setWinAlwaysOnTop_class is null, so objc_allocateClassPair failed');
}
OSStuff.setWinAlwaysOnTop_jsMethods = {}; // holds key of aArrHwndPtrStr and value is js method
var IMP_for_mainThreadSelector = ctypes.FunctionType(ctypes.default_abi, ctypes.void_t, []);
OSStuff.setWinAlwaysOnTop_jsMethods[aArrHwndPtrStr[0]] = function() {
console.log('setWinAlwaysOnTop_jsMethods ' + 0 + ' called');
};
OSStuff.setWinAlwaysOnTop_cMethods = {};
OSStuff.setWinAlwaysOnTop_cMethods[aArrHwndPtrStr[0]] = IMP_for_mainThreadSelector.ptr(OSStuff.setWinAlwaysOnTop_jsMethods[aArrHwndPtrStr[0]]);
OSStuff.setWinAlwaysOnTop_methodSelectors = {};
OSStuff.setWinAlwaysOnTop_methodSelectors[aArrHwndPtrStr[0]] = ostypes.API('sel_registerName')(aArrHwndPtrStr[0]);
var rez_class_addMethod = ostypes.API('class_addMethod')(OSStuff.setWinAlwaysOnTop_class, OSStuff.setWinAlwaysOnTop_methodSelectors[aArrHwndPtrStr[0]], OSStuff.setWinAlwaysOnTop_cMethods[aArrHwndPtrStr[0]], 'v');
if (needsRegistration) {
ostypes.API('objc_registerClassPair')(OSStuff.setWinAlwaysOnTop_class);
OSStuff.setWinAlwaysOnTop_allocation = ostypes.API('objc_msgSend')(OSStuff.setWinAlwaysOnTop_class, ostypes.HELPER.sel('alloc'));
OSStuff.setWinAlwaysOnTop_instance = ostypes.API('objc_msgSend')(OSStuff.setWinAlwaysOnTop_allocation, ostypes.HELPER.sel('init'));
}
var rez_perform = ostypes.API('objc_msgSend')(OSStuff.setWinAlwaysOnTop_instance, ostypes.HELPER.sel('performSelectorOnMainThread:withObject:waitUntilDone:'), ostypes.HELPER.sel(aArrHwndPtrStr[0]), ostypes.CONST.NIL, ostypes.CONST.YES);
console.error('perform done!!');

Related

Writing a test class for Salesforce/APEX trigger

I have written down trigger in Salesforce APEX . It is working properly.
Code For Trigger is:
trigger SDRDemoUpdate_test on Event (before update) {
Map<ID,Event> records = New Map<ID,Event>([SELECT CreatedBy.Name FROM Event WHERE ID IN: trigger.new]);
for (Event obj :Trigger.new){
obj.SDR_Original_Demo__c = records.get(obj.id).CreatedBy.Name;
}
}
Now I am trying to write code for its test class. It is giving error on line saying object can not be parsed to String.
Code For Test Class is:
#isTest
public class originalDemo {
static testMethod void test_original_demo() {
Event obj = new Event();
obj.CreatedBy = 'Tom';
obj.Owner = 'Jack';
obj.What = 'Opportunity';
insert.obj;
userInfo.getName();
}
}
Looking forward to find out the solution. Any help would be appreciated.
Thanks
Your issue in these lines
obj.CreatedBy = 'Tom';
obj.Owner = 'Jack';
obj.What = 'Opportunity';
You tried to pass String to fields which required Id.
User user = [SELECT Id FROM User LIMIT 1];
obj.CreatedById = UserInfo.getUserId();
obj.OwnerId = user.Id;
obj.WhatId = opportunity.Id;

Small AS2 OOP Issue

I'm working with Actionscript 2 (not ready to upgrade yet, although it's irreverent to the problem) but I'm having trouble with OOP and classes.
I've got a "Tool" class, written like so:
class com.Tool {
public var self:MovieClip;
private static var Type:String;
function Tool(T:String, X:Number, Y:Number) {
Type = T;
self = _root.createEmptyMovieClip("obj"+_root.getNextHighestDepth(), _root.getNextHighestDepth());
self._x = X;
self._y = Y;
self.width = 36;
self.height = 36;
self.onRollOver = function() {
trace(Type);
}
}
}
I create 3 of them in the main script like so:
var toolPan:Tool = new Tool("pan", 0, 0);
var toolSquare:Tool = new Tool("square", 0, 38);
var toolLine:Tool = new Tool("line", 0, 76);
It all works great, except the onRollOver. It's supposed to output the unique "Type" string, but it always outputs "line" (the last Type Tool created) regardless which one I roll over.
Needless to say, I'm still a beginner to all this. But it seems like they're all sharing the same variable :/ How do I make these variables unique to each object created?
Thank you very much!
It's because it's type static, so the value is shared by all instances of that class. Remove it and it should work.
private var Type:String;

lua_touserdata is returning null

I am badly stuck trying to get my userInfo reference. One of my method is returning instance of the object. Everytime createUserInfo is called, it will return the userInfoObject to the lua.
However, when I call a method for userInfo object from Lua, I am not able to get the reference of the userInfo object (lua_touserdata(L,1))
static int getUserName (lua_State *L){
UserInfo **userInfo = (UserInfo**)lua_touserdata(L,1);
// The following is throwing null! Need help.
// Not able to access the userInfo object.
NSLog(#"UserInfo Object: %#", *userInfo);
}
static const luaL_reg userInstance_methods[] = {
{"getUserName", getUserName},
{NULL, NULL}
}
int createUserInfo(lua_State *L){
UserInfo *userInfo = [[UserInfo alloc] init];
UserInfoData **userInfoData = (UserInfoData **)lua_newuserdata(L, sizeof(userInfo*));
*userInfoData = userInfo;
luaL_openlib(L, "userInstance", userInstance_methods, 0);
luaL_getmetatable(L, "userInfoMeta");
lua_setmetatable(L, -2);
return 1;
}
// I have binded newUserInfo to the createUserInfo method.
// I have also created the metatable for this userInfo Object in the init method.
// luaL_newmetatable(L, "userInfoMeta");
// lua_pushstring(L, "__index");
// lua_pushvalue(L, -2);
// lua_settable(L, -3);
// luaL_register(L, NULL, userInstance_methods);
Please let me know if I am missing anything!
My LuaCode snippet:
local library = require('plugin.user')
local userInfo = library.newUserInfo()
print(userInfo.getUserName())
Update
I got rid of null, after using lua_upvalueindex(1) This is giving reference back to the user info instance.
UserInfo **userInfo = (UserInfo**)lua_touserdata(L,lua_upvalueindex( 1 ));
Hope it helps others too!
I think it may be the way your dealing with the userdata's metatable. Specifically, I think what you're returning from createUserInfo() is a table not a userdata. What I suggest is that you create the metatable once e.g. in luaopen, and then just set that on the new userdata. Something like this...
int createUserInfo(lua_State *L) {
UserInfo *userInfo = [[UserInfo alloc] init];
UserInfoData **userInfoData = (UserInfoData **)lua_newuserdata(L, sizeof(userInfo));
*userInfoData = userInfo;
luaL_getmetatable(L, "userInfoMeta");
lua_setmetatable(L, -2);
return 1;
}
LUALIB_API int luaopen_XXX(lua_State *L)
{
luaL_newmetatable(L,"userInfoMeta");
luaL_openlib(L, NULL, userInstance_methods, 0);
lua_pushvalue(L, -1);
lua_setfield(L, -2, "__index");
...
lua_upvalueindex(1) has fixed the nil error.
UserInfo **userInfo = (UserInfo**)lua_touserdata(L,lua_upvalueindex( 1 ));
I want to explain in brief on what is actually happening. function(s) in C will get stack of params passed to the method. Lua online document has example of an Array, where all of its methods take first parameter of array instance. so, lua_touserdata(L,1) worked fine as the first parameter is the array instance.
Example from lua.org shows
a = array.new(10) --size 10
array.insert(a, 1, 1) --array.insert(instance, index, value).
lua_touserdata(L,1) works as the first param is the array instance.
In my case, I was invoking the method over instance without any params. So, the lua stack was empty in my C function and lua_touserdata(L,1) was throwing null.
Example:
a = array.new(10)
a.showValues() --the method is not over array. it is called on instance.
So, inorder to get access to the instance in showValues, I need to call lua_touserdata(L, lua_upvalueindex(1)). This will give the array instance object.

Implement the same function in AS2 for an Array

I have an array, and I would like to make a function onRelease for all of the array positions.
The code would be like:
pick = new Array(2,3,4);
var botoes1:MovieClip = lev.attachMovie("block", "block_"+lev.getNextHighestDepth(), lev.getNextHighestDepth(), {_x:550, _y:1*22});
_root.botoes1.gotoAndStop(pick[1]);
var botoes2:MovieClip = lev.attachMovie("block", "block_"+lev.getNextHighestDepth(), lev.getNextHighestDepth(), {_x:550, _y:2*22});
_root.botoes2.gotoAndStop(pick[2]);
var botoes3:MovieClip = lev.attachMovie("block", "block_"+lev.getNextHighestDepth(), lev.getNextHighestDepth(), {_x:550, _y:3*22});
_root.botoes3.gotoAndStop(pick[3]);
for(i=0;i<3;i++){
_root['botoes'+i].onRelease() = Function () {
}
}
but it doesn't work this way...
and if possible, how can I make the MovieClip declaring for all the buttons in an for loop?
Couple syntax errors there, here's what this line should look like:
_root['botoes' + i].onRelease = function()
{
// Function body.
//
}
Your previous code was trying to assign the result of _root['botoes' + i].onRelease() (which would have been undefined) to the result of Function() (which would have been a Function object).

How do I mock this value using Rhino Mocks

Here is the method I'm trying to test:
public override void CalculateReductionOnYield()
{
log.LogEnter();
if (illus.RpFundStreams.Count <= 0)
{
throw new InvalidDataException("No regular premium fund streams which are required in order to calculate reduction on yield");
}
// Add the individual ReductionOnYield classes to the collection.)
foreach (RegularPremiumFundStream fs in illus.RpFundStreams)
{
foreach (int i in ReductionOnYieldMonths)
{
ReductionOnYield roy = new ReductionOnYield(i);
roy.FundStream = fs;
ReductionsOnYield.Add(roy);
}
foreach (ReductionOnYield redOnYield in ReductionsOnYield)
{
if (redOnYield.Month == 0 || illus.RegularPremiumInPlanCurrency == 0M)
{
redOnYield.Reduction = 0M;
}
else
{
double[] regPremiums = new double[redOnYield.Month + 1];
for (int i = 1; i <= redOnYield.Month; i++)
{
regPremiums[i - 1] = Convert.ToDouble(-1*redOnYield.FundStream.FundStreamMonths[i].ValRegularPremium);
}
regPremiums[redOnYield.Month] = Convert.ToDouble(redOnYield.FundStream.GetFundStreamValue(redOnYield.Month));
redOnYield.Reduction = Convert.ToDecimal(Math.Pow((1 + Financial.IRR(ref regPremiums, 0.001D)), 12) - 1);
}
}
}
How do I mock all the required classes to test the value of redOnYield.Reduction to make sure that it working properly?
e.g. how do I mock redOnYield.FundStream.GetFundStreamValue(redOnYield.Month) and redOnYield.FundStream.FundStreamMonths[i].ValRegularPremium ?
Is this a valid test? Or am I going about this the wrong way?
without more info on your objects its hard to say, but you want something like:
var fundStream = MockRepository.GenerateStub<TFundStream>();
fundStream.Stub(f => f.GetFundStreamValue(60)).Return(220000M);
var redOnYeild = MockRepository.GenerateStub<TRedOnYeild>();
redOnYeild.Stub(r => r.FundStream).Return(fundStream);
redOnYield is an object returned from iterating ReductionsOnYield. I don't see where this is coming from. If we assume it's a virtual property, then you'll want to create a collection of mock ReductionOnYield objects and stub out ReductionsOnYield to return your mocked collection (or, to make it easier to test, have CalculateReductionOnYield accept an IEnumerable and operate on that collection).
Once you get the ReductionsOnYield issue resolved, Andrew's response of stubbing out the properties will get you where you want to be. Of course, this assumes that FundStream is virtual (so it can be mocked/stubbed) as well as RegularPremiumFundStream's GetFundStreamValue and FundStreamMonths.