hite/AppHost

native 调用 web 没有 callback功能

sysuleiw opened this issue · 5 comments

native 调用 web 没有 callback功能

如题,今天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 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

@sysuleiw

  1. Android 端,现在看不到有人来做迹象,💔。
  2. callback
    写的挺好的,你这个属于通用的 callback 功能支持。
    我们项目里的 callback 是区分接口的,只有个别接口 callback,而且识场景,决定是用 self.callback 还是像你代码里的 callbackList dictionary。所以就不加进去了,不如你上面写的。

@hite
感谢解答,期待Android早日开源😆