-
Notifications
You must be signed in to change notification settings - Fork 280
Block
As we know that OC block is a NSObject, and block is corresponding to WaxFunction in wax, so if we know the block's arguments type, we can structure the block.
In armv7/i386, arguments's address in stack is simple, and char,int,BOOL,pointer,id
can be treated as int
, so we can use variable arguments function to structure a block. (see wax_block_transfer.m) like:
- (LongLong (^)(int p, ...))luaBlockReturnLongLongWithFirstIntParamTypeEncoding:(NSString *)paramsTypeEncoding{
return [[^LongLong(int q, ...){
LUA_BLOCK_CALL_ARM32_RETURN_BUFFER(paramsTypeEncoding, LongLong, q);
} copy] autorelease];
}
In arm64/x86_64, things become harder, but some we treat char,int,BOOL,pointer,id,long
as longlong, and treat float,double
as double, so can generate a block pool with 510 functions to support block with maximum 7 different kind arguments(is't enough?). (see wax_block_transfer_pool.m)
- you can use
toblock(luaFunction, typeArray)
to convert Lua function to OC block. The first item in typeArray must be the return value type(except block that return void and no arguments). (toblock is package of luaBlockWithParamsTypeArray, see lib/stdlib/ext/block.lua) - void block, return void block
UIView:animateWithDuration_animations_completion(1,
toblock(
function()
label:setCenter(CGPoint(300, 300))
end
),
toblock(
function(finished)
print('lua animations completion ' .. tostring(finished))
end
,{"void", "BOOL"})-- return void
)
- (void)testReturnIdWithFirstIdBlock:(id(^)(id aFirstId, BOOL aBOOL, int aInt, NSInteger aInteger, float aFloat, CGFloat aCGFloat, id aId))block
local res = self:testReturnIdWithFirstIdBlock(
toblock(
function(aFirstId, aBOOL, aInt, aInteger, aFloat, aCGFloat, aId)
print("lua aFirstInt")
return "123"
end
, {"id", "id", "BOOL", "int", "NSInteger" , "float" , "CGFloat" , "id" })
)
- avoid retain cycle use block just once
--OC block void (^)(UIViewController * sourceViewController, UIWebView * webView);
local weakSelf = self--temp self
self:setMyblock(
toblock(
function(sourceViewController, webView)
-- print("lua sourceViewController")
print(string.format("lua sourceViewController=%s webView=%s self.price=%s", tostring(sourceViewController), tostring(webView), tostring(weakSelf:price())))
weakSelf = nil--make it empty
end
, {"void", "id", "id"})
)
use block more than once
local weak = {}
b = {__mode = "v"}
setmetatable(weak, b)
weak.self = self
toblock(
function(sourceViewController, webView)
-- print("lua sourceViewController")
print(string.format("lua sourceViewController=%s webView=%s self.price=%s", tostring(sourceViewController), tostring(webView), tostring(weakSelf:price())))
weak.self:xxx()
end
), {"void", "id", "id"})
)
more example in AutoTest
call block like Lua function
--OC block void (^)())block
block()
--or call it like this
luaCallBlockWithParamsTypeArray(block, {"void"});
--OC block void (^)(NSString * code, NSDictionary * responseData))response
block("abcd", {k1="v1", k2="v2"})
--or call it like this
luaCallBlockWithParamsTypeArray(block, {"void","id", "id"}, str, {k1="v1", k2="v2"})
--OC block CGFloat(^)(CGFloat aFirstCGFloat, BOOL aBOOL, int aInt, NSInteger aInteger, float aFloat, CGFloat aCGFloat, id aId))block
local res = block(TEST_VALUE_CGFLOAT, TEST_VALUE_BOOL, TEST_VALUE_INTEGER,TEST_VALUE_CGFLOAT)
--or call it like this
local res = luaCallBlockWithParamsTypeArray(block, {"CGFloat","CGFloat", "BOOL", "NSInteger", "CGFloat"}, TEST_VALUE_CGFLOAT, TEST_VALUE_BOOL, TEST_VALUE_INTEGER,TEST_VALUE_CGFLOAT)
Q:When should use luaCallBlockWithParamsTypeArray
?
A:when you want to call a block that is got by toblock
local blockGotBytoblock = toblock(
function(code, responseData)
print("lua code=" .. code .. " responseData=" .. tostring(responseData))
end
, {"void", "NSString *", "NSDictionary *"})
luaCallBlockWithParamsTypeArray(blockGotBytoblock, {"void", "NSString *", "NSDictionary *"},
"abc", {k1="v1", k2="v2"})
if you want to write OC code like this:
UIView *view = [UIView new];
[self.view addSubview:view];
view.backgroundColor = [UIColor greenColor];
[view mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.view).offset(200);
make.left.equalTo(self.view).offset(50);
make.width.offset(10);
make.height.offset(10);
}];
then the Lua code is
local view = UIView:init()
self:view():addSubview(view)
view:setBackgroundColor(UIColor:greenColor())
view:masUNDERxLINEmakeConstraints(toblock(
function ( make )
make:top():equalTo()(self:view()):offset()(200);
make:left():equalTo()(self:view()):offset()(50);
make:width():offset()(10);
make:height():offset()(10);
end
,{"void", "MASConstraintMaker *"}))
Attention: you can't write equalTo(self:view()) or offset(200)
, because equalTo
, offset
is not a method which accept arguments, it's a method that returns a block!
more example in AutoTest