• 封装AFN3.1并且封装自定义alertView

好久没写博客了,最近项目接近上线,加班也多了,把最近更新的afn封装了下,同时封装的还有一个自定义的提示框。简单的利用一个写好的框架。

  • 一、封装AFN

  • AFN3.1里更新了很多东西,这里只封装了一下如何上传图片并且返回进度条
  • 首先,我们需要定义三个block,用来把进度,成功后返回的数据和失败返回的error

      /**定义请求成功的block*/
      typedef void(^requestSuccess)( NSDictionary * responseObject);
        
      /**定义请求失败的block*/
      typedef void(^requestFailure)( NSError *error);
        
      /**定义上传进度block*/
      typedef void(^uploadProgress)(CGFloat progress);
    
  • 接着导入AFNetworking.h,并且写方法名字。这里,因为上传图片的时候有图片类型,图片名字,文件名字等,并且有可能上传多张图片,所以我们在封装的时候要把所有的问题都考虑进去,因此,封装以及参数如下:

      /**
      *  上传图片
      *
      *  @param baseUrlStr   baseUrlStr
      *  @param appendUrlStr appendUrlStr
      *  @param para         参数
      *  @param imageArray   图片数组
      *  @param successBlock 成功block
      *  @param failureBlock 失败block
      *  @param progress     上传进度
      */
      +(void)UPDATA_baseUrlStr:(NSURL *)baseUrl
              appendUrlStr:(NSString *)appendUrlStr
                  parameters:(NSDictionary *)para
              withImageArr:(NSArray *)imageArray
                  sourceName:(NSArray *)nameArr
                  fileName:(NSArray *)fileNameArr
                  mimeType:(NSString *)type
          withSuccessBlock:(requestSuccess)successBlock
              withFailurBlock:(requestFailure)failureBlock
          withUpLoadProgress:(uploadProgress)progressUp;
    
  • 接着在.m里实现方法如下:

      /**
       *  上传图片
       *
       *  @param baseUrlStr   baseUrlStr
       *  @param appendUrlStr appendUrlStr
       *  @param para         参数
       *  @param imageArray   图片数组
       *  @param successBlock 成功block
       *  @param failureBlock 失败block
       *  @param progressUp   上传进度
       */
      +(void)UPDATA_baseUrlStr:(NSURL *)baseUrl
                  appendUrlStr:(NSString *)appendUrlStr
                    parameters:(NSDictionary *)para
                  withImageArr:(NSArray *)imageArray
                    sourceName:(NSArray *)nameArr
                      fileName:(NSArray *)fileNameArr
                      mimeType:(NSString *)type
              withSuccessBlock:(requestSuccess)successBlock
               withFailurBlock:(requestFailure)failureBlock
            withUpLoadProgress:(uploadProgress)progressUp
      {
          NSMutableArray *tempSourceNameArr = [NSMutableArray array];
          NSMutableArray *tempFileNameArr = [NSMutableArray array];
          if (nameArr.count > 0) {
              [tempSourceNameArr addObjectsFromArray:nameArr];
          }else {
              for (int i = 0; i < imageArray.count; i ++) {
                  [tempSourceNameArr addObject: [NSString stringWithFormat:@"name%d",i]];
              }
          }
            
          if (fileNameArr.count > 0) {
              [tempFileNameArr addObjectsFromArray:fileNameArr];
          }else {
              for (int i = 0; i < imageArray.count; i ++) {
                  [tempFileNameArr addObject: [NSString stringWithFormat:@"image%d",i]];
              }
          }
            
          AFHTTPSessionManager *manager = [[AFHTTPSessionManager alloc]initWithBaseURL:baseUrl];
          manager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"text/html",@"text/plain",nil];
          NSString *mimeTypeStr = [NSString stringWithFormat:@"image/%@",type];
            
          [manager POST:appendUrlStr parameters:para constructingBodyWithBlock:^(id<AFMultipartFormData>  _Nonnull formData) {
              int j = 0;
              for (UIImage *image in imageArray) {
                  NSData *imgData;
                  if ([type isEqualToString:@"jpg"]) {
                      imgData = UIImageJPEGRepresentation(image, 0.5);
                  } else
                  {
                      imgData = UIImagePNGRepresentation(image);
                  }
                  [formData appendPartWithFileData:imgData name:[tempSourceNameArr objectAtIndex:j] fileName:[tempFileNameArr objectAtIndex:j] mimeType:mimeTypeStr];
                  j++;
              }
          } progress:^(NSProgress * _Nonnull uploadProgress) {
      //        NSLog(@"......fractionCompleted:%f",uploadProgress.fractionCompleted);
      //        NSLog(@"......completedUnitCount:%lld",uploadProgress.completedUnitCount);
      //        NSLog(@"......totalUnitCount:%lld",uploadProgress.totalUnitCount);
                
              if (uploadProgress.totalUnitCount != 0.00) {
                  CGFloat progress = uploadProgress.completedUnitCount/(CGFloat)uploadProgress.totalUnitCount;
                  progressUp(progress);
              }
                
          } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
              successBlock(responseObject);
          } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
              failureBlock(error);
          }];
          
      }
    
  • 需要注意的是,在progress上传进度的传回来的进度里,传回来的是一个NSProgress类,点击去可以看到,这个类里有一个属性,叫fractionCompleted,这个属性是double型的。然而,问题来了,当我们打印这个属性的时候发现,这个属性会先传过来1,然后再传过来0.12、0.23等等浮点型的进度条。那我们没有办法了嘛?当然不是。参考属性我们可以看到,NSProgress里还有两个属性:uploadProgress.completedUnitCount和uploadProgress.totalUnitCount。前者是已经上传的资源总数,后者是所上传的资源的总字节数。通过两者相处,可以得出进度条的百分比。因此,可以通过progress把两者的商传出去。

      CGFloat progress = uploadProgress.completedUnitCount/(CGFloat)uploadProgress.totalUnitCount;
      progressUp(progress);
    

