别人的iOS精华iOS 每天一读买不来的iOS实用技巧

iOS 初步开发完问题小记

2016-10-14  本文已影响902人  凉风起君子意如何

题外话

基于市场运营针对老版本H5与本地混合app(偏h5,大概只有登录注册找回密码用户那块等是本地)无法很好的推广,公司领导决定重新改版,统一用本地模式。并且要求大概20个工作日完成。所以这段时间确实很忙,主要因素有以下几点,总体就是不确定和空白:

后期会陆续补充整个项目的框架,以及用到的一些第三方库及使用,以及一些费时间点。

正题

iOS这边整个项目进度:大概功能已开发完成,测试那边也大概的走了一遍。解决bug中。上几个图,嘿嘿😋

首页.png 个人中心.png

以下就记录下自己觉得比较重要的知识点(个人观点哈,大咖请绕行,😀)

1. tableview 多个textfield, 键盘遮挡问题

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    //监听键盘出现和消失,解决键盘遮挡最后textfield问题
    [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
    [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
}

- (void)viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];
    
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

#pragma mark 键盘出现
-(void)keyboardWillShow:(NSNotification *)note
{
    CGRect keyBoardRect=[note.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
    self.tableview.frame = CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height - 64 - keyBoardRect.size.height);
}
#pragma mark 键盘消失
-(void)keyboardWillHide:(NSNotification *)note
{
    self.tableview.frame = CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height - 64);
}

2. oc与js简单交互

场景:邀请页面加载H5,如下邀请好友页面,思路分解:

邀请好友页面.png

核心代码(相应代码位置自己调一下)如下:

#import <WebKit/WebKit.h>
#import <JavaScriptCore/JavaScriptCore.h>
@property (strong, nonatomic) JSContext *context;
#pragma mark - 邀请好友页面 uiwebview代理
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
    self.loadCount --;
    
    //oc call js,oc给js传值
    self.context = [[JSContext alloc] init];
    self.context = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
    // 打印异常
    self.context.exceptionHandler =
    ^(JSContext *context, JSValue *exceptionValue)
    {
        context.exception = exceptionValue;
        NSLog(@"%@", exceptionValue);
    };
    
    [self.webView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"inviteInfo('%@','%@');",
                                                          self.inviteNumber,self.inviteEarn]];
    
    __weak BannerHrefVC *weakself = self;
    self.context[@"handleShare"] =
    ^(NSString *title,NSString *text)
    {
        dispatch_async(dispatch_get_main_queue(), ^(void){
            NSLog(@"%@ %@",title,text);
            weakself.shareTitle = title;
            weakself.shareText = text;
            [weakself setupUMShare];
        });
    };
    
    self.context[@"goFriendList"] =
    ^(void)
    {
        dispatch_async(dispatch_get_main_queue(), ^(void){
            [weakself.navigationController pushViewController:[[FriendsListVC alloc]initWithTitle:@"好友列表" ] animated:NO];
        });
    };
}

3. 上传头像

场景:个人中心,从本地拍照或者选择相册里面照片上传到服务器,并更新。特别注意content-type的设置(设置不对,会发生一系列的错误,最折磨人的是后台那边能收到图片,但是打不开,这个时候不仅跟这个参数有关,后台那边接收方式也有关系)如下图:

上传图片.png

核心代码如下:
iOS客户端
AFURLResponseSerialization.h 的init里面

#pragma -mark 我这边直接改的源文件,不建议这样改,自己在用的地方相应设置下就好
self.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/json", @"text/javascript",@"multipart/form-data",@"text/plain", nil];

最好自己用的地方如下设置:
AFHTTPSessionManager *session = [AFHTTPSessionManager manager];
    //https
    session.securityPolicy = [self customSecurityPolicy];
    session.securityPolicy.allowInvalidCertificates = YES;
    session.responseSerializer = [AFJSONResponseSerializer serializer];
    session.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/json", @"text/javascript",@"multipart/form-data",@"text/plain", nil];
    session.requestSerializer = [AFJSONRequestSerializer serializer];
