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

最近写的项目的技术点

作者: 一米押金 | 来源:发表于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秒调用一次
就是这样子的设计方法

相关文章

  • 最近写的项目的技术点

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

  • 无题

    最近空,我想写写技术经历,写写人生经历。 写技术经历时,我遇到了问题,很简单,我用这项技术达成了目的,然而却只是很...

  • 如何写好技术方案

    本文将介绍写技术方案的意义,如何评判技术方案的好坏,如何写好技术方案。 写技术方案的意义 写技术方案根本目的是提高...

  • 最近接触的技术点二

    其实今年我也是才进入到工作岗位不久,因为瘟疫来袭,我所在的城市又被称为“瘟疫之源”,一路之下,我竟然好几个月没了,...

  • 关于AppleDoc的一点使用心得

    因为项目的完成已经接近于收官,所以,昨天经理开始让我整理技术文档,想到一点点慢慢写技术文档的麻烦,就觉得头疼,然...

  • 项目的架构以及技术点

    1111

  • 快速上手系列简要说明

    最近打算开始攒点技术文章,主要是我对一些常见技能的学习总结。 如题,写作的目的是为了“快速上手”,因为某些技术在实...

  • 技术博客的思考

    写技术博客的好处很多,但并不适合每个人。 你应该明确写技术博客的目的。我把目的简单粗暴的分成两种:笔记和营销。为什...

  • angular表单校验

    最近在写项目的时候,产品要求对表单的必填输入项进行友好的校验提示,效果如图: " 这个需求很简单,怎么实现我不管。...

  • 最近写项目的一些小总结

    可变字符串的拼接 如图这段code 报错原来是我声明属性的时候 属性是没有mutableCopy的 所以copy出...

网友评论

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

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