你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發基礎 >> kerkee 之 Web 和 iOS 開發使用篇

kerkee 之 Web 和 iOS 開發使用篇

編輯:IOS開發基礎

kerkee 之Web和iOS開發使用篇

簡單認識:kerkee 是一個多主體共存型 Hybrid 框架,具有跨平台、用戶體驗好、性能高、擴展性好、靈活性強、易維護、規范化、集成雲服務、具有Debug環境、徹底解決跨域問題。該框架從開發者角度支持三種團隊開發模式:Web開發者 、Native開發者 、Web開發者和Native團隊共同合作的開發團隊 。

下面我將從 Web開發者和Native(iOS)團隊共同合作的開發團隊 模式來分析使用該框架。

一、相關資料:

官網地址:http://www.kerkee.com

Github 源碼地址:https://github.com/kercer

QQ交流群:110710084

二、簡單的使用:

kerkee在iOS上的快速上手指南

1、建立新項目 kerkeeHDDemo 在項目目錄中建立 Podfile 文件:

platform :ios, '7.0'inhibit_all_warnings!pod ‘kerkee’, ’~> 1.0.1’

2、使用 CocoaPods 來導入 kerkee 框架,使用終端 cd 到你的 Podfile 文件所在的目錄:

cd $PodfilePathpod install

3、運行 Podfile 同目錄中的 kerkeeHDDemo.xcworkspace 即可;

4、在項目中添加 html 代碼:(本人對 html 不熟悉,相信懂的人肯定懂)

kerkeeTest.html :

                                                        
        
        [object Object]        
        [object Object]

上面有三種方式來處理按鈕的點擊事件:

i. 直接在 中處理

ii. 使用 function 處理;

iii. 使用 js 來處理 function。

代碼解釋:

代碼理解分析kerkeeJSManagerjs 這邊中 iOS 和 js 交互橋梁,在 iOS 也同樣存在 kerkeeJSManager 關鍵字jsToOc()kerkeeJSManager 方法 ,使用 kerkeeJSManager.jsToOc() 可以調用 iOS 對應的 - (void)jsToOc:(KCWebView)aWebView argList:(KCArgList)args 方法,實現 js 調用 iOS原生代碼ocToJs()在 iOS 中使用 [KCJSBridge callJSFunction:@"ocToJs" withJSONObject:@{@"hhh" : @"www"} WebView:m_webView]; 可以調用 js 的 ocToJs() 方法,實現了 iOS 調用 js 代碼

kerkeeTest.js :

var kerkeeJSManager;function buttonClick2(s1)
{    kerkeeJSManager.jsToOc(s1);
}

5、在項目中添加 iOS 代碼:

HDJSToOCManager.h

#import #import "KCJSObject.h"#import "KCArgList.h"// 這個類作為 和 js 交互橋梁類@interface HDJSToOCManager : KCJSObject- (void)jsToOc:(KCWebView*)aWebView argList:(KCArgList*)args;

- (void)mutualJSOC:(KCWebView*)aWebView argList:(KCArgList*)args;@end

HDJSToOCManager.m

#import "HDJSToOCManager.h"#import #import "KCJSBridge.h"@implementation HDJSToOCManager- (NSString*)getJSObjectName{    // 這個 和 js 中的變量要保持一致
    return @"kerkeeJSManager";
}// js 中 可以調用 jsToOc() 來調用- (void)jsToOc:(KCWebView*)aWebView argList:(KCArgList*)args{    NSLog(@"JS調用OC args : %@", args);
}

- (void)mutualJSOC:(KCWebView*)aWebView argList:(KCArgList*)args{    NSLog(@"JS調用OC,OC回調JS args : %@", args);    NSMutableDictionary *dic = [NSMutableDictionary dictionary];
    [dic setObject:@"success" forKey:@"info"];    NSString *json = [[NSString alloc] initWithData:[NSJSONSerialization dataWithJSONObject:dic options:0 error:nil] encoding:NSUTF8StringEncoding];    KCAutorelease(json);    //回調,callbackId,kerkee.js 內部已經處理好
    [KCJSBridge callbackJS:aWebView callBackID:[args getObject:@"callbackId"] jsonString:json];
}@end