#pragma -mark
#pragma -mark tableview delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (indexPath.row == 0) {
        //设置头像
        [self alterHeadPortrait];
    }
}

- (void)alterHeadPortrait{
    //解决iOS8在调用系统相机拍照时,会有一两秒的停顿,然后再弹出UIImagePickConroller的问题
    if([[[UIDevice
          currentDevice] systemVersion] floatValue]>=8.0) {
        
        self.modalPresentationStyle=UIModalPresentationOverCurrentContext;
        
    }
    
    //初始化提示框
    UIAlertController *alert = [UIAlertController alertControllerWithTitle:nil message:nil preferredStyle:UIAlertControllerStyleActionSheet];
    //按钮:从相册选择,类型:UIAlertActionStyleDefault
    [alert addAction:[UIAlertAction actionWithTitle:@"从相册选择" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        //初始化UIImagePickerController
        UIImagePickerController *PickerImage = [[UIImagePickerController alloc]init];
        //获取方式1:通过相册(呈现全部相册),UIImagePickerControllerSourceTypePhotoLibrary
        //获取方式2,通过相机,UIImagePickerControllerSourceTypeCamera
        //获取方法3,通过相册(呈现全部图片),UIImagePickerControllerSourceTypeSavedPhotosAlbum
        PickerImage.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
        //允许编辑,即放大裁剪
        PickerImage.allowsEditing = YES;
        //自代理
        PickerImage.delegate = self;
        //页面跳转
        [self presentViewController:PickerImage animated:YES completion:nil];
    }]];
    //按钮:拍照,类型:UIAlertActionStyleDefault
    [alert addAction:[UIAlertAction actionWithTitle:@"拍照" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action){
        /**
         其实和从相册选择一样,只是获取方式不同,前面是通过相册,而现在,我们要通过相机的方式
         */
        UIImagePickerController *PickerImage = [[UIImagePickerController alloc]init];
        //获取方式:通过相机
        PickerImage.sourceType = UIImagePickerControllerSourceTypeCamera;
        PickerImage.allowsEditing = YES;
        PickerImage.delegate = self;
        [self presentViewController:PickerImage animated:YES completion:nil];
    }]];
    //按钮:取消,类型:UIAlertActionStyleCancel
    [alert addAction:[UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:nil]];
    [self presentViewController:alert animated:YES completion:nil];
}

#pragma mark
#pragma mark PickerImage完成后的代理方法
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info{
    
    //定义一个newPhoto,用来存放我们选择的图片。
    UIImage *newPhoto = [info objectForKey:@"UIImagePickerControllerEditedImage"];
    self.ivHead.image = newPhoto;
    //上传头像到服务器
    [self reqUpdateHeader:newPhoto];
    [self dismissViewControllerAnimated:YES completion:nil];
}

#pragma mark
#pragma mark 上传头像到服务器
- (void)reqUpdateHeader:(UIImage *)image{
    AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
    manager.responseSerializer = [AFJSONResponseSerializer serializer];
    manager.requestSerializer = [AFJSONRequestSerializer serializer];
    NSString *strURL =  [NSString stringWithFormat:@"http://test.helloan.cn/mobile/rest/uploadPhoto/savePhoto/1?token=%@",
                        [PersonalCenterData sharedInstance].userInfo.token];
    
    [manager POST:strURL parameters:nil
           constructingBodyWithBlock:^(id<AFMultipartFormData>  _Nonnull formData) {
       NSData *fileData = UIImageJPEGRepresentation(image, 0.1);
       NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
       formatter.dateFormat = @"yyyyMMddHHmmss";
       NSString *str = [formatter stringFromDate:[NSDate date]];
       NSString *fileName = [NSString stringWithFormat:@"%@.jpg", str];
       [formData appendPartWithFileData:fileData name:@"fileName" fileName:fileName mimeType:@"image/jpg"];
    } progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        NSLog(@"%@",responseObject);
        if ([[responseObject objectForKey:@"code"] isEqualToString:Response_OK]) {
            [PersonalCenterData sharedInstance].userInfo.logoUrl = [responseObject objectForKey:@"logoUrl"];
        }
        [self.view makeToast:[responseObject objectForKey:@"message"]];
        
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        NSLog(@"%@",error);
    }];
}

java后台

DiskFileItemFactory factory = new DiskFileItemFactory();
        //设置工厂的缓冲区的大小,当上传的文件大小超过缓冲区的大小时,就会生成一个临时文件存放到指定的临时目录当中。
        factory.setSizeThreshold(1024*100);//设置缓冲区的大小为100KB,如果不指定,那么缓冲区的大小默认是10KB
        //创建一个文件上传解析器
        ServletFileUpload upload = new ServletFileUpload(factory);
         //解决上传文件名的中文乱码
        upload.setHeaderEncoding("UTF-8"); 
        //设置上传单个文件的大小的最大值,目前是设置为1024*1024字节,也就是1MB
        upload.setFileSizeMax(1024*1024);
        //设置上传文件总量的最大值,最大值=同时上传的多个文件的大小的最大值的和,目前设置为10MB
//        upload.setSizeMax(1024*1024*10);
        //4、使用ServletFileUpload解析器解析上传数据,解析结果返回的是一个List<FileItem>集合,每一个FileItem对应一个Form表单的输入项
        List<FileItem> list = upload.parseRequest(request);

4. label自动换行问题

网上查挺多的,这里只是记录下,以后好查阅😀

    UILabel *lb = [[UILabel alloc]init];
    lb.numberOfLines = 0;
    lb.lineBreakMode = NSLineBreakByWordWrapping;

5. label设置部分字体颜色

其实可以跟上面写在一起的,但是懒得改下面的序列号了,真的好懒啊,莫怪😀

UILabel *lb = [[UILabel alloc]initWithFrame:CGRectMake(ContentX, 0, kScreenWidth-ContentX, kRowHeight+10)];
        lb.textColor = [UIColor grayColor];
        NSString *str1 = @"密码为6-15个字符,建议字母数字和特殊字符混合,登录密码必须和交易密码不同。新用户交易密码为登录密码。";
        NSMutableAttributedString *str = [[NSMutableAttributedString alloc]
                                          initWithString:str1];
        //    //设置字号
        //    [str addAttribute:NSFontAttributeName value:font range:range];
        //设置文字颜色
        NSRange range =[str1 rangeOfString:@"新用户交易密码为登录密码。"];
        [str addAttribute:NSForegroundColorAttributeName value:kColorHeadPerson range:range];
        lb.attributedText = str;
        lb.numberOfLines = 0;
        lb.lineBreakMode = NSLineBreakByWordWrapping;
        lb.font = kFontText;
        [head addSubview:lb];

6. 动态获取cell高度

待写

7. 重写导航左侧返回按钮

如下代码也对导航和底部tab的显示和隐藏做了处理

#pragma -mark viewLife
- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.view.backgroundColor = [UIColor whiteColor];
    self.automaticallyAdjustsScrollViewInsets = NO;
    
    self.navigationController.navigationBar.barTintColor = kColorHeadPerson;
    //半透明状态
    self.navigationController.navigationBar.translucent = NO;

    self.navigationController.navigationBar.tintColor = [UIColor whiteColor];
    //设置文字前景色
    [self.navigationController.navigationBar setTitleTextAttributes:
  @{NSFontAttributeName:[UIFont systemFontOfSize:22],
    NSForegroundColorAttributeName:[UIColor whiteColor]}];
    //重写返回按钮
    self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc]initWithImage:[UIImage imageNamed:@"back_normal"]
                                                                            style:UIBarButtonItemStylePlain
                                                                           target:self
                                                                           action:@selector(buttonBack)];
    
    self.hud = [[MBProgressHUD alloc]initWithView:self.view];
    self.hud.delegate = self;
    self.hud.mode = MBProgressHUDModeIndeterminate;
    self.hud.label.text=@"加载中,请稍后!";
    self.hud.backgroundColor =[UIColor lightGrayColor];
    [self.view addSubview:self.hud];
}

