成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

weex-iOS實(shí)戰(zhàn)

roundstones / 914人閱讀

摘要:前言學(xué)習(xí)也有一段時(shí)間了,關(guān)于在三端的使用,我們也做了實(shí)戰(zhàn)開發(fā),渲染時(shí)間在之間,各平臺(tái)體驗(yàn)相比都有極大的提升,此文章在的角度記錄開發(fā)過程中遇到的一些問題,如果想要了解前端和安卓的開發(fā)可以參考我同事寫的一些內(nèi)容實(shí)踐前端視角實(shí)踐安卓視角準(zhǔn)備工作

前言

weex學(xué)習(xí)也有一段時(shí)間了,關(guān)于weex在三端的使用,我們也做了實(shí)戰(zhàn)開發(fā),渲染時(shí)間在100-300ms之間,各平臺(tái)體驗(yàn)相比H5都有極大的提升,此文章在iOS的角度記錄開發(fā)過程中遇到的一些問題,如果想要了解前端和安卓的開發(fā)可以參考我同事寫的一些內(nèi)容weex 實(shí)踐(前端視角)、weex 實(shí)踐(安卓視角)

準(zhǔn)備工作

weexSDK接入
Weex iOS SDK 官方集成指南

WXDevtool工具使用
Weex調(diào)試神器——Weex Devtools使用手冊(cè)

訂單頁實(shí)戰(zhàn)(weex-iOS相關(guān))

接下來我以訂單頁面為例,來描述一些用到的weex相關(guān)知識(shí)點(diǎn),如下圖描述

1. 初始化SDK,注冊(cè)module、protocol、component

/* 在appDelagate里初始化weexSDK并注冊(cè)module、protocol、component  */
-(void)initWeex{
    /* 初始化SDK環(huán)境 */
    [WXSDKEngine initSDKEnviroment];
    /* 自定義module*/
    [WXSDKEngine registerModule:@"shopBase" withClass:[BaseModule class]];
    [WXSDKEngine registerModule:@"shopModal" withClass:[WXModuleAnno class]];
    /* 初始化Protocol*/
    [WXSDKEngine registerHandler:[WXImgLoaderDefaultImpl new] withProtocol:@protocol(WXImgLoaderProtocol)];
    [WXSDKEngine registerHandler:[WXSJNetworkDefaultlmpl new] withProtocol:@protocol(WXNetworkProtocol)];
     /* 初始化Component*/
    [WXSDKEngine registerComponent:@"a" withClass:NSClassFromString(@"WXPushComponent")];
}

2. 實(shí)現(xiàn)類似選項(xiàng)卡的效果
如圖片第一點(diǎn)描述同一個(gè)viewcontroller多個(gè)view間的切換,此處本店訂單和我的訂單為不同的view,點(diǎn)擊來回切換,達(dá)到類似選項(xiàng)卡的效果
先貼段渲染weex頁面的基礎(chǔ)代碼

/*通過JS鏈接渲染weex頁面 會(huì)產(chǎn)出一個(gè)view*/
-(void)renderWeexWithUrl:(NSString *)url{
    _instance = [[WXSDKInstance alloc] init];
    _instance.viewController = self;
    CGFloat width = self.view.frame.size.width;
    _instance.frame = CGRectMake(self.view.frame.size.width-width, 0, width, _weexHeight);
    _instance.onCreate = ^(UIView *view) {
       /*頁面渲染成功 會(huì)產(chǎn)出一個(gè)view*/
    };
    _instance.onFailed = ^(NSError *error) {
      
    };
    _instance.renderFinish = ^(UIView *view) {

    };
    _instance.updateFinish = ^(UIView *view) {
    };
    [_instance renderWithURL:[NSURL URLWithString:url] options:@{@"bundleUrl":url} data:nil];
}

如上所述 我們可以針對(duì)產(chǎn)出的view進(jìn)行處理,簡(jiǎn)單的頁面直接添加到self.view上即可。
假如需要多個(gè)view間的切換,就如訂單頁的tabbar切換,我這里做了如下處理:
把每次新產(chǎn)生的view存到一個(gè)字典里,key是鏈接 value是新產(chǎn)生view ,每次渲染頁面前先通過key查找是否已經(jīng)存在該view,如果已存在把存的view拿出來展示,不存在渲染出來新的view
代碼修改如下

-(void)renderWeexWithUrl:(NSString *)url{
    /*通過url查找是否已經(jīng)存在該view 已存在顯示出來已有的 不再重新渲染*/
    if ([self.mdicViews objectForKey:url] && [[self.mdicViews objectForKey:url] isKindOfClass:[UIView class]]) {
        [self loadViewforKey:url];
    }else{
        __weak typeof(self) weakSelf = self;
        _instance = [[WXSDKInstance alloc] init];
        _instance.viewController = self;
        CGFloat width = self.view.frame.size.width;
        _instance.frame = CGRectMake(self.view.frame.size.width-width, 0, width, _weexHeight);
        _instance.onCreate = ^(UIView *view) {
            /*頁面渲染成功 會(huì)產(chǎn)出一個(gè)view*/
            [weakSelf.mdicViews setValue:view forKey:url];
            [weakSelf loadViewforKey:url];
        };
        _instance.onFailed = ^(NSError *error) {
            
        };
        _instance.renderFinish = ^(UIView *view) {
            
        };
        _instance.updateFinish = ^(UIView *view) {
        };
        [_instance renderWithURL:[NSURL URLWithString:url] options:@{@"bundleUrl":url} data:nil];
    }
    
}

/*通過key顯示某個(gè)view的操作*/
-(void)loadViewforKey:(NSString *)mstrJs{
    self.weexView = [_mdicViews objectForKey:mstrJs];
    [self.view insertSubview:self.weexView atIndex:0];
    UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, self.weexView);
    for (int i=0; i

3. 自定義a標(biāo)簽component 攔截url進(jìn)行跳轉(zhuǎn)

#import 

@interface WXPushComponent : WXComponent 

@end


#import "WXPushComponent.h"

@interface WXPushComponent()

@property (nonatomic, strong) UITapGestureRecognizer *tap;
@property (nonatomic, strong) NSString *href;

@end

@implementation WXPushComponent


- (instancetype)initWithRef:(NSString *)ref type:(NSString *)type styles:(NSDictionary *)styles attributes:(NSDictionary *)attributes events:(NSArray *)events weexInstance:(WXSDKInstance *)weexInstance
{
    self = [super initWithRef:ref type:type styles:styles attributes:attributes events:events weexInstance:weexInstance];
    if (self) {
        _tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(openURL)];
        _tap.delegate = self;
        if (attributes[@"href"]) {
            _href = attributes[@"href"];
        }
    }
    return self;
}

- (void)dealloc
{
    if (_tap.delegate) {
        _tap.delegate = nil;
    }
}

- (void)viewDidLoad
{
    [self.view addGestureRecognizer:_tap];
}

- (void)openURL
{
    if (_href && [_href length] > 0) {
        /* a標(biāo)簽的跳轉(zhuǎn)連接 可以根據(jù)該鏈接 進(jìn)行跳轉(zhuǎn) */
    }
}

- (void)updateAttributes:(NSDictionary *)attributes
{
    if (attributes[@"href"]) {
        _href = attributes[@"href"];
    }
}

#pragma mark
#pragma gesture delegate

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
    if ([gestureRecognizer isKindOfClass:[UITapGestureRecognizer class]] && [otherGestureRecognizer isKindOfClass:[UITapGestureRecognizer class]]) {
        return YES;
    }
    
    return NO;
}

@end

4. 自定義module實(shí)現(xiàn)confirm、toast、alert

#import 
#import 
#import 

@interface WXModuleAnno : NSObject

@end

#import "WXModuleAnno.h"

@implementation WXModuleAnno

@synthesize weexInstance;

WX_EXPORT_METHOD(@selector(toast:))
WX_EXPORT_METHOD(@selector(alert:callback:))
WX_EXPORT_METHOD(@selector(confirm:callback:))

- (void)confirm:(NSDictionary *)param callback:(WXModuleCallback)callback
{
    NSString *message = [self stringValue:param[@"message"]];
    NSString *okTitle = [self stringValue:param[@"okTitle"]];
    NSString *cancelTitle = [self stringValue:param[@"cancelTitle"]];
    if (okTitle.length==0) {
        okTitle = @"確認(rèn)";
    }
    if (cancelTitle.length==0) {
        cancelTitle = @"取消";
    }
    /* 此處為自己的彈框組件或者系統(tǒng)的組件 */
    
    /**/
    callback(okTitle);
   
}

- (void)toast:(NSDictionary *)param{
    NSString *message = [NSString stringWithFormat:@"%@",param[@"message"]];
    if (!message) return;
    /* 此處為自己的toast 組件 */
    
    /**/

}

- (void)alert:(NSDictionary *)param callback:(WXModuleCallback)callback
{
    NSString *message = [self stringValue:param[@"message"]];
    NSString *okTitle = [self stringValue:param[@"okTitle"]];
    /* 此處為自己的彈框組件或者系統(tǒng)的組件 */
    
    /**/
    callback(okTitle);
}

// 獲取當(dāng)前NVC
-(UINavigationController *)currentNVC{
    return [weexInstance.viewController navigationController];
}
// 獲取當(dāng)前VC
-(UIViewController *)currentVC{
    return weexInstance.viewController;
}

- (NSString*)stringValue:(id)value
{
    if ([value isKindOfClass:[NSString class]]) {
        return value;
    }
    if ([value isKindOfClass:[NSNumber class]]) {
        return [value stringValue];
    }
    return nil;
}

@end


5. 自定義圖片加載protocol,可以對(duì)圖片進(jìn)行壓縮和緩存的處理

#import 
#import 
@interface WXImgLoaderDefaultImpl : NSObject
@end

#import "WXImgLoaderDefaultImpl.h"
#import 

@interface WXImgLoaderDefaultImpl()

@end

@implementation WXImgLoaderDefaultImpl

#pragma mark -
#pragma mark WXImgLoaderProtocol

- (id)downloadImageWithURL:(NSString *)url imageFrame:(CGRect)imageFrame userInfo:(NSDictionary *)userInfo completed:(void(^)(UIImage *image,  NSError *error, BOOL finished))completedBlock
{
    if ([url hasPrefix:@"jpg"] || [url hasPrefix:@"png"]) {
       /* 做相應(yīng)的處理 */
    }
    return (id)[[SDWebImageManager sharedManager] downloadImageWithURL:[NSURL URLWithString:url] options:0 progress:^(NSInteger receivedSize, NSInteger expectedSize) {
        
    } completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
        if (completedBlock) {
            completedBlock(image, error, finished);
        }
    }];
}
@end

6. 自定義NetworkProtocol,可以針對(duì)網(wǎng)絡(luò)請(qǐng)求進(jìn)行攔截修改

#import 
#import 
@interface WXSJNetworkDefaultlmpl : NSObject

@end

#import "WXSJNetworkDefaultlmpl.h"

@interface WXNetworkCallbackInfo : NSObject

@property (nonatomic, copy) void(^sendDataCallback)(int64_t, int64_t);
@property (nonatomic, copy) void(^responseCallback)(NSURLResponse *);
@property (nonatomic, copy) void(^receiveDataCallback)(NSData *);
@property (nonatomic, strong) NSMutableData *data;
@property (nonatomic, copy) void(^compeletionCallback)(NSData *, NSError *);

@end