這個類主要是生成和 js 對應的變量 kerkeeJSManager ,是 iOS 這邊 iOS 和 js 交互橋梁

ViewController.m

- (void)viewDidLoad {
    [super viewDidLoad];     // 將 HDJSToOCManager對象 和 js中的 kerkeeJSManager (詳見HDJSToOCManager)綁定
    [KCJSBridge registObject:[[HDJSToOCManager alloc] init]];    NSString *file = [[NSBundle mainBundle] pathForResource:@"kerkeeTest" ofType:@"html"];    NSURL *url = [NSURL URLWithString:file];    NSMutableURLRequest *request =[NSMutableURLRequest requestWithURL:url];
    m_webView = [[KCWebView alloc] initWithFrame:self.view.bounds];
    [m_webView loadRequest:request];
    [self.view addSubview:m_webView];    // 在m_webView 加載 “kerkee.js” 代碼,具體代碼見 KCApiBridge.m 中的 init 方法 (這個時候需要在項目中添加“kerkee.js” 文件)
    m_jsBridge = [[KCJSBridge alloc] initWithWebView:m_webView delegate:self];

    UIButton *bb = [UIButton buttonWithType:UIButtonTypeInfoLight];
    bb.frame = CGRectMake(100, 400, 50, 50);
    [bb addTarget:self action:@selector(ocToJs) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:bb];
}

- (void)ocToJs{
    [KCJSBridge callJSFunction:@"ocToJs" withJSONObject:@{@"hhh" : @"www"} WebView:m_webView];
}

#pragma mark --
#pragma mark KCWebViewProgressDelegate
-(void)webView:(KCWebView*)webView identifierForInitialRequest:(NSURLRequest*)initialRequest{

}

#pragma mark - UIWebView Delegate
- (void)webViewDidFinishLoad:(UIWebView *)aWebView{    NSString *scrollHeight = [aWebView stringByEvaluatingJavaScriptFromString:@"document.body.scrollHeight;"];    NSLog(@"scrollHeight: %@", scrollHeight);    NSLog(@"webview.contentSize.height %f", aWebView.scrollView.contentSize.height);
}

- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error{

}

- (BOOL)webView:(UIWebView *)aWebView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{    return YES;
}