- (void)buttonBack
{
    [self.navigationController popViewControllerAnimated:NO];
}

-(void)viewWillAppear:(BOOL)animated{
    
    [super viewWillAppear:animated];
    
    [self.navigationController setNavigationBarHidden:NO animated:YES];
    self.tabBarController.tabBar.hidden = YES;
}

- (void)viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];
    
    self.tabBarController.tabBar.hidden = NO;
}

8. 程序延迟执行

场景:操作完之后,例如修改密码完成之后,先toast,之后延时3秒再进行页面跳转。若不延时,toast显示是看不到的。
网上后来看到有三种方式,大概为:performSelector,nstimer,gcd. 我这边用的是gcd

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
                //your code
            });

9. 从普通vc到tabitem中的一个vc

场景:从实名认证成功页面(该页面为从个人中心也所push的,此页上有个去投资按钮)回到产品页(如下图)

产品页.png

核心代码如下:

//转到产品列表页
- (void)goInvest
{
    self.tabBarController.selectedIndex = 1;
    [self.navigationController popToRootViewControllerAnimated:NO];
}

10. 列表上拉弹回问题

- (void)viewDidLoad {
    [super viewDidLoad];
    self.tableview = [[UITableView alloc]initWithFrame:self.view.bounds style:UITableViewStyleGrouped];
    self.tableview.dataSource = self;
    self.tableview.delegate = self;
    self.tableview.scrollEnabled = YES;
    [self.view addSubview:self.tableview];
}
-(void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    self.tableview.contentSize =CGSizeMake(0, kRowHeight*5+ButtonHeight +40+10);
}

11. 充值(调用第三方宝付接口)

充值接口目前这个版本走的其实都是web,api貌似要贵好多,以后版本公司可能会改用api。多一句,web真的好慢,其实充值这么慢,无形中会流失掉一部分想投资的用户。

#pragma -mark
#pragma -mark 充值获取交易号
- (void)doCharge
{
    NSLog(@"doCharge");
    NSString *token = [PersonalCenterData sharedInstance].userInfo.token;
    if (!token) {
        [self.view makeToast:NoLoginMsg];
        return;
    }
    [[PersonalCenterLogicManager sharedInstance]postChargeWithToken:token amount:[self.tfAmount.text intValue] success:^(NSDictionary *dic) {
        if ([[dic objectForKey:@"code"] isEqualToString:Response_OK]) {
            NSString *tradeNo =[dic objectForKey:@"tradeNo"];
            if (tradeNo) {
                //跳转到第三方宝付充值
                BaoFooPayController*web = [[BaoFooPayController alloc] init];
                web.PAY_TOKEN = tradeNo;
                web.delegate = self;
                [self presentViewController: web animated:YES completion:^{ }];
            }
        }
        else{
            [self.view makeToast:[dic objectForKey:@"message"]];
        }
        
    } failure:^(NSError *err) {
        [self.view makeToast:ServerError];
    }];
}

#pragma mark - BaofooDelegate
-(void)callBack:(NSString*)params
{
    NSLog(@"返回的参数是:%@",params);
    if ([params rangeOfString:@"支付成功"].location != NSNotFound) {
        //条件为真,表示字符串searchStr包含一个自字符串substr
        ChargeSuccessVC *vc = [[ChargeSuccessVC alloc]initWithTitle:@"充值成功"];
        vc.chargeAmount = self.tfAmount.text;
        vc.bankNumber = self.bankInfo.bankNumber;
        [self.navigationController pushViewController:vc animated:NO];
    }else
    {
        //条件为假,表示不包含要检查的字符串
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"提示" message:[NSString stringWithFormat:@"支付结果:%@",params] delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil, nil];
        [alert show];
    }
}

还需待写的有
1 银行选择
2 二级联动城市选择
3 顶部滚动等

连续上7天的班,脑壳都快炸了,回家好好休息😝,看到这里的你,愿你周末愉快!

上一篇 下一篇

猜你喜欢

热点阅读