美文网首页
最近写项目的一些小总结

最近写项目的一些小总结

作者: LD_左岸 | 来源:发表于2018-03-31 11:52 被阅读37次

    可变字符串的拼接

    Snip20180331_13.png

    如图这段code 报错
    原来是我声明属性的时候

    @property(nonatomic,copy)NSMutableString * mutableString;
    

    属性是没有mutableCopy的 所以copy出来的其实是一个不可变字符串 所以报错
    解决方案很简单 两种
    1.简单直接了当


    Snip20180331_14.png

    2.直接了当简单


    Snip20180331_15.png

    WKWebView与JS的一些简单交互

    js调用OC <js调用OC的方法 或者js向OC传值>

    1.初始化webView的时候 添加处理脚本


    Snip20180331_3.png

    2.去代理方法中接收js传过来的参数

    #pragma mark - WKScriptMessageHandler
    //JS调OC----->OC里调用JS的方法 既能把JS的方法改掉 又能把JS的参数传递过来
    - (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
        if ([message.name isEqualToString:@"showName"]||[message.name isEqualToString:@"showName_t"]) {
          
            LDLog(@"%@",message.body);
    
        }
        
    }
    
      1. dealloc中删除注册的方法
    - (void)dealloc
    {
        LDLog(@"%s",__func__);
        [self.webView.configuration.userContentController removeScriptMessageHandlerForName:@"showName"];
        [self.webView.configuration.userContentController removeScriptMessageHandlerForName:@"showName_t"];
    }
    

    就是这么简单! 就可以实现了js调用OC了

    • 注意点是:js那边的方法要写在onLoad里 他们需要这么调用 可能和安卓略有不同
     function showName(val){
                window.webkit.messageHandlers.showName.postMessage(val) ;
             } 
    
    • 关于第一点中的WeakScriptMessageDelegate是因为
    [userCC addScriptMessageHandler:self name:@"showName"];
    

    直接添加对当前控制器 有强引用 造成控制器无法释放的问题
    WeakScriptMessageDelegate的具体实现是:

    .h
    
    #import <Foundation/Foundation.h>
    #import <WebKit/WebKit.h>
    @interface WeakScriptMessageDelegate : NSObject<WKScriptMessageHandler>
    @property (nonatomic, weak) id<WKScriptMessageHandler> scriptDelegate;
    - (instancetype)initWithDelegate:(id<WKScriptMessageHandler>)scriptDelegate;
    @end
    
    
    .m
    
    #import "WeakScriptMessageDelegate.h"
    
    @implementation WeakScriptMessageDelegate
    - (instancetype)initWithDelegate:(id<WKScriptMessageHandler>)scriptDelegate {
        self = [super init];
        if (self) {
            _scriptDelegate = scriptDelegate;
        }
        return self;
    }
    - (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
        [self.scriptDelegate userContentController:userContentController didReceiveScriptMessage:message];
    }
    - (void)dealloc
    {
        LDLog(@"%s",__func__);
    }
    

    OC调用JS (OC给js传值)更简单 两句代码 多一行都不带写的

    // 页面加载完成之后调用
    - (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation{
    
        NSString * jsStr = [NSString stringWithFormat:@"and_paperid('%@')",self.model.paper_id];
        [webView evaluateJavaScript:jsStr completionHandler:^(id _Nullable result, NSError * _Nullable error) {
            LDLog(@"%@",error);
        }];
        
        
    }
    这个地方 只要打印出error  99%的情况下是H5的把js没写明白
    

    关于H5的弹窗

    如果H5里 想向OC传一些值 验证是他没传过来 还是你没接受到 可以让H5写个alert()验证一把

    • 我们只需实现wkwebView的代理方法即可

    • 验证H5的alert()弹窗 使用80%的场景

    - (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler
    {
        completionHandler();
        
    }
    
    • Confirm弹窗
    - (void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL))completionHandler{
        //    DLOG(@"msg = %@ frmae = %@",message,frame);
        UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"提示" message:message?:@"" preferredStyle:UIAlertControllerStyleAlert];
        [alertController addAction:([UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
            completionHandler(NO);
        }])];
        [alertController addAction:([UIAlertAction actionWithTitle:@"确认" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
            completionHandler(YES);
        }])];
        [self presentViewController:alertController animated:YES completion:nil];
    }
    
    • TextInput弹窗
    - (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString * _Nullable))completionHandler{
                 completionHandler();
    }
    
    • WKWebView的加载进度
    UIProgressView *progressView = [[UIProgressView alloc] initWithProgressViewStyle:UIProgressViewStyleDefault];
            progressView.progressTintColor = HWColor(0, 170, 100);
            progressView.trackTintColor = [UIColor clearColor];
            self.progressView = progressView;
            [self.view insertSubview:progressView aboveSubview:_webView];
            [progressView mas_makeConstraints:^(MASConstraintMaker *make) {
                make.top.mas_offset(64);
                make.left.and.right.mas_equalTo(self.view);
                make.height.mas_equalTo(2);
            }];
            [_webView mas_makeConstraints:^(MASConstraintMaker *make) {
                make.top.and.left.and.right.mas_offset(0);
                make.bottom.mas_offset(0);
            }];
            [_webView addObserver:self
                forKeyPath:@"estimatedProgress"
                options:NSKeyValueObservingOptionNew
                context:nil];
    
    - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object
       change:(NSDictionary<NSString *,id> *)change  context:(void *)context
    {
        if ([keyPath isEqualToString:@"estimatedProgress"]) {
            self.progress = self.webView.estimatedProgress;
        }else{
            [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
        }
    }
    -(void)setProgress:(CGFloat)progress
    {
        _progress = progress;
        if (self.progressView.alpha == 0) {self.progressView.alpha = 1;}
        [self.progressView setProgress:progress animated:YES];
        if (progress >= 1) {
             [UIView animateWithDuration:0.8 animations:^{
                self.progressView.alpha = 0;
            } completion:^(BOOL finished) {
                self.progressView.progress = 0;
            }];
        }
    }
    

    sessionid的验证

    • 登录成功后保存
    AFHTTPSessionManager *manager=[AFHTTPSessionManager manager];
        manager.responseSerializer.acceptableContentTypes=[NSSet setWithObjects:@"application/json", nil];
    
    
    
        [manager.requestSerializer setHTTPShouldHandleCookies:NO];
    
    
    
        manager.requestSerializer.timeoutInterval=5.0f;
    
    [manager POST:LoginAPI parameters:@{@"user_id":_accountTF.text,@"password":_passwordTF.text} progress:nil success:^(NSURLSessionDataTask * _Nonnull task, NSDictionary * dict) {
            
            if ([[NSString stringWithFormat:@"%@",dict[@"flag"]] isEqualToString:@"1"]) {//登录成功
               
                /**保存session*/
                NSHTTPURLResponse* response = (NSHTTPURLResponse* )task.response;
                NSString* dataCookie = [NSString stringWithFormat:@"%@",[[response.allHeaderFields[@"Set-Cookie"]componentsSeparatedByString:@";"]objectAtIndex:0]];
                LDLog(@"登录成功获取到的sessionid = %@",dataCookie);
                
                if ([dataCookie isEqualToString:@"(null)"] || dataCookie == NULL) {
                }else
                {
                    [[NSUserDefaults standardUserDefaults] setObject:dataCookie forKey:@"cookie"];
                }
                successChangeUI();
            }else{
                [self errorAlert];
            }
        } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
            LDLog(@"error = %@",error);
            [self errorAlert];
        }];
    
    
    • 之后发起的每一个请求 都把sessionid拼接到请求头里
     AFHTTPSessionManager *manager=[AFHTTPSessionManager manager];
        manager.responseSerializer.acceptableContentTypes = [[NSSet alloc]initWithObjects:@"text/html",@"application/json",@"application/xml",@"text/javascript", nil];
        manager.requestSerializer.timeoutInterval=5.0f;
        /*在请求头中添加cookie*/
        NSString* headerCookie = [[NSUserDefaults standardUserDefaults] objectForKey:@"cookie"];
        if(headerCookie!=nil&& headerCookie.length>0) {
            [manager.requestSerializer setValue:headerCookie forHTTPHeaderField:@"Cookie"];
        }
        [manager POST:TeacherStatisticsMatchHomeAPI parameters:@{@"class_no":class,@"level_id":self.level_id} progress:nil success:^(NSURLSessionDataTask * _Nonnull task, NSDictionary * dict) {
            
            [MBProgressHUD hideHUD];
            
        } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
            [MBProgressHUD hideHUD];
            LDLog(@"%@",error);
        }];
    
    • 目前不太如人意的地方是 需要自动登录 所以逻辑如下 每次启动先去更新一把session
    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
           self.window = [[UIWindow alloc]initWithFrame:[UIScreen mainScreen].bounds];
        self.window.backgroundColor = [UIColor whiteColor];
        if ([LDUserTool isAutoLogin]) {
            UIViewController *emptyView = [[UIViewController alloc] init];
            self.window.rootViewController = emptyView;
            [self saveSessionid:^{
                 self.window.rootViewController = [[MtTabBarController alloc]init];
            } fail:^{
                 self.window.rootViewController = [[MtTabBarController alloc]init];
            }];
              
        }else{
            self.window.rootViewController = [[PlatformSelectController alloc]init];
        }
        [self.window makeKeyAndVisible];
        [self monitorNetworkStatus];
        return YES;
    }
    

    让collectionView的Frame由数据源决定

    在网络请求成功的回调里

    [self.view layoutIfNeeded];
     _collectionView.xmg_height = _collectionView.contentSize.height;
    

    隐藏某个控制器的状态栏

    两步
    1.在Info.plist中添加View controller-based status bar appearance

    C44A98B62DFF88F7342E0CE348A03102.png

    2.在需要隐藏的控制器里拷贝上这句代码

    - (BOOL)prefersStatusBarHidden
    {
        return YES;
    }
    

    只让项目里的某一个控制器支持横竖屏 其余控制器皆是竖屏

    Snip20180502_1.png

    第一步:AppDelegate.m

    BOOL isShu = 0;
    @implementation AppDelegate
    - (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
    {
        if (isShu == 1) {
            return UIInterfaceOrientationMaskAll;
        }else{
            return (UIInterfaceOrientationMaskPortrait);
        }
    }
    
    // 支持设备自动旋转
    - (BOOL)shouldAutorotate
    {
        if (isShu == 1) {
            return YES;
        }
        return NO;
    }
    

    第二步:支持横竖屏的控制器

    extern BOOL isShu;
    - (void)viewWillApplear {
        isShu = YES;
    }
    -(void)viewWillDisapplear
    {
         isShu = NO;
    }
    

    两步就OK别的代码不需要写 简单直截了当!

    判断横竖屏的方法

    - (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator {
    //可根据size参数判断是横还是竖
        [_ldPlayView mas_updateConstraints:^(MASConstraintMaker *make) {
            make.top.mas_offset(0);
            make.width.mas_equalTo(size.width);
            make.height.mas_equalTo(size.width * 9 / 16);
            make.left.mas_offset(0);
        }];
    }
    

    点击按钮 切换横竖屏

    _ldPlayView.crossScreen = ^(BOOL isCross) {
                if (isCross) {
     
                    NSNumber *orientation = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeLeft];
                    //如果当前设备不是横屏
                    if ([UIDevice currentDevice].orientation!=[orientation integerValue]) {
                        [[UIDevice currentDevice] setValue:orientation forKey:@"orientation"];
                    }
    
                    
                }else{
    
                    NSNumber *orientation = [NSNumber numberWithInt:UIDeviceOrientationPortrait];
                    if ([UIDevice currentDevice].orientation!=[orientation integerValue]) {
                        [[UIDevice currentDevice] setValue:orientation forKey:@"orientation"];//让设备竖屏
                        //点击按钮是让设备竖屏
                    }
                }
            };
    

    如果你对self.webView.scrollView设置了属性监听 你需要在dealloc里移除监听者 这是大家都知晓的

    但是你在写这行self.webView = nil;代码之前 也必须移除观察者 不然后在11以下的系统上崩溃 崩的无任何提示!

    • 正则匹配字符串中的数字
    - (NSMutableAttributedString*)returnArrtStrWith:(NSString*)str
    {
        if (!str.length) {
            return [[NSMutableAttributedString alloc]initWithString:@""];
        }
        NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"[0-9]+" options:0 error:nil];
        NSArray *numArr = [regex matchesInString:str options:0 range:NSMakeRange(0, [str length])];
        NSMutableAttributedString * attr = [[NSMutableAttributedString alloc]initWithString:str];
        
        for (NSTextCheckingResult *attirbute in numArr) {
            [attr setAttributes:@{NSForegroundColorAttributeName:HWColor(255, 212, 0)} range:attirbute.range];
            
        }
        return attr;
    }
    

    鉴于水平有限 能力一般 理解有误之处 深望不吝指出!

    相关文章

      网友评论

          本文标题:最近写项目的一些小总结

          本文链接:https://www.haomeiwen.com/subject/lljgcftx.html