@implementation WXSJNetworkDefaultlmpl
{
    NSMutableDictionary *_callbacks;
    NSURLSession *_session;
}
- (id)sendRequest:(NSURLRequest *)request withSendingData:(void (^)(int64_t, int64_t))sendDataCallback
     withResponse:(void (^)(NSURLResponse *))responseCallback
  withReceiveData:(void (^)(NSData *))receiveDataCallback
  withCompeletion:(void (^)(NSData *, NSError *))compeletionCallback
{
    /*攔截了URL 如果沒有域名時(shí) 添加上域名 為了保持三端同步使用 我們域名放在每個(gè)端添加*/
    if (![request.URL.absoluteString hasPrefix:@"http"]) {
        request = [NSURLRequest requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@%@",@"",request.URL.absoluteString]]];
    }
    WXNetworkCallbackInfo *info = [WXNetworkCallbackInfo new];
    info.sendDataCallback = sendDataCallback;
    info.responseCallback = responseCallback;
    info.receiveDataCallback = receiveDataCallback;
    info.compeletionCallback = compeletionCallback;
    
    if (!_session) {
        _session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]
                                                 delegate:self
                                            delegateQueue:[NSOperationQueue mainQueue]];
    }
    
    NSURLSessionDataTask *task = [_session dataTaskWithRequest:request];
    if (!_callbacks) {
        _callbacks = [NSMutableDictionary dictionary];
    }
    [_callbacks setObject:info forKey:task];
    [task resume];
    
    return task;
}

- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task
   didSendBodyData:(int64_t)bytesSent
    totalBytesSent:(int64_t)totalBytesSent
totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend
{
    WXNetworkCallbackInfo *info = [_callbacks objectForKey:task];
    if (info.sendDataCallback) {
        info.sendDataCallback(totalBytesSent, totalBytesExpectedToSend);
    }
}

- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)task
didReceiveResponse:(NSURLResponse *)response
 completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler
{
    WXNetworkCallbackInfo *info = [_callbacks objectForKey:task];
    if (info.responseCallback) {
        info.responseCallback(response);
    }
    completionHandler(NSURLSessionResponseAllow);
}

- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)task didReceiveData:(NSData *)data
{
    WXNetworkCallbackInfo *info = [_callbacks objectForKey:task];
    if (info.receiveDataCallback) {
        info.receiveDataCallback(data);
    }
    
    NSMutableData *mutableData = info.data;
    if (!mutableData) {
        mutableData = [NSMutableData new];
        info.data = mutableData;
    }
    
    [mutableData appendData:data];
}

- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
{
    WXNetworkCallbackInfo *info = [_callbacks objectForKey:task];
    if (info.compeletionCallback) {
        info.compeletionCallback(info.data, error);
    }
    [_callbacks removeObjectForKey:task];
}

@end
weex native webview 無縫跳轉(zhuǎn)

主要講解如何實(shí)現(xiàn)weex native webview間的跳轉(zhuǎn),達(dá)到可以不僅隨意跳轉(zhuǎn)并且可以替換native頁面的效果
以下內(nèi)容來源于我司安卓大神weex 實(shí)踐(安卓視角)
App的跳轉(zhuǎn)規(guī)則的weex支持方案設(shè)計(jì)
跳轉(zhuǎn)規(guī)則如下圖,如果看不清,可以到新頁面放大查看,主要介紹一下兩個(gè)配置參數(shù):
1.參數(shù)interceptUrlList可以動(dòng)態(tài)配置需要攔截的h5鏈接,然后生成統(tǒng)一跳轉(zhuǎn)地址 showjoyshop://page.sh/order
示例如下:

[
    {
        "page":"order",
        "url":"https://dshdjshjbx"
    },
    {
        "page":"detail",
        "url":"https://dsdsds"
    }
]

2.然后通過order在參數(shù)weexPages里查找對(duì)應(yīng)的js信息,然后渲染
示例如下:

[
   {
       "page":"order",
       "url":"https://dshdjshjbx.js",
       "md5":"323827382huwhdjshdjs",
       "h5":"http://dsds.html"
       "v":"1.5.0"
    },
    {
       "page":"detail",
       "url":"https://dsdsds.js",
       "md5":"323827382huwhdjshdjs",
       "h5":"http://dsds.html"
       "v":"1.5.0"
    }
]

url: 需要渲染的js

md5: js文件的md5值用于校驗(yàn)

h5: 渲染失敗后的降級(jí)方案