这样,就可以得到上传进度了。

  • AFN封装就这样完成了。

  • 二、封装提示框

  • 首先是github上的一个还不错的库,我稍微改动了一下,把“取消”和“确定”按钮都传了出去,为了修改背景色,文字颜色等。

      typedef void(^LXAlertClickIndexBlock)(NSInteger clickIndex,UIButton *cancelBtn,UIButton *otherBtn);
    
  • 然后我们要定义一下动画类型,类型为枚举类型:

      typedef NS_ENUM(NSInteger , LXAShowAnimationStyle) {
          LXASAnimationDefault    = 0,
          LXASAnimationLeftShake  ,
          LXASAnimationTopShake   ,
          LXASAnimationNO         ,
      };
    
  • 接着我们写方法.

      @property (nonatomic,copy)LXAlertClickIndexBlock clickBlock;
        
      @property (nonatomic,assign)LXAShowAnimationStyle animationStyle;
    
    
      /**
       *  初始化alert方法(根据内容自适应大小,目前只支持1个按钮或2个按钮)
       *
       *  @param title         标题
       *  @param titleColor    标题颜色
       *  @param message       内容(根据内容自适应大小)
       *  @param messageColor  内容颜色
       *  @param cancelTitle   取消按钮
       *  @param otherBtnTitle 其他按钮
       *  @param block         点击事件block
       *
       *  @return 返回alert对象
       */
      -(instancetype)initWithTitle:(NSString *)title
                        titleColor:(UIColor *)titleColor
                           message:(NSString *)message
                      messageColor:(UIColor *)messageColor
                    cancelBtnTitle:(NSString *)cancelTitle
                     otherBtnTitle:(NSString *)otherBtnTitle
                   clickIndexBlock:(LXAlertClickIndexBlock)block;
        
      /**
       *  showLXAlertView
       */
      -(void)showLXAlertView;
        
      /**
       *  不隐藏,默认为NO。设置为YES时点击按钮alertView不会消失(适合在强制升级时使用)
       */
      @property (nonatomic,assign)BOOL dontDissmiss;
    
  • 这里我们又搞出一个clickBlock,是为了捕捉按钮的点击事件。方法实现如下:

      -(instancetype)initWithTitle:(NSString *)title
                        titleColor:(UIColor *)titleColor
                           message:(NSString *)message
                      messageColor:(UIColor *)messageColor
                    cancelBtnTitle:(NSString *)cancelTitle
                     otherBtnTitle:(NSString *)otherBtnTitle
                   clickIndexBlock:(LXAlertClickIndexBlock)block
      {
          if(self=[super init]){
              self.frame=MainScreenRect;
              self.backgroundColor=[UIColor colorWithWhite:.3 alpha:.7];
                
              _alertView=[[UIView alloc] init];
              _alertView.backgroundColor=[UIColor whiteColor];
              _alertView.layer.cornerRadius=6.0;
              _alertView.layer.masksToBounds=YES;
              _alertView.userInteractionEnabled=YES;
                
                
              if (title) {
                  _titleLab=[[UILabel alloc] initWithFrame:CGRectMake(0, 10, AlertView_W, LXATitle_H)];
                  _titleLab.text=title;
                  _titleLab.textAlignment=NSTextAlignmentCenter;
                  _titleLab.font=LXADTitleFont;
        
                  if (titleColor) {
                      _titleLab.textColor=titleColor;
                  }else{
                      _titleLab.textColor=[UIColor blackColor];
                  }
              }
                
              CGFloat messageLabSpace = 25;
              _messageLab=[[UILabel alloc] init];
              _messageLab.backgroundColor=[UIColor whiteColor];
              _messageLab.text=message;
              if (messageColor) {
                  _messageLab.textColor=messageColor;
              }else{
                  _messageLab.textColor=[UIColor lightGrayColor];
              }
              _messageLab.font=LXADMessageFont;
              _messageLab.numberOfLines=0;
              _messageLab.textAlignment=NSTextAlignmentCenter;
              _messageLab.lineBreakMode=NSLineBreakByTruncatingTail;
              _messageLab.characterSpace=2;
              _messageLab.lineSpace=3;
              CGSize labSize = [_messageLab getLableRectWithMaxWidth:AlertView_W-messageLabSpace*2];
              CGFloat messageLabAotuH = labSize.height < MessageMin_H?MessageMin_H:labSize.height;
              CGFloat endMessageLabH = messageLabAotuH > MessageMAX_H?MessageMAX_H:messageLabAotuH;
              _messageLab.frame=CGRectMake(messageLabSpace, _titleLab.frame.size.height+_titleLab.frame.origin.y+10, AlertView_W-messageLabSpace*2, endMessageLabH);
                
                
              //计算_alertView的高度
              _alertView.frame=CGRectMake(0, 0, AlertView_W, _messageLab.frame.size.height+LXATitle_H+LXABtn_H+40);
              _alertView.center=self.center;
              [self addSubview:_alertView];
              [_alertView addSubview:_titleLab];
              [_alertView addSubview:_messageLab];
                
              if (cancelTitle) {
                  _cancelBtn=[UIButton buttonWithType:UIButtonTypeCustom];
                  [_cancelBtn setTitle:cancelTitle forState:UIControlStateNormal];
                  [_cancelBtn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
                  [_cancelBtn setBackgroundImage:[UIImage imageWithColor:SFQLightGrayColor] forState:UIControlStateNormal];
                  _cancelBtn.titleLabel.font=LXADBtnTitleFont;
                  _cancelBtn.layer.cornerRadius=3;
                  _cancelBtn.layer.masksToBounds=YES;
                  [_cancelBtn addTarget:self action:@selector(YBAlerBtnClick:) forControlEvents:UIControlEventTouchUpInside];
                  [_alertView addSubview:_cancelBtn];
              }
                
              if (otherBtnTitle) {
                  _otherBtn=[UIButton buttonWithType:UIButtonTypeCustom];
                  [_otherBtn setTitle:otherBtnTitle forState:UIControlStateNormal];
                  [_otherBtn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
                  _otherBtn.titleLabel.font=LXADBtnTitleFont;
                  _otherBtn.layer.cornerRadius=3;
                  _otherBtn.layer.masksToBounds=YES;
                  [_otherBtn setBackgroundImage:[UIImage imageWithColor:SFQMainColor] forState:UIControlStateNormal];
                  [_otherBtn addTarget:self action:@selector(YBAlerBtnClick:) forControlEvents:UIControlEventTouchUpInside];
                  [_alertView addSubview:_otherBtn];
              }
                
              CGFloat btnLeftSpace = 40;//btn到左边距
              CGFloat btn_y = _alertView.frame.size.height-40;
              if (cancelTitle && !otherBtnTitle) {
                  _cancelBtn.tag=0;
                  _cancelBtn.frame=CGRectMake(btnLeftSpace, btn_y, AlertView_W-btnLeftSpace*2, LXABtn_H);
              }else if (!cancelTitle && otherBtnTitle){
                  _otherBtn.tag=0;
                  _otherBtn.frame=CGRectMake(btnLeftSpace, btn_y, AlertView_W-btnLeftSpace*2, LXABtn_H);
              }else if (cancelTitle && otherBtnTitle){
                  _cancelBtn.tag=0;
                  _otherBtn.tag=1;
                  CGFloat btnSpace = 20;//两个btn之间的间距
                  CGFloat btn_w =(AlertView_W-btnLeftSpace*2-btnSpace)/2;
                  _cancelBtn.frame=CGRectMake(btnLeftSpace, btn_y, btn_w, LXABtn_H);
                  _otherBtn.frame=CGRectMake(_alertView.frame.size.width-btn_w-btnLeftSpace, btn_y, btn_w, LXABtn_H);
              }
                
              block(1111111,_cancelBtn,_otherBtn);
              self.clickBlock=block;
                
          }
          return self;
      }
        
        
      -(void)YBAlerBtnClick:(UIButton *)btn{
            
          if (self.clickBlock) {
              self.clickBlock(btn.tag,nil,nil);
          }
            
          if (!_dontDissmiss) {
              [self dismissAlertView];
          }
            
      }
        
      -(void)setDontDissmiss:(BOOL)dontDissmiss{
          _dontDissmiss=dontDissmiss;
      }
        
      -(void)showLXAlertView{
            
            
            
          _alertWindow=[[UIWindow alloc] initWithFrame:MainScreenRect];
          _alertWindow.windowLevel=UIWindowLevelAlert;
          [_alertWindow becomeKeyWindow];
          [_alertWindow makeKeyAndVisible];
            
          [_alertWindow addSubview:self];
            
          [self setShowAnimation];
            
      }
        
      -(void)dismissAlertView{
          [self removeFromSuperview];
          [_alertWindow resignKeyWindow];
      }
        
      -(void)setShowAnimation{
            
          switch (_animationStyle) {
                    
              case LXASAnimationDefault:
              {
                  [UIView animateWithDuration:0 delay:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
                      [_alertView.layer setValue:@(0) forKeyPath:@"transform.scale"];
                  } completion:^(BOOL finished) {
                      [UIView animateWithDuration:0.23 delay:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
                          [_alertView.layer setValue:@(1.2) forKeyPath:@"transform.scale"];
                      } completion:^(BOOL finished) {
                          [UIView animateWithDuration:0.09 delay:0.02 options:UIViewAnimationOptionCurveEaseInOut animations:^{
                              [_alertView.layer setValue:@(.9) forKeyPath:@"transform.scale"];
                          } completion:^(BOOL finished) {
                              [UIView animateWithDuration:0.05 delay:0.02 options:UIViewAnimationOptionCurveEaseInOut animations:^{
                                  [_alertView.layer setValue:@(1.0) forKeyPath:@"transform.scale"];
                              } completion:^(BOOL finished) {
                                    
                              }];
                          }];
                      }];
                  }];
              }
                  break;
                    
              case LXASAnimationLeftShake:{
            
                  CGPoint startPoint = CGPointMake(-AlertView_W, self.center.y);
                  _alertView.layer.position=startPoint;
                    
                  //damping:阻尼,范围0-1,阻尼越接近于0,弹性效果越明显
                  //velocity:弹性复位的速度
                  [UIView animateWithDuration:.8 delay:0 usingSpringWithDamping:.5 initialSpringVelocity:1.0 options:UIViewAnimationOptionCurveEaseIn animations:^{
                      _alertView.layer.position=self.center;
                        
                  } completion:^(BOOL finished) {
                        
                  }];
              }
                  break;
                    
              case LXASAnimationTopShake:{
                    
                  CGPoint startPoint = CGPointMake(self.center.x, -_alertView.frame.size.height);
                  _alertView.layer.position=startPoint;
                    
                  //damping:阻尼,范围0-1,阻尼越接近于0,弹性效果越明显
                  //velocity:弹性复位的速度
                  [UIView animateWithDuration:.8 delay:0 usingSpringWithDamping:.5 initialSpringVelocity:1.0 options:UIViewAnimationOptionCurveEaseIn animations:^{
                      _alertView.layer.position=self.center;
                        
                  } completion:^(BOOL finished) {
                        
                  }];
              }
                  break;
                    
              case LXASAnimationNO:{
                    
              }
                    
                  break;
                    
              default:
                  break;
          }
            
      }
        
        
      -(void)setAnimationStyle:(LXAShowAnimationStyle)animationStyle{
          _animationStyle=animationStyle;
      }
        
      @end
        
        
        
        
        
      @implementation UIImage (Colorful)
        
      + (UIImage *)imageWithColor:(UIColor *)color
      {
          CGRect rect = CGRectMake(0.0f, 0.0f, 1.0f, 1.0f);
          UIGraphicsBeginImageContext(rect.size);
          CGContextRef context = UIGraphicsGetCurrentContext();
            
          CGContextSetFillColorWithColor(context, [color CGColor]);
          CGContextFillRect(context, rect);
            
          UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
          UIGraphicsEndImageContext();
            
          return image;
      }
    
  • 完成上一步以后,把它封装在YBAFN.h里;

      /**
       *  自定义提醒
       *
       *  @param str   提醒文字
       *  @param style 动画风格
       */
      +(void)YB_alertViewWithShowStr:(NSString *)str withStyle:(LXAShowAnimationStyle)style
      {
          LXAlertView *alert = [[LXAlertView alloc] initWithTitle:@"提示" titleColor:[UIColor blackColor] message:str messageColor:[UIColor grayColor] cancelBtnTitle:nil otherBtnTitle:@"确定" clickIndexBlock:^(NSInteger clickIndex, UIButton *cancelBtn, UIButton *otherBtn) {
          }];
          if (!style) {
              style = LXASAnimationTopShake;
          }
          alert.animationStyle=style;
          [alert showLXAlertView];
      }
        
        
      + (LXAlertView *)YB_alertViewContent:(NSString *)showStr WithStyle:(LXAShowAnimationStyle)style indexBlock:(void (^)(NSInteger btnIndex))indexBlock
      {
          LXAlertView *alert = [[LXAlertView alloc] initWithTitle:@"提示" titleColor:[UIColor blackColor] message:showStr messageColor:[UIColor grayColor] cancelBtnTitle:nil otherBtnTitle:@"确定" clickIndexBlock:^(NSInteger clickIndex, UIButton *cancelBtn, UIButton *otherBtn) {
                
          }];
          alert.clickBlock = ^(NSInteger clickIndex,UIButton *cancelBtn,UIButton *otherBtn){
              indexBlock(clickIndex);
          };
          alert.animationStyle=style;
          [alert showLXAlertView];
          return alert;
      }
    
  • 在程序中调用:

      [YBAFN YB_alertViewContent:@"这是用来测试的呀" WithStyle:LXASAnimationLeftShake indexBlock:^(NSInteger btnIndex) {
              if (btnIndex == 0) {
                  NSLog(@"点击了确定");
              }
          }];
    
  • 动图如下:

效果图

  • 至此,大功告成。项目照例放在此:DEMO