native 调用 web 没有 callback功能
sysuleiw opened this issue · 5 comments
sysuleiw commented
native 调用 web 没有 callback功能
sysuleiw commented
如题,今天clone了源码下来,没有找到对应入口,是没有还是我打开的姿势不对?
hite commented
@sysuleiw AppHost 现在内置的 Response 里是没有 callback 的例子,但是 js 端本身是支持的。native 端的 支持需要你自己写。
在实际项目里是有 callback 的 Response,被我开源的时候删掉了,我给你举个例子;
以 confirm 为例,在 HUDResponse 里有个接口处理,类似
apphost.invoke('confirm',
{title:'222'},
function(){
}
)
,的调用,而 native 端,响应逻辑如下。
....
@property (strong, nonatomic) NSMutableDictionary *callbackPool;
....
- (void)showConformWithTitle:(NSString *)title detail:(NSString *)detail callbackKey:(NSString *)callback
{
NYQAlertViewButtonModel *buttonModel = [[NYQAlertViewButtonModel alloc] initWithButtonStyle:NYQAlertViewButtonStyleConfirm];
buttonModel.title = @"确定";
NYQAlertView *alertView = [[NYQAlertView alloc] initWithTitle:title subTitle:detail buttonTitles:@[ @"取消", buttonModel ] contentView:nil];
alertView.delegate = self;
[alertView show];
if (callback.length > 0) {
alertView.tag = kTagOfAlertSeed++;
[self.callbackPool setObject:callback forKey:@(alertView.tag)];
}
}
- (void)nyqAlertView:(NYQAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex
{
NSString *callbackKey = [self.callbackPool objectForKey:@(alertView.tag)];
if (callbackKey) {
[self callbackFunctionOnWebPage:callbackKey param:@{ @"index" : @(buttonIndex) }];
[self.callbackPool removeObjectForKey:@(alertView.tag)];
DDLogDebug(@"[JSBridge] confirm or alert callback key : %@, index:%d", callbackKey, buttonIndex);
}
}
sysuleiw commented
@sysuleiw AppHost 现在内置的 Response 里是没有 callback 的例子,但是 js 端本身是支持的。native 端的 支持需要你自己写。
在实际项目里是有 callback 的 Response,被我开源的时候删掉了,我给你举个例子;
以 confirm 为例,在 HUDResponse 里有个接口处理,类似apphost.invoke('confirm', {title:'222'}, function(){ } ),的调用,而 native 端,响应逻辑如下。
.... @property (strong, nonatomic) NSMutableDictionary *callbackPool; .... - (void)showConformWithTitle:(NSString *)title detail:(NSString *)detail callbackKey:(NSString *)callback { NYQAlertViewButtonModel *buttonModel = [[NYQAlertViewButtonModel alloc] initWithButtonStyle:NYQAlertViewButtonStyleConfirm]; buttonModel.title = @"确定"; NYQAlertView *alertView = [[NYQAlertView alloc] initWithTitle:title subTitle:detail buttonTitles:@[ @"取消", buttonModel ] contentView:nil]; alertView.delegate = self; [alertView show]; if (callback.length > 0) { alertView.tag = kTagOfAlertSeed++; [self.callbackPool setObject:callback forKey:@(alertView.tag)]; } } - (void)nyqAlertView:(NYQAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex { NSString *callbackKey = [self.callbackPool objectForKey:@(alertView.tag)]; if (callbackKey) { [self callbackFunctionOnWebPage:callbackKey param:@{ @"index" : @(buttonIndex) }]; [self.callbackPool removeObjectForKey:@(alertView.tag)]; DDLogDebug(@"[JSBridge] confirm or alert callback key : %@, index:%d", callbackKey, buttonIndex); } }
ok,非常感谢;
web的callback调用已经明白;
另外还有两个问题请教楼主:
1.Android端开源计划有明确的时间点了吗?
2.关于native的callback楼主是不准备开源了吗?我这边也简单实现了,截取部分如下(有需要的同学也可以看看)
- (void)fire:(NSString *)actionName param:(NSDictionary *)paramDict callback:(AppHostResponseCallback)callback;
新增response如下
//
// AHCallbackResponse.m
// AppHost
//
// Created by sysuleiw on 2019/5/14.
// Copyright © 2019 liang. All rights reserved.
//
#import "AHCallbackResponse.h"
#import <objc/runtime.h>
static NSInteger uniqueId = 0;
static NSMutableDictionary *supportActionList = nil;
static NSMutableDictionary *supportCallbackList = nil;
static void selectorImp(id self, SEL _cmd, id arg)
{
NSString *selStr = NSStringFromSelector(_cmd);
if (selStr.length == 0)
{
return;
}
AppHostResponseCallback callback = (AppHostResponseCallback)[supportCallbackList objectForKey: selStr];
if (callback)
{
callback(arg);
}
[supportCallbackList removeObjectForKey:selStr];
[supportActionList removeObjectForKey:[selStr stringByReplacingOccurrencesOfString:@":" withString:@"_"]];
}
@implementation AHCallbackResponse
+ (NSDictionary<NSString *, NSString *> *)supportActionList
{
return supportActionList;
}
+ (NSString *)addResponseCallback:(AppHostResponseCallback)callback
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
supportActionList = [NSMutableDictionary new];
supportCallbackList = [NSMutableDictionary new];
});
if (callback)
{
NSString *uniqueStr = [NSString stringWithFormat:@"cbk_%zd",uniqueId++];
NSAssert([supportActionList objectForKey:uniqueStr] == nil, @"native 回调函数重复,不支持多线程");
[supportActionList setObject:@"1" forKey:[NSString stringWithFormat:@"%@_", uniqueStr]];
[self addMethodWithBlock:callback andUniqueStr:uniqueStr];
return uniqueStr;
}
return @"";
}
+ (void)addMethodWithBlock:(AppHostResponseCallback)callback andUniqueStr:(NSString *)uniqueStr
{
NSString *selName = [NSString stringWithFormat:@"%@:", uniqueStr];
SEL sel = NSSelectorFromString(selName);
class_addMethod(self, sel, (IMP)selectorImp, "v@:@");
[supportCallbackList setObject:[callback copy] forKey:NSStringFromSelector(sel)];
}
@end
window.appHost.__fire = function(_action, _data) {
var func = reqs[_action + ""];
if (typeof func == 'function') {
var respCallback = null;
var callBackId = _data['cbk'];
if (typeof callBackId != "undefined")
{
respCallback = function(data)
{
var fullParam =
{
action: callBackId,
param:data
};
window.webkit.messageHandlers.kAHScriptHandlerName.postMessage(fullParam)
}
}
func(_data, respCallback);
}
}
hite commented
- Android 端,现在看不到有人来做迹象,💔。
- callback
写的挺好的,你这个属于通用的 callback 功能支持。
我们项目里的 callback 是区分接口的,只有个别接口 callback,而且识场景,决定是用 self.callback 还是像你代码里的 callbackList dictionary。所以就不加进去了,不如你上面写的。