上面的代碼並不多,其核心代碼之一在 KCApiBridge 中,可以看到, KCApiBridge 在初始化的時候找到 kerkee.js 並且使用- (nullable NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script; 在 iOS 的 UIWebView 注入 kerkee.js 代碼。這份 js 才是真正的將 iOS 的橋梁 HDJSToOCManager 實體和 js變量 kerkeeJSManager 的關鍵代碼。在 這裡 可以看到作者在demo中的 kerkee.js 源碼。因為我對 js 也是入門階段,所以選擇在源碼上改動之後,代碼如下:

;(function(window){    if (window.WebViewJSBridge)        return;    window.WebViewJSBridge = {

  };    console.log("--- kerkee init begin---");    var browser={        versions:function(){            var u = navigator.userAgent, app = navigator.appVersion;            return {
                trident: u.indexOf('Trident') > -1, //IE
                presto: u.indexOf('Presto') > -1, //opera
                webKit: u.indexOf('AppleWebKit') > -1, //apple&google kernel
                gecko: u.indexOf('Gecko') > -1 && u.indexOf('KHTML') == -1,//firfox
                mobile: !!u.match(/AppleWebKit.*Mobile.*/), //is Mobile
                ios: !!u.match(/(i[^;]+;( U;)? CPU.+Mac OS X/), //is ios
                android: u.indexOf('Android') > -1 || u.indexOf('Adr') > -1, //android
                iPhone: u.indexOf('iPhone') > -1 , //iPhone or QQHD
                iPad: u.indexOf('iPad') > -1, //iPad
                iPod: u.indexOf('iPod') > -1, //iPod
                webApp: u.indexOf('Safari') == -1, //is webapp,no header and footer
                weixin: u.indexOf('MicroMessenger') > -1, //is wechat
                qq: u.match(/sQQ/i) == " qq" //is qq
            };
        }(),
        language:(navigator.browserLanguage || navigator.language).toLowerCase()
    }    var global = this || window;    var ApiBridge ={
        msgQueue : [],
        callbackCache : [],
        callbackId : 0,
        processingMsg : false,
        isReady : false,
        isNotifyReady : false
    };    ApiBridge.create = function()
    {                  
        ApiBridge.bridgeIframe = document.createElement("iframe");        ApiBridge.bridgeIframe.style.display = 'none';        document.documentElement.appendChild(ApiBridge.bridgeIframe);
    };    ApiBridge.prepareProcessingMessages = function()
    {        ApiBridge.processingMsg = true;
    };    ApiBridge.fetchMessages = function()
    {        if (ApiBridge.msgQueue.length > 0)
        {            var messages = JSON.stringify(ApiBridge.msgQueue);            ApiBridge.msgQueue.length = 0;            return messages;
        }        ApiBridge.processingMsg = false;        return null;
    };    ApiBridge.callNative = function(clz, method, args, callback)
    {        var msgJson = {};        msgJson.clz = clz;        msgJson.method = method;        if (args != undefined)            msgJson.args = args;        if (callback)
        {            var callbackId = ApiBridge.getCallbackId();            ApiBridge.callbackCache[callbackId] = callback;            if (msgJson.args)
            {                msgJson.args.callbackId = callbackId.toString();
            }            else
            {                msgJson.args =
                {                    "callbackId" : callbackId.toString()
                };
            }
        }        if (browser.versions.ios)
        {            if (ApiBridge.bridgeIframe == undefined)
            {                ApiBridge.create();
            }            // var msgJson = {"clz": clz, "method": method, "args": args};
            ApiBridge.msgQueue.push(msgJson);            if (!ApiBridge.processingMsg)                ApiBridge.bridgeIframe.src = "kcnative://go";
        }        else if (browser.versions.android)
        {            // android
            return prompt(JSON.stringify(msgJson));
        }

    };    ApiBridge.log = function(msg)
    {        ApiBridge.callNative("ApiBridge", "JSLog",
        {            "msg" : msg
        });
    }    ApiBridge.getCallbackId = function()
    {        return ApiBridge.callbackId++;
    }    ApiBridge.onCallback = function(callbackId, obj)
    {        if (ApiBridge.callbackCache[callbackId])
        {            ApiBridge.callbackCache[callbackId](obj);            // ApiBridge.callbackCache[callbackId] = undefined;
            // //如果是注冊事件的話,不能undefined;
        }
    }    ApiBridge.onBridgeInitComplete = function(callback)
    {        ApiBridge.callNative("ApiBridge", "onBridgeInitComplete", {}, callback);
    }    ApiBridge.onNativeInitComplete = function(callback)
    {        ApiBridge.isReady = true;        console.log("--- kerkee onNativeInitComplete end ---");        if (callback)
        {            callback();            ApiBridge.isNotifyReady = true;            console.log("--- device ready go--- ");
        }
    }    ApiBridge.compile = function(aIdentity, aJS)
    {        var value;        var error;        try
        {
            value = eval(aJS);
        }        catch (e)
        {            var err = {};            err.name = e.name;            err.message = e.message;            err.number = e.number & 0xFFFF;
            error = err;
        }        ApiBridge.callNative("ApiBridge", "compile",
        {            "identity" : aIdentity,            "returnValue" : value,            "error" : error
        });
    }    var _Configs =
    {
        isOpenJSLog:false,
        sysLog:{},
        isOpenNativeXHR:true,
        sysXHR:{}
    };    _Configs.sysLog = global.console.log;    _Configs.sysXHR = global.XMLHttpRequest;    var kerkee = {};    /*****************************************     * JS和iOS 交互接口     *****************************************/
    kerkee.jsToOc = function(s1)
       {       ApiBridge.callNative("kerkeeJSManager", "jsToOc",
            {                "s1" : s1
            });
       };       kerkee.mutualJSOC = function(aString, callback)
       {       ApiBridge.callNative("kerkeeJSManager", "mutualJSOC",
            {                "aString" : aString
            }, callback);
       }    global.kerkeeJSManager = kerkee;    kerkee.openJSLog = function()
    {        _Configs.isOpenJSLog = true;        global.console.log = ApiBridge.log;
    }    kerkee.closeJSLog = function()
    {        _Configs.isOpenJSLog = false;        global.console.log = _Configs.sysLog;
    }    kerkee.onDeviceReady = function(handler)
    {        ApiBridge.onDeviceReady = handler;        if (ApiBridge.isReady && !ApiBridge.isNotifyReady && handler)
        {            console.log("-- device ready --");            handler();            ApiBridge.isNotifyReady = true;
        }
    };    kerkee.invoke = function(clz, method, args, callback)
    {        if (callback)
        {            ApiBridge.callNative(clz, method, args, callback);
        }        else
        {            ApiBridge.callNative(clz, method, args);
        }
    };    kerkee.onSetImage = function(srcSuffix, desUri)
    {        // console.log("--- kerkee onSetImage ---");
        var obj = document.querySelectorAll('img[src$="' + srcSuffix + '"]');        for (var i = 0; i < obj.length; ++i)
        {
            obj[i].src = desUri;
        }
    };    /*****************************************     * XMLHttpRequest實現     *****************************************/
    var _XMLHttpRequest = function()
    {        this.id = _XMLHttpRequest.globalId++;        _XMLHttpRequest.cache[this.id] = this;        this.status = 0;        this.statusText = '';        this.readyState = 0;        this.responseText = '';        this.headers = {};        this.onreadystatechange = undefined;        ApiBridge.callNative('XMLHttpRequest', 'create',
        {            "id" : this.id
        });
    }    _XMLHttpRequest.globalId = 0;    _XMLHttpRequest.cache = [];    _XMLHttpRequest.setProperties = function(jsonObj)
    {        var id = jsonObj.id;        if (_XMLHttpRequest.cache[id])
        {            var obj = _XMLHttpRequest.cache[id];            if (jsonObj.hasOwnProperty('status'))
            {                obj.status = jsonObj.status;
            }            if (jsonObj.hasOwnProperty('statusText'))
            {                obj.statusText = jsonObj.statusText;
            }            if (jsonObj.hasOwnProperty('readyState'))
            {                obj.readyState = jsonObj.readyState;
            }            if (jsonObj.hasOwnProperty('responseText'))
            {                obj.responseText = jsonObj.responseText;
            }            if (jsonObj.hasOwnProperty('headers'))
            {                obj.headers = jsonObj.headers;
            }            if (_XMLHttpRequest.cache[id].onreadystatechange)
            {                _XMLHttpRequest.cache[id].onreadystatechange();
            }
        }
    }    _XMLHttpRequest.prototype.open = function(method, url, async)
    {        ApiBridge.callNative('XMLHttpRequest', 'open',
        {            "id" : this.id,            "method" : method,            "url" : url,            "scheme" : window.location.protocol,            "host" : window.location.hostname,            "port" : window.location.port,            "href" : window.location.href,            "referer" : document.referrer != "" ? document.referrer : undefined,            "useragent" : navigator.userAgent,            "cookie" : document.cookie != "" ? document.cookie : undefined,            "async" : async,            "timeout" : this.timeout
        });
    }    _XMLHttpRequest.prototype.send = function(data)
    {        if (data != null)
        {            ApiBridge.callNative('XMLHttpRequest', 'send',
            {                "id" : this.id,                "data" : data
            });
        }        else
        {            ApiBridge.callNative('XMLHttpRequest', 'send',
            {                "id" : this.id
            });
        }
    }    _XMLHttpRequest.prototype.overrideMimeType = function(mimetype)
    {        ApiBridge.callNative('XMLHttpRequest', 'overrideMimeType',
        {            "id" : this.id,            "mimetype" : mimetype
        });
    }    _XMLHttpRequest.prototype.abort = function()
    {        ApiBridge.callNative('XMLHttpRequest', 'abort',
        {            "id" : this.id
        });
    }    _XMLHttpRequest.prototype.setRequestHeader = function(headerName,            headerValue)
    {        ApiBridge.callNative('XMLHttpRequest', 'setRequestHeader',
        {            "id" : this.id,            "headerName" : headerName,            "headerValue" : headerValue
        });
    }    _XMLHttpRequest.prototype.getAllResponseHeaders = function()
    {        var strHeaders = '';        for ( var name in this.headers)
        {
            strHeaders += (name + ": " + this.headers[name] + "
");
        }        return strHeaders;
    }    _XMLHttpRequest.prototype.getResponseHeader = function(headerName)
    {        var strHeaders;        var upperCaseHeaderName = headerName.toUpperCase();        for ( var name in this.headers)
        {            if (upperCaseHeaderName == name.toUpperCase())
                strHeaders = this.headers[name]
        }        return strHeaders;
    }    _XMLHttpRequest.deleteObject = function(id)
    {        if (_XMLHttpRequest.cache[id])
        {            _XMLHttpRequest.cache[id] = undefined;
        }
    }    global.ApiBridge = ApiBridge;    global.kerkee = kerkee;    global.XMLHttpRequest = _XMLHttpRequest;    kerkee.register = function(_window)
    {        _window.ApiBridge = window.ApiBridge;        _window.kerkee = window.kerkee;        _window.console.log = window.console.log;        _window.XMLHttpRequest = window.XMLHttpRequest;        _window.open = window.open;
    };    ApiBridge.onBridgeInitComplete(function(aConfigs)
    {        if (aConfigs)
        {            if (aConfigs.hasOwnProperty('isOpenJSLog'))
            {                _Configs.isOpenJSLog = aConfigs.isOpenJSLog;
            }            if (aConfigs.hasOwnProperty('isOpenNativeXHR'))
            {                _Configs.isOpenNativeXHR = aConfigs.isOpenNativeXHR;
            }
        }        if (_Configs.isOpenJSLog)
        {            global.console.log = ApiBridge.log;
        }        ApiBridge.onNativeInitComplete(ApiBridge.onDeviceReady);

    });

})(window);

如果單純的只是 js 和 iOS 的交互,只需要關注 下面 的代碼即可:(當然你也可以自己設置多個 kerkeeJSManager 橋梁及 更多的 交互方法)

/***************************************** * JS和iOS 交互接口 *****************************************/kerkee.jsToOc = function(s1)
   {   ApiBridge.callNative("kerkeeJSManager", "jsToOc",
        {            "s1" : s1
        });
   };   kerkee.mutualJSOC = function(aString, callback)
   {   ApiBridge.callNative("kerkeeJSManager", "mutualJSOC",
        {            "aString" : aString
        }, callback);
   }global.kerkeeJSManager = kerkee;

6、編譯運行:

Xcode 編譯運行效果

7、demo下載地址:GitHub地址

三、總結:

這裡只是簡單的介紹了 iOS 使用 kerkee 框架來加載 html 實現 js 和 iOS 交互 ,如果只是單純的為了簡單的交互,可以看我的另外一篇博客 :JS和OC相互調用 ,這裡介紹了幾個更加輕量級的框架實現 js 和 iOS 交互。但是 js 和 iOS 交互 功能在kerkee 框架的一小部分,更多高性能、支持跨平台、擴展性好、易維護等等優秀的特性,我會慢慢閱讀源碼來說明。



該博客更好的閱讀體驗地址



  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved