最近写项目的一些小总结

可变字符串的拼接

最近写项目的一些小总结_第1张图片
Snip20180331_13.png

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

@property(nonatomic,copy)NSMutableString * mutableString;

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


最近写项目的一些小总结_第2张图片
Snip20180331_14.png

2.直接了当简单


最近写项目的一些小总结_第3张图片
Snip20180331_15.png

WKWebView与JS的一些简单交互

js调用OC

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


最近写项目的一些小总结_第4张图片
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 
#import 
@interface WeakScriptMessageDelegate : NSObject
@property (nonatomic, weak) id scriptDelegate;
- (instancetype)initWithDelegate:(id)scriptDelegate;
@end

.m

#import "WeakScriptMessageDelegate.h"

@implementation WeakScriptMessageDelegate
- (instancetype)initWithDelegate:(id)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 *)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;
}

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

最近写项目的一些小总结_第5张图片
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)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;
}

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

你可能感兴趣的:(最近写项目的一些小总结)