美文网首页
项目总结

项目总结

作者: 小時間光 | 来源:发表于2018-10-23 10:03 被阅读154次

    将近半年多的时间,从产品到设计再到开发,现在我们的APP
    终于进入了公测阶段,利用这段比较轻松的时间对APP中用到的一些技术和自己学到的一些技术做一个总结。

    1、自定义Push和Pop动画,同时有侧滑效果

    如图所示:


    自定义Push和Pop动画
    -(void)pushViewWithData:(NSDictionary *)data{
        
        UIViewController *popView = [[NSClassFromString(@"popViewController") alloc]init];
        SEL aSelector = NSSelectorFromString(@"setdata:");
        if ([popView respondsToSelector:aSelector]) {
            IMP aIMP = [popView methodForSelector:aSelector];
            void (*setter)(id, SEL, NSDictionary*) = (void(*)(id, SEL, NSDictionary*))aIMP;
            setter(popView, aSelector,data);
        }
        CATransition* transition = [CATransition animation];
        transition.duration = 0.35;
        transition.type = kCATransitionMoveIn;
        transition.subtype = kCATransitionFromTop;
        transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];
        [self.navigationController.view.layer addAnimation:transition forKey:kCATransition];
        [self.navigationController pushViewController:popView animated:NO];
    }
    
    -(void)popAnimation{
        
        CATransition* transition = [CATransition animation];
        transition.duration = 0.35;
        transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
        transition.type = kCATransitionReveal;
        transition.subtype = kCATransitionFromBottom;
        [self.navigationController.view.layer addAnimation:transition forKey:kCATransition];
        [self.navigationController popViewControllerAnimated:NO];
    }
    
    

    具体代码可参考demo


    2、animateWithDuration动画修改UIViewframe闪一下然后才有动画效果

    解决方法:使用CGAffineTransform动画实现:

        [UIView animateWithDuration:3 delay:0.1 options:UIViewAnimationOptionCurveEaseInOut animations:^{
    
            [weakSelf.heartbtn setTransform:CGAffineTransformMake(27.0 / 73.0, 0, 0, 27.0 / 73.0, -((ScreenW / 2) - 26.5), 23)];
    
     } completion:^(BOOL finished) {
    
    }];
    
    缩放效果

    3、按钮透明度为0时不响应点击事件

    UIButton透明度为0时,不响应点击事件,我以为是系统的问题,就采用了为'UIView'添加UITapGestureRecognizer事件,但是也出现了同样的问题,当UIView透明度为0时,也不响应点击事件了.个人推测,当UIButton透明度为0时,默认调用Hidden方法,所以不响应点击事件。可设置按钮Type可避免该问题

    _heartbtn = [UIButton buttonWithType: UIButtonTypeCustom];
     [self.view addSubview:_heartbtn];
    

    4、设置圆角

    一般的,在开发中设置UIView的圆角,可直接设置cornerRadius属性,

           self.layer.cornerRadius = 10.f;
    

    但是,在实际的开发中,APP设计师给出的一些View的圆角并不是四个角全部都是圆形,如下面的几张图,那么针对这种情况,就需要用系统为开发者提供的设置贝兹曲线圆角来实现。

    You Send a SWEET Timer Toast
    // MARK: - 设置顶部两个圆角
    -(void)SettingSharaviewRound:(float)Round selfview:(UIView *)selfview
    {
        UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:selfview.bounds byRoundingCorners:UIRectCornerTopLeft | UIRectCornerTopRight cornerRadii:CGSizeMake(Round, Round)];
        CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init];
        maskLayer.frame = selfview.bounds;
        maskLayer.path = maskPath.CGPath;
        selfview.layer.mask = maskLayer;
    }
    

    如果使用Masonry添加约束会导致用以上代码设置圆角不起作用,解决方案是在设置圆角之前调用父viewlayoutIfNeeded方法。

     [superView layoutIfNeeded];
    

    5、通过Blocks来关联UIButton的点击事件

    在开发中通常使用的按钮点击:

        UIButton *chatBtn = [[UIButton alloc]initWithFrame:CGRectMake(100, 100, 100, 44)];
        [self.view addSubview:chatBtn];
            [settingbtn mas_makeConstraints:^(MASConstraintMaker *make) {
                //距离顶部
                make.top.equalTo(weakSelf.mas_top).with.offset(20.f);
                //距离右边
                make.right.equalTo(weakSelf.mas_right).with.offset(-15.f);
                //设置大小
                make.size.mas_equalTo(CGSizeMake(50, 50));
            }];
        [chatBtn addTarget:self action:@selector(TouchChatBtn:) forControlEvents:UIControlEventTouchUpInside];
    
    
    -(void)TouchChatBtn:(UIButton *)sender
    {
      printf("\n================\n");
    }
    

    通过代码关联

    #import <objc/runtime.h>
    
      void (^addTargetBlock)(void) = ^(void){
            
            printf("\n================\n");
        };
        objc_setAssociatedObject(chatBtn, &clickChatBtnType, addTargetBlock, OBJC_ASSOCIATION_COPY_NONATOMIC);
        
        
    
    -(void)TouchChatBtn:(UIButton *)sender
    {
        void(^addTargetBlock)(void) = objc_getAssociatedObject(sender, &clickChatBtnType);
        if(addTargetBlock)
        {
            addTargetBlock();
        }
    }
    

    进一步改进,通过给系统的UIButton添加一个分类来实现

    #import <objc/runtime.h>
    
    //===================================
    //  UIButton 分类
    //===================================
    
    typedef void (^addTargetBlock)(void);
    
    @interface UIButton (Category)
    
    -(void)addTargetEvent:(UIControlEvents)EventType withTargetBlock:(addTargetBlock)TargetBlock;
    
    @end
    
    static const int block_key;
    -(void)addTargetEvent:(UIControlEvents)EventType withTargetBlock:(addTargetBlock)TargetBlock
    {
        objc_setAssociatedObject(self, &block_key, TargetBlock, OBJC_ASSOCIATION_COPY_NONATOMIC);
        [self addTarget:self action:@selector(AddTargetBlocks:) forControlEvents:EventType];
    }
    
    -(void)AddTargetBlocks:(id)sender
    {
        addTargetBlock block = (addTargetBlock)objc_getAssociatedObject(self, &block_key);
        if (block) {
            block();
        }
    }
    

    使用ReactiveObjC框架来监听按钮点击事件

    使用时导入头文件#import "ReactiveObjC.h"

     //===========================
        [[_confirmBtn rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(__kindof UIControl * _Nullable x) {
            
            NSLog(@"=========================");
    
        }];
    

    参考:iOS开发·runtime原理与实践: 关联对象篇

    Effective Objective-C 2.0 第10条:在既有类中使用关联对象存放自定义数据


    6、无动画先pop当前UIViewController,再push到下一个UIViewController

    在一些需求中,从A界面Push到B界面,在从BPush到C,但是从C返回时直接返回到A界面,一般的Pop掉当前界面的同时再Push到一个新的界面会有一个动画效果,针对这种情况,采用的方法是当从B界面Push到C界面时,直接把B从栈中移除。

    //获取跳转实例
      LTBaseViewController *InputNewPasswordView = [[NSClassFromString(@"InputNewPasswordViewController") alloc]init];
    
                // 获取当前路由的控制器数组
                NSMutableArray *vcArray = [NSMutableArray arrayWithArray:self.navigationController.viewControllers];
                // 获取档期控制器在路由的位置
                int index = (int)[vcArray indexOfObject:self];
                // 移除当前路由器
                [vcArray removeObjectAtIndex:index];
                // 添加新控制器
                [vcArray addObject: InputNewPasswordView];
    
                SEL aSelector = NSSelectorFromString(@"setReset_code:");
                if ([InputNewPasswordView respondsToSelector:aSelector]) {
                    IMP aIMP = [InputNewPasswordView methodForSelector:aSelector];
                    void (*setter)(id, SEL, NSString*) = (void(*)(id, SEL, NSString*))aIMP;
                    setter(InputNewPasswordView, aSelector,@"1008611");
                }
    
                [self.navigationController setViewControllers:vcArray animated:YES];
    

    7、Push的同时释放之前的内存

    当用户被其他设备踢掉或者用户主动退出登录时,之前我的处理方式是,直接设置登录界面为windowrootViewController,同时清理本地数据库的数据,出现的问题是每次重新登录APP在手机中的使用内存就会多20+M,个人觉得这是由于我在没有释放掉当前ViewController内存所导致的,所以最终我的做法是:

    (1)、之前的UIViewController已经没有用了,直接释放掉这些内存,跳转时采用popToViewController来实现;
    (2)、干掉并释放掉单例的内存;
    (3)、清理本地数据库的部分数据;
    (4)、移除KVO监听;

    跳转到登录界面,并释放掉栈中的内存

     //获取要跳转的界面
            UIViewController *LoginView = [[NSClassFromString(@"LoginViewController") alloc]init];
            // 获取navigationcontroller的栈
            NSMutableArray *navStack = [thisView.navigationController.childViewControllers mutableCopy];
            // 修改栈
            [navStack replaceObjectAtIndex:0 withObject:LoginView];
            // 重新设置navigation的栈
            [thisView.navigationController setViewControllers:navStack animated:YES];
            // 出栈并跳转至目标控制器(控制器和当前控制器之间的对象将全部释放)
            [thisView.navigationController popToViewController:LoginView animated:true];
    

    释放Socket单例内存 移除KVO监听

    // MARK: - 内存释放
    -(void)ClearData
    {
        [_socket disconnect];
        [_client removeObserver:self forKeyPath:@"status"];
        [_client removeObserver:self forKeyPath:@"loginState"];
        onceToken = 0;
        _client = nil;
    }
    

    8、导入PCH文件之后报错unknown type name 'NSString'

    解决方法:在PCH文件中引用Foundation
    #ifdef __OBJC__
    
    #import <Foundation/Foundation.h>
    
    #endif
    

    9、通过Runtime+分类的方式实现UITextView的placeHolder占位文字

    #import <objc/runtime.h>
    
    @implementation UITextView (Category)
    
    -(void)getplaceholder:(NSString *)placeholderString fontsize:(float)fontsize
    {
        UILabel *placeholder = [[UILabel alloc] init];
        placeholder.text = placeholderString;
        placeholder.numberOfLines = 0;
        placeholder.textColor = [UIColor lightGrayColor];
        [placeholder sizeToFit];
        [self addSubview:placeholder];
        
        self.font = [UIFont systemFontOfSize:fontsize];
        placeholder.font = [UIFont systemFontOfSize:fontsize];
        
        [self setValue:placeholder forKey:@"_placeholderLabel"];
    }
    
    @end
    
    #import "UITextView+Category.h"
    
     UITextView *inputTxt = [[UITextView alloc]init];
        [self.view addSubview:inputTxt];
        [inputTxt mas_makeConstraints:^(MASConstraintMaker *make) {
            //
            make.center.equalTo(weakSelf.view);
            //
            make.size.mas_equalTo(CGSizeMake(250, 120));
        }];
        inputTxt.layer.cornerRadius = 5.f;
        inputTxt.backgroundColor = [UIColor groupTableViewBackgroundColor];
        [inputTxt getplaceholder:@"please input" fontsize:13.5];
    

    效果如图所示

    placeHolder占位文字

    10、查看第三方相关Log日志

    第一步:


    Window-->Devices

    第二步:


    Download
    第三步:
    保存文件

    第四步:


    显示包内容
    第五步:
    Log日志文件

    11、Application Loader stuck at “Authenticating with the iTunes store” when uploading an iOS app

    参考Stack overflow

    参考Apple Developer

    按照里面的做法,执行命令行,修改DNS,开VPN,修改代理,然而并没有什么卵用,折腾到凌晨1点多,公司的网络实在太坑爹,最后手机开个热点,不到20秒,上传成功。


    12、报错 Application tried to push a nil view controller on target

    UIViewController *MySettingsView = [[NSClassFromString(@"MySettingsViewController") alloc]init];
      [self.navigationController pushViewController:MySettingsView animated:YES];
    

    百度搜的是没有初始化storyboard对象造成的,但我的工程中并没有使用storyboard,是因为文件路径缺失造成的,解决方法:
    Target —> Budild Phaes,导入报错的文件即可。


    13、iOS 11之后系统没有导航栏时 WKWebView下移问题

         [(UIScrollView *)[[_webview subviews] objectAtIndex:0] setBounces:NO];
        _webview.scrollView.bounces = NO;
        _webview.scrollView.showsHorizontalScrollIndicator = NO;
        [_webview sizeToFit];
         if(isiPhoneXDevice){
            _webview.scrollView.contentInset = UIEdgeInsetsMake(-44,0,-44,0);
        }else{
            _webview.scrollView.contentInset = UIEdgeInsetsMake(-20,0,0,0);
        }
    

    相关文章

      网友评论

          本文标题:项目总结

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