v: 最低支持的版本號(hào)

這樣就達(dá)到了動(dòng)態(tài)攔截,動(dòng)態(tài)上線weex的目的

預(yù)加載weex-JS頁面 提高渲染速度

主要講解提前預(yù)下載JS文件的邏輯(當(dāng)然也可以不預(yù)下載,直接使用js鏈接即可)
為了提升渲染效率,我們會(huì)提前把js文件下載到本地,使用時(shí)直接加載本地文件,下載邏輯如下:
首先我們會(huì)有一個(gè)地方錄入如下格式的json數(shù)據(jù)

[
   {
       "page":"頁面名稱",
       "url":"js下載鏈接",
       "md5":"js文件MD5",
       "h5":"對(duì)應(yīng)的h5頁面"
       "v":"版本號(hào)"
    },
    {
       "page":"shoporder",
       "url":"https://xxxx.js",
       "md5":"js文件MD5",
       "h5":"http://xxxx.html"
       "v":"1.7.0"
    }
]

page: 對(duì)應(yīng)統(tǒng)一跳轉(zhuǎn)的 path(暫為頁面名稱)

url: 需要渲染的js

md5: js文件的md5值用于校驗(yàn)

h5: 渲染失敗后的降級(jí)方案

v: 最低支持的版本號(hào)

然后根據(jù)配置文件做如下操作

每次更新完配置文件,遍歷,查看是否存在md5一致的page_xxx.js文件,如果不存在則更新

下載完成后,保存格式為xxx.js,校驗(yàn)md5
相同的話,記錄文件的最后修改時(shí)間
不同的話,刪除已下載文件,重新下載,重復(fù)校驗(yàn)流程

支持統(tǒng)一跳轉(zhuǎn)協(xié)議,page對(duì)應(yīng)目前app端的統(tǒng)一跳轉(zhuǎn)協(xié)議里的page,有必要的時(shí)候可以替換原來的native頁面,解決native頁面錯(cuò)誤不能及時(shí)修復(fù)的問題。加載失敗的話,打開h5頁面

每次打開指定頁面的時(shí)候,先檢查本地是否有對(duì)應(yīng)page文件,再檢驗(yàn)最后修改時(shí)間是否跟記錄的一致
一致就加載
不一致就用線上url

第三條提到的統(tǒng)一跳轉(zhuǎn)協(xié)議是我們?yōu)榱私怦罡鱾€(gè)模塊所使用的一種方式,可根據(jù)自己的業(yè)務(wù)做相應(yīng)的改變
我們的就類似:
showjoyshop://page.sh/weex
showjoyshop://page.sh/webview
weex對(duì)應(yīng)的就是weex的vc webview對(duì)應(yīng)的就是webview的vc  weex和webview即是第三條提到的page

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/86744.html

相關(guān)文章

  • spring boot - 收藏集 - 掘金

    摘要:引入了新的環(huán)境和概要信息,是一種更揭秘與實(shí)戰(zhàn)六消息隊(duì)列篇掘金本文,講解如何集成,實(shí)現(xiàn)消息隊(duì)列。博客地址揭秘與實(shí)戰(zhàn)二數(shù)據(jù)緩存篇掘金本文,講解如何集成,實(shí)現(xiàn)緩存。 Spring Boot 揭秘與實(shí)戰(zhàn)(九) 應(yīng)用監(jiān)控篇 - HTTP 健康監(jiān)控 - 掘金Health 信息是從 ApplicationContext 中所有的 HealthIndicator 的 Bean 中收集的, Spring...

    rollback 評(píng)論0 收藏0
  • 從小白程序員一路晉升為大廠高級(jí)技術(shù)專家我看過哪些書籍?(建議收藏)

    摘要:大家好,我是冰河有句話叫做投資啥都不如投資自己的回報(bào)率高。馬上就十一國(guó)慶假期了,給小伙伴們分享下,從小白程序員到大廠高級(jí)技術(shù)專家我看過哪些技術(shù)類書籍。 大家好,我是...

    sf_wangchong 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<