美文网首页
最近写的项目的技术点

最近写的项目的技术点

作者: 一米押金 | 来源:发表于2019-08-21 15:29 被阅读0次

    1.定位问题(在使用之前一定要在info.plist里设置权限哦)

    // 导包
    #import <CoreLocation/CoreLocation.h>
    
    // 在.m里设置一个变量
    /**
     定位管理
     */
    @property(nonatomic ,strong) CLLocationManager *manager;
    

    定位配置

         _manager = [[CLLocationManager alloc] init];
         _manager.delegate = self;
         //    [manager requestAlwaysAuthorization];
         [_manager requestWhenInUseAuthorization];
         _manager.desiredAccuracy = kCLLocationAccuracyBest;
         _manager.distanceFilter = 1.0;
         [_manager startUpdatingLocation];
    

    pragma mark -- CLLocationManagerDelegate

    - (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations {
    
         CLLocation *currentLocation = [locations lastObject];
         //地理反编码 可以根据坐标(经纬度)确定位置信息(街道 门牌等)
         CLGeocoder *geoCoder = [[CLGeocoder alloc]init];
         [geoCoder reverseGeocodeLocation:currentLocation completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) {
              if (placemarks.count >0) {
                   CLPlacemark *placeMark = placemarks[0];
                   NSString *currentCity = placeMark.locality;
                   if (!currentCity) {
                        currentCity = @"无法定位当前城市";
                   }
                   // 考虑到定位的频繁性,在一开始没有值的时候才刷新表格
                   if (self.location.length <= 0) {
                        // 省 + 市 + 区
                        self.location = [NSString stringWithFormat:@"%@%@%@",placeMark.administrativeArea,currentCity,placeMark.subLocality];
                         [self.tableView reloadData];
                   }
              }
         }];
    }
    

    2.在使用IQKeyboardManager,使用UITableViewController有bug没办法处理,用到tableView,针对输入框键盘弹出挡住了Cell的处理

    // 注册通知
    - (void)registerForKeyboardNotifications {
         [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
         [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillBeHidden:) name:UIKeyboardWillHideNotification object:nil];
    }
    // 通知方法
    - (void)keyboardWillShow:(NSNotification *)aNotification {
         NSDictionary* info = [aNotification userInfo];
         // 注意不要用UIKeyboardFrameBeginUserInfoKey,第三方键盘可能会存在高度不准,相差40高度的问题
         CGSize kbSize = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size;
         if (_insertIndexPath.section > 0) {
              // 修改滚动天和tableView的contentInset
              self.tableView.contentInset = UIEdgeInsetsMake(0, 0, kbSize.height, 0);
              self.tableView.scrollIndicatorInsets = UIEdgeInsetsMake(0, 0, kbSize.height, 0);
    
              // 跳转到当前点击的输入框所在的cell
              [UIView animateWithDuration:0.5 animations:^{
                   [self.tableView scrollToRowAtIndexPath:_insertIndexPath atScrollPosition:UITableViewScrollPositionTop animated:NO];
              }];
         }
    }
    
    - (void)keyboardWillBeHidden:(NSNotification *)aNotification {
         self.tableView.contentInset = UIEdgeInsetsZero;
         self.tableView.scrollIndicatorInsets = UIEdgeInsetsZero;
    }
    

    3.扫描条形码的方法

    1.使用的框架 #import <LBXScanViewController.h>
    2.使用这个的注意事项,因为我这边想要扫描二维码条形码都可以的情况,本来想要直接拖项目,但是发现这个项目用了retain,release方法,所以用pod导入的,导入的方式如下:
    pod 'LBXScan/LBXZXing','~> 2.3'
    pod 'LBXScan/UI','~> 2.3'
    3.写了个控制器继承这个方法
    #import <LBXScanViewController.h>
    @interface DIYScanViewController : LBXScanViewController
    @end
    4.使用这个控制器
    -(void)scannerClick{
         [self.view endEditing:YES];
    
         //  CocoaPods的版本库是有缓存的, 但在使用pod指令更新版本库时会出现冲突, 导致更新并不能如期完成, 需要手动删除本地缓存, 再进行更新。
    //
    //     解决方法:
    //
    //     $ sudo rm -fr ~/.cocoapods/repos/master
    //     $ pod setup
    //
    //     之后重新 pod install 顺利通过
         // Note: as of CocoaPods 1.0, `pod repo update` does not happen on `pod install` by default.
         DIYScanViewController *scanVc = [DIYScanViewController new];
         // 这个要定义LBXScan_Define_UI才能用
         scanVc.style = [self ZhiFuBaoStyle];
         scanVc.isOpenInterestRect = YES;
         scanVc.libraryType = SLT_ZXing;
         WK(weakSelf);
         scanVc.scannerCallBack = ^(NSString *scanStr) {
              weakSelf.express = scanStr;
              weakSelf.inputF.text = weakSelf.express;
              [weakSelf pipeiExpress:self.pipeiBtn];
         };
         [self.navigationController pushViewController:scanVc animated:YES];
    }
    
    - (LBXScanViewStyle*)ZhiFuBaoStyle
    {
         //设置扫码区域参数
         LBXScanViewStyle *style = [[LBXScanViewStyle alloc]init];
         style.centerUpOffset = 60;
         style.xScanRetangleOffset = 30;
    
         if ([UIScreen mainScreen].bounds.size.height <= 480 )
           {
              //3.5inch 显示的扫码缩小
              style.centerUpOffset = 40;
              style.xScanRetangleOffset = 20;
           }
    
         style.photoframeAngleStyle = LBXScanViewPhotoframeAngleStyle_Inner;
         style.photoframeLineW = 2.0;
         style.photoframeAngleW = 16;
         style.photoframeAngleH = 16;
    
         style.isNeedShowRetangle = NO;
         style.anmiationStyle = LBXScanViewAnimationStyle_NetGrid;
    
         style.notRecoginitonArea = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.6];
    
    
         //使用的支付宝里面网格图片
         UIImage *imgFullNet = [UIImage imageNamed:@"CodeScan.bundle/qrcode_scan_full_net"];
         style.animationImage = imgFullNet;
    
         return style;
    }
    5.这里提到一个"定义",所以要在一个通用的文件里进行定义:
    #define LBXScan_Define_ZXing   //下载了ZXing模块
    #define LBXScan_Define_UI     //下载了界面模块
    
    

    4.分享里如果跳转的是自己app的配置

    要在info里配置scheme


    配置scheme.png

    然后测试的话,就在浏览器里输入paproperty://,看是否能进入即可
    这是在测试分享点击的时候我进行的调试,如果不能,就跳到苹果商店这样子的分析

    5.针对图片比较大,我如何获取图片的高度

    图片尺寸配置.png

    由于我这里有个类似商城的项目,详情展示的是商品的大图,由于大图是网络图片,只有一个链接,我参考之前做百思不得姐的demo的时候,它有一个高度值,但是这里却没有,我问后端有没有获取,没有的时候,我不知道该怎么办,我求助师父,它的代码告诉我,sd_webImage这个框架是真的很强力:

    // 设置照片view
         UIView *photoView = [[UIView alloc] init];
         CGFloat tempH = 100;
         NSInteger i = 0;
         for (PALMPicturePicList *picList in self.pics) {
              UIImageView *imageView = [[UIImageView alloc] init];
              imageView.backgroundColor = [UIColor colorWithWhite:0 alpha:0.6];
              imageView.frame = CGRectMake(0, i * tempH, [UIScreen mainScreen].bounds.size.width, tempH);
              imageView.contentMode = UIViewContentModeScaleAspectFill;
              imageView.clipsToBounds = YES;
              [photoView addSubview:imageView];
              [imageView sd_setImageWithURL:[NSURL URLWithString:picList.picUrl] completed:^(UIImage * _Nullable image, NSError * _Nullable error, SDImageCacheType cacheType, NSURL * _Nullable imageURL) {
                   if (image) {
                        CGRect imageViewF = imageView.frame;
                        CGFloat whScale = image.size.width / image.size.height;
                        imageViewF.size.height = imageViewF.size.width / whScale;
                        imageView.frame = imageViewF;
                        [self updatePhotoView];
                   }
              }];
              i ++;
         }
         [self.scrollView addSubview:photoView];
         self.photoView = photoView;
    

    6.附上我常写的展示图片的方法

    // 导包
    #import <UIImageView+WebCache.h>
    #import "MJPhotoBrowser.h"
    #import "MJPhoto.h"
    

    配置

    #pragma mark -- 商品详情的评价区域
    -(void)setupImageView:(NSInteger)count{
         for (UIImageView *imgView in self.picView.subviews) {
              [imgView removeFromSuperview];
         }
    
         int maxColumns = 3;
         CGFloat IWPhotoMargin = 10;
         CGFloat IWPhotoW = (kScreenW - IWPhotoMargin * 2 - 13 - 59)/3;
         CGFloat IWPhotoH = IWPhotoW;
         // 初始化9个子控件
         for (int i = 0; i<count; i++) {
              UIImageView *photoView = [[UIImageView alloc] init];
              photoView.userInteractionEnabled = YES;
              photoView.tag = i + 100;
               
              // 设置图片链接(这里可能传的是一个模型,不一定是个简单的url字符串)
              PALMCommentsPicList *picList = self.pics[i];
              NSURL *url = [NSURL URLWithString:picList.picUrl];
              [photoView sd_setImageWithURL:url placeholderImage:[UIImage imageNamed:@"shequdefault"]];
    
              [photoView addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(photoTap:)]];
              // 设置子控件的frame
              int col = i % maxColumns;
              int row = i / maxColumns;
              CGFloat photoX = col * (IWPhotoW + IWPhotoMargin);
              CGFloat photoY = row * (IWPhotoH + IWPhotoMargin);
              photoView.frame = CGRectMake(photoX, photoY, IWPhotoW, IWPhotoH);
              [self.picView addSubview:photoView];
         }
    }
    
    - (void)photoTap:(UITapGestureRecognizer *)recognizer
    {
         //确定photo的张数
         NSInteger count = self.pics.count;
    
         // 1.封装图片数据
         NSMutableArray *myphotos = [NSMutableArray arrayWithCapacity:count];
         for (int i = 0; i<count; i++)
           {
              // 一个MJPhoto对应一张显示的图片
              MJPhoto *mjphoto = [[MJPhoto alloc] init];
              // 告诉URL,来源于哪个UIImageView(目的:点击这个图片变大之后,再点击要还原到那个位置)
              mjphoto.srcImageView = self.picView.subviews[i];
              // 设置图片链接(这里可能传的是一个模型,不一定是个简单的url字符串)
              PALMCommentsPicList *picList = self.pics[i];
              mjphoto.url = [NSURL URLWithString:picList.picUrl]; // 图片路径
              [myphotos addObject:mjphoto];
           }
    
         // 2.显示相册
         MJPhotoBrowser *browser = [[MJPhotoBrowser alloc] init];
         browser.currentPhotoIndex = recognizer.view.tag - 100; // 弹出相册时显示的第一张图片是?
         browser.photos = myphotos; // 设置所有的图片
         [browser show];
    }
    

    7.上线遇到的麻烦

    上线的屏幕尺寸.jpg

    遇到过,就是苹果开发者里显示的可供销售,但是app商城就是查不到,此时可以考虑修改价格和销售范围,然后再改回来,如果还是不行,那就只能干等,至于等待多久,我暂时找不到答案了。

    8.内购(待续)

    注意点.png

    这里需要注意的是,CNAPS代码里,进行银行搜索的时候,银行,所在地址,都要输入英文,然后银行的地址也写的比较麻烦,我也是搜索了很久才搜索到,特别是用邮编定位的时候,大家虽然都知道武汉的邮编是430000,但是集合太大,可以搜索到很多的银行,然而开户的位置就只有那一家,所以在这里花费了不少功夫,所以目前情况,要么问银行工作人员,要么就是找到一个比较精确的地址,然后去分析,由于地址列表都是英文,所以得借助下翻译,要搞清楚自己在哪个地区,毕竟武汉那么大,硚口区,武昌区,东西湖区。。。。
    然后账户持有人姓名,这里是要输入英文的,输入中文是不作数的

    报税表什么的,其实就没什么了,就是按照苹果的协议,选择公司所需求的即可,然后工作人员的信息的话,可以全部只填写一个人,也没什么大问题,然后后续就是价格的配置
    通过appstoreConnect->我的app,找到需要写价格的app,如图


    项目.png

    点击加号即可增加商品,下方的列表就是我配置的商品,其中产品ID要设计明确,这个id根据后续自己的设计的产品的id息息相关的,要注意,设计的办法可以"xxxxx_产品的价格",比方说10元的爱心豆,即"lovebean_10"
    这里的参考名称相当于标记,没有什么可以参考的

    点击添加按钮展示的菜单,要注意的:


    appStore信息.png

    这里本地化版本就是,要展示给用户看的,描述的是到后来你在布置模型里一个叫skproduct的模型里的一个参数,显示名称这个是给用户看的,很有必要

    审核图片标准.png

    这里就需要美工切一张图片给我们了,审核的备注的话,写一些备注信息就可以了,然后提交只有只有是“准备提交”,那才算是设置好,不然就去查看下为何设置错误了

    添加沙箱测试人员.png

    在这里添加沙箱测试人员,注意里面的邮箱是没有在苹果里注册的,密码也需要牢牢记住,后续内购支付里派上用场的,因为不可能一直用自己的账户进行测试,这钱流的杠杠的,也不能在配置金额里手动输入一毛钱,所以得配置一个沙盒的账号进行内购测试

    此时前奏配置已经完成,后续就是打开xcode把这个打开


    purchase.png

    导包#import <StoreKit/StoreKit.h>

    然后就是要注意的细节了
    细节1,就是要跟后端配合,后端准备的价格和商品,要跟我在苹果里设置的要一一对应,一一添加,比方说我配置了“1,3,6,12,18,30”元的商品,后端也要这么配置,而且按价格顺序配置,我这边需要做的就是根据价格,然后设计一个数组依次添加,我们之前不是设置了一个商品id么?这时候作用就出来了
    前缀是我们的“xxx_” 后缀是价格,""这么一拼接,就是添加的id了
    值得注意的是,即便这么添加然后发送请求的时候

                        // 能够销售的商品
                        NSSet *set = [[NSSet alloc] initWithArray:products];
                        // "异步"询问苹果能否销售
                        SKProductsRequest *request = [[SKProductsRequest alloc] initWithProductIdentifiers:set];
                        request.delegate = weakSelf;
                        // 启动请求
                        [request start];
    

    会发现产品的数组是个乱序,所以要在代理方法里进行一次排序,保证顺序是产品需求的样式,跟后端进行一一比对

    #pragma mark -- SKProductsRequestDelegate
    /**
     获取内购商品的请求(请求苹果服务器,所以会很慢)
     */
    -(void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response{
         // 获取内购商品的请求
         if (self.productDict == nil) {
              self.productDict = [NSMutableDictionary dictionaryWithCapacity:response.products.count];
         }
         NSMutableArray *productArray = [NSMutableArray array];
         // 按照价格进行排序
         NSArray *sorctProducts = [response.products sortedArrayUsingComparator:^NSComparisonResult(SKProduct *obj1, SKProduct *obj2) {
              return [obj1.price compare:obj2.price];//升序
         }];
         for (SKProduct *product in sorctProducts) {
              [self.productDict setObject:product forKey:product.productIdentifier];
              // 按照价格进行排序
              [productArray addObject:product];
         }
    
         if ([self.delegate respondsToSelector:@selector(IAPToolGotProducts:ChargeData:)]) {
              [self.delegate IAPToolGotProducts:productArray ChargeData:self.chargeData];
         }
    }
    

    最后就是逻辑上的注意了,因为内购是给苹果服务器发送内购消息,所以请求的时间上会很卡,而且内购成功之后也需要跟后端进行订单校验,只有成功了才会把爱心豆加到用户的账户。。

    所以会出现一些漏单操作(比方说用户第一次绑定支付宝,可能会默认内购失败,比方说在拿着内购验签的时候,内购成功了,但是服务器请求失败了的操作)

    处理的方式的话,就要在这个代理方法里分析,到底漏单的环节在哪里

    #pragma mark -- SKPaymentTransactionObserver
    /**
     *  监测购买队列的变化(订单的成功,失败与取消都会在这里产生)
     *
     *  @param queue        队列
     *  @param transactions 交易
     */
    -(void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(nonnull NSArray<SKPaymentTransaction *> *)transactions{
         // 处理结果
         for (SKPaymentTransaction *transaction in transactions) {
              ZRLog(@"队列状态变化 %@", transaction);
              // 队列状态发生了错误
              if (transaction.error) {
                   [self showErrorTipWith:transaction.error.localizedDescription andStyle:SVProgressHUDStyleDark];
                   return ;
              }
              // 如果小票状态是购买完成
              if (transaction.transactionState == SKPaymentTransactionStatePurchased) { // 购买完成(销毁交易)
                   [self showLoadingWihtBlackBackgroundAndString:@"加载中..." andMaskType:SVProgressHUDMaskTypeBlack];
                   if (self.CheckAfterPay) {// 需要向苹果验证凭据
                        // 验证购买凭据
                        [self verifyPruchaseWithID:transaction];
                   }else{// 不需要向苹果服务器验证
    
                   }
                   [self showDisminss];
                   // 将交易从交易队列中删除
                   [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
              } else if (transaction.transactionState == SKPaymentTransactionStateRestored) { // 恢复购买(销毁交易)
                   [self showDisminss];
                   // 恢复已经完成的所有交易.(仅限永久有效商品)
                   // 将交易从交易队列中删除
                   [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
              }else if (transaction.transactionState == SKPaymentTransactionStateFailed){ // 购买失败(销毁交易)
                   [self showErrorTipWith:@"购买失败" andStyle:SVProgressHUDStyleDark];
                   // 将交易从交易队列中删除
                   [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
                   [self showDisminss];
    #pragma mark -- 由于目前只监听支付成功然后我校验的回调,所以这里没有接口处理
                   // 删除本地订单数据
                   [PAInPurchaseTool successConsumptionOfGoodsWithOrderNo:transaction.transactionIdentifier];
              }else if (transaction.transactionState == SKPaymentTransactionStatePurchasing){ // 正在购买
                   [self showLoadingWihtBlackBackgroundAndString:@"正在购买中..." andMaskType:SVProgressHUDMaskTypeBlack];
                   ZRLog(@"商品正在准备购买中...");
              }else if (transaction.transactionState == SKPaymentTransactionStateDeferred){ // 交易延迟
                   ZRLog(@"购买交易延迟");
                   [self showDisminss];
                   // 将交易从交易队列中删除
                   [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
              }
         }
    }
    

    在这里找到购买的逻辑,以上代码都是只展示逻辑,不能用在自己其他项目直接拷贝的

    我这里也做了标记,就是监听成功回调,其他的都不会请求后端了
    所以就放在购买成功里的服务器校验

    目前的方法是:
    我在请求之前,我先跟苹果端的校验一次,然后成了之后,把这个订单根据一个重要的主键(我这里选择的是账单的订单号),保存到本地,然后再请求服务器进行校验,如果请求成功,且结果返回是需要的,那么就刷新爱心豆,反之都算漏单,然后再次启动app的时候调用恢复单据的接口,我设置的是每20秒调用一次
    就是这样子的设计方法

    相关文章

      网友评论

          本文标题:最近写的项目的技术点

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