美文网首页
iOS 杂记(持续更新)

iOS 杂记(持续更新)

作者: Mory | 来源:发表于2017-04-06 16:59 被阅读55次

    文件下载或者上传后需要使用 MD5验证文件的完整性,不可简单的根据上传或下载完成后的回调来判断是否成功。

    • tabview 和 collectionView的长按抖动模式

    #pragma mark - 抖动动画
    #define Angle2Radian(angle) ((angle) / 180.0 * M_PI)
    - (void)shakingAnimation:(UICollectionViewCell *)cell{
        CAKeyframeAnimation *anim = [CAKeyframeAnimation animation];
        anim.keyPath = @"transform.rotation";
        
        anim.values = @[@(Angle2Radian(-2)), @(Angle2Radian(2)), @(Angle2Radian(-2))];
        anim.duration = 0.25;
        
        // 动画次数设置为最大
        anim.repeatCount = MAXFLOAT;
        // 保持动画执行完毕后的状态
        anim.removedOnCompletion = NO;
        anim.fillMode = kCAFillModeForwards;
        
        [cell.layer addAnimation:anim forKey:@"shake"];
    }
    
    • 逐行读取 txt 文件内容,将所需内容取出

    #txt文件文件内容大概是这个样子的,x 和 y 的长度还不一样,但是最前面的是一样的长度,所以下面用的方式不一样
    53282 X:13435840.64291;Y:3550350.6154879997
    53280 X:13435846.923805503;Y:3550349.5415525
    53279 X:13435853.009440003;Y:3550349.639183
    53278 X:13435859.062531002;Y:3550349.5740960003
    
       #//获取txt 文件
        NSString *pathTxt =  [[NSBundle mainBundle] pathForResource:@"iBeaconPoint" ofType:@"txt"];
        //逐行添加到数组中
        NSArray *arr = [[NSString stringWithContentsOfFile:pathTxt] componentsSeparatedByString:@"\n"];
        //准备遍历数组
        NSEnumerator *enmu = [arr objectEnumerator];
        
        while (NSString *tmp = [enmu nextObject]) {
         //因为取出的内容为 nextObject,所以在下面判断取到的字符串长度不得=0
            if (tmp.length == 0) {
                break;
            }
            NSString *strMinor = nil;
            NSString *strX = nil;
            NSString *strY = nil;
            //截取字符串
            strMinor = [tmp substringWithRange:NSMakeRange(0,5)];
            //扫描对象
            NSScanner *scanner = [NSScanner scannerWithString:tmp];
            //用不同的特征获取数据
            [scanner scanUpToString:@"X:" intoString:nil];
            [scanner scanString:@"X:" intoString:nil];
            [scanner scanUpToString:@";" intoString:&strX];
            
            [scanner scanUpToString:@"Y:" intoString:nil];
            [scanner scanString:@"Y:" intoString:nil];
            [scanner scanUpToString:@";" intoString:&strY];
            
            
            NSLog(@"%@,%@,%@",[strX description],[strY description],[strMinor description]);
        }
    
    • 引用下别人的总结知识点,相当全面

    http://www.jianshu.com/p/1ff9e44ccc78

    • 如何判断文件类型

    这是链接,主要还是搜集文件头标示建立数据,以便在后面进行判断http://blog.csdn.net/yagerfgcs/article/details/51427085

    • Xcode注释快捷键

    command+option+/      -> 快速注释(不同的位置不一样)
    command+/             -> 双斜线
    
    • MacOS终端可以集成了MD5加密功能。输入命令:echo "待加密字符串" | md5
    • Widget 使用图片也是必不可少,然而 imageNamed: 和 imageWithContentsOfFile: 两种方式加载都不行,即使设置了文件的 target 为 Widget Extension,需要在其target 内部建立一个 .xcassets 文件即可加载图片。
    • dispatch_after 设置延时操作,是进行延时提交到操作队列,并不是先提交队列再延时。
    • 防止 app 审核不通过,在自定义目录数据存储的时候,需要在程序中给自定义的目录设置“do not backup”属性,防止数据会被 iCloud 备份,从而被拒上架。
    • 注销登录,直接回到登录界面

    /**
      退出登录后需要 再获取主窗口 然后设置他的根控制器为登录界面
     */
       NavController *nav = [[NavController alloc] initWithRootViewController:[[MainLoginController alloc] init]];
       [UIApplication sharedApplication].keyWindow.rootViewController = nav;
    /
    如果要跳转的视图界面已将存在导航栏,则直接
    [UIApplication sharedApplication].keyWindow.rootViewController = yourViewController;
    
    • 多层模态视图,直接回到 root 视图,瞒天过海

        UIViewController *rootVC = self.presentingViewController;
        
        while (rootVC.presentingViewController) {
            rootVC = rootVC.presentingViewController;
        }
        
        rootVC.view.alpha = 0.0;
        [rootVC dismissViewControllerAnimated:YES completion:nil];
    
    • 导航栏隐藏界面push 到导航栏显示界面的过渡方案

    • 1,第一种
    //当前界面隐藏
           -(void)viewWillAppear(BOOL)animated{
                [super viewWillAppear:animated];
                [self.navigationController setNavigationBarHidden:YES animated:YES];
            }
     //下个界面显示
            -(void)viewWillAppear(BOOL)animated{
                [super viewWillAppear:animated];
                [self.navigationController setNavigationBarHidden:NO animated:YES];
            }
    
    • 2,第二种 swift 版(其实 OC 也差不多)
            override func viewWillAppear(_ animated: Bool) {
                super.viewWillAppear(true)
                navigationController?.setNavigationBarHidden(true, animated: true)
             }
            override func viewDidDisappear(_ animated: Bool) {
                super.viewDidDisappear(true)
                navigationController?.setNavigationBarHidden(false, animated: true)
             }
    
    • push 界面后自定义返回按钮,需重写滑动手势返回代理方法

    1:添加代理<UIGestureRecognizerDelegate>
    2:让导航栏成为代理    
    //使得 nav 成为手势的代理,自定义导航 leftButtonItem 时使用,以代替系统无法在自定义时使用右划返回。
        nav.interactivePopGestureRecognizer.delegate = self;
    3:开始重写代理方法
     //#pragma 以下是当自定义 leftButtonItem 时,需重写右划返回方法,响应原系统右划返回。
    -(BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
        if (self.viewControllers.count <= 1 ) {
            return NO;
        }
        return YES;
    }
    //允许同时响应多个手势
    -(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
        return YES;
     }
    -(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldBeRequiredToFailByGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
        
        return [gestureRecognizer isKindOfClass: UIScreenEdgePanGestureRecognizer.class];
    }
    
    • 启动界面直接强转竖屏(可以自选),其他界面可以按自己要求写

    屏幕快照 2017-04-12 下午12.59.28.png
     - (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {
        //set statusbar to the desired rotation position
        
     return  UIInterfaceOrientationMaskAllButUpsideDown;;
    }
    
    • 屏幕强制旋转

    1: 有 tabbar 和导航栏的情况,在自定义 tabbarController 里面添加下面代码。如果是自定义 tabbar 控件的话,可以看到下面的自定义tabbar,中间添加了一个类似于微博的发布按钮,在旋转屏幕后本身不在中间了,可以重新设置 layout 方法。

    需要在 tabbar 里面处理,添加全局旋转判断 
        BOOL __shouldAutorotate;
    //再注册旋转屏幕的通知
        [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(autorotateInterface:) name:@"InterfaceOrientation" object:nil];
    再添加方法,接收通知信息
    -(void)autorotateInterface:(NSNotification *)notifition
    {
        __shouldAutorotate = [notifition.object boolValue];
        NSLog(@"接收到的通知>> %d", __shouldAutorotate);
    }
    /**
     *  @return 是否支持旋转
     */
    -(BOOL)shouldAutorotate{
       NSLog(@"======>> %d", __shouldAutorotate);
        return  __shouldAutorotate;
    }
    /**
     *  适配旋转的类型
     *  @return 类型
     */
    -(UIInterfaceOrientationMask)supportedInterfaceOrientations
    {
        if (!__shouldAutorotate) {
            return UIInterfaceOrientationMaskPortrait;
        }
        return UIInterfaceOrientationMaskAllButUpsideDown;
    }
    

    2只有导航栏的情况

    自定义一个 navigation 类,里面添加方法,在控制器里面使用导航栏的的时候生效。
    /**
     *
     *  @return 是否支持旋转
     */
    -(BOOL)shouldAutorotate
    {
        return NO;//这个可以仿照上面的判断添加全局之类的,我的只要竖屏,不要旋转,所以就先这样
    }
    /**
     *  适配旋转的类型
     *
     *  @return 类型
     */
    -(UIInterfaceOrientationMask)supportedInterfaceOrientations
    {
    //旋转类型自己改,按需求来。
         return UIInterfaceOrientationMaskPortrait;    
    }
    
    • 自定义tabbar时,中间添加一个按钮-》移花接木。

    1:自定义重写 tabbar

    .h 继承 tabbar 重写
    @interface MYtabbar : UITabBar
    .m
    /** 发布按钮 */
    @property (nonatomic, strong) UIButton *publishButton;
     - (instancetype)initWithFrame:(CGRect)frame
    {
        if (self = [super initWithFrame:frame]) {
            // 添加发布按钮
            _publishButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, self.height, self.height)];
            [_publishButton setImage:[UIImage imageNamed:@"publish"] forState:UIControlStateNormal];
            _publishButton.backgroundColor = [UIColor greenColor];
            [_publishButton sizeToFit];
            [_publishButton addTarget:self action:@selector(publishClick) forControlEvents:UIControlEventTouchUpInside];
            [self addSubview:_publishButton];
        }
        return self;
    }
    /**
     * 布局子控件
     */
     - (void)layoutSubviews
    {
        [super layoutSubviews];
        
        // tabBar的尺寸
        CGFloat width = self.width;
        CGFloat height = self.height;
        // 按钮索引
        int index = 0; 
        // 按钮的尺寸
        CGFloat tabBarButtonW = width / 3;
        CGFloat tabBarButtonH = height;
        CGFloat tabBarButtonY = 0;
        
        // 设置3个TabBarButton的frame
        for (UIView *tabBarButton in self.subviews) {
            if (![NSStringFromClass(tabBarButton.class) isEqualToString:@"UITabBarButton"]) continue;
            
            // 计算按钮的X值
            CGFloat tabBarButtonX = index * tabBarButtonW;
            if (index == 1) { // 给后面2个button增加一个宽度的X值
                tabBarButtonX += tabBarButtonW;
            }
            
            // 设置按钮的frame
            tabBarButton.frame = CGRectMake(tabBarButtonX, tabBarButtonY, tabBarButtonW, tabBarButtonH);
            // 增加索引
            index++;
        }
        // 设置发布按钮的位置
        self.publishButton.center = CGPointMake(width * 0.5, height * 0.5);
        self.publishButton.width = SCREEN_WIDTH/3 ;
    }
    //重新布局使用,横竖屏切换时需要监听并调用此方法,不然会引起布局错误。上面的 layoutSubviews 走一次。
     -(void)layoutIfNeeded{
        // 设置发布按钮的位置
        self.publishButton.center = CGPointMake(self.width * 0.5, self.height * 0.5);
        self.publishButton.width = SCREEN_WIDTH/3 ;
    }
    

    其他控制器需要重现布局时调用

    在自定义 tabbar 界面初始化重写的 
    [self setValue:[[MYtabbar alloc] init] forKeyPath:@"tabBar"];
        ///横竖屏切换时调用此方法
     [self.tabBarController.tabBar layoutIfNeeded];
    

    2:简单添加按钮到 tabbar,这个有点类似某直播的效果,按钮可以写的很大,但是触发范围需要重写才能改变。

        UIButton *button = [[UIButton alloc]initWithFrame:CGRectMake(0.0,0.0,70,70];
    
        //防止 button 的 image 被压缩变形
        UIImage *buttonImage = [[UIImage imageNamed:@"publish"] resizableImageWithCapInsets:UIEdgeInsetsMake(0,0,0,0)];
        [button setImage:buttonImage forState:UIControlStateNormal];
        
        button.center = CGPointMake(SCREEN_WIDTH/2,self.tabBar.height/2);
        [button addTarget:self action:@selector(publishClick) forControlEvents:UIControlEventTouchUpInside];
        [self.tabBar addSubview:button];
    

    3:投机取巧的方法
    使用系统自身的 tabba ,添加他的viewControllers时,可以多添加一个,放在数组中间的位置。然后,使用上面的方法,直接自定义按钮添加上去,但是
    // 选择指定的控制器视图显示,不可以选择到你写的那个假的抢位置控制器.

        [self setSelectedIndex:2];//不谢默认是0
    

    创建的方法

    /**
     *  Tabbar创建
     */
     - (void)createSystemTabbar{
       MapViewController *mapView = [[MapViewController alloc] init];
        DataViewController *dataView = [[DataViewController alloc] init];
        PublishViewController *publish = [[PublishViewController alloc] init];#抢位子用的
        self.viewControllers = [NSArray arrayWithObjects:
                                [self createNavWithViewController:mapView WithTitle:@"地图" image:[UIImage imageNamed:@"map_sel"] unselectImage:[UIImage imageNamed:@"map"]],
    
                                [self createNavWithViewController:publish WithTitle:@"" image:[UIImage imageNamed:@"publish"] unselectImage:[UIImage imageNamed:@""]],
                                
                                [self createNavWithViewController:dataView WithTitle:@"数据" image:[UIImage imageNamed:@"data_sel"] unselectImage:[UIImage imageNamed:@"data"]],
                                
                                nil];
        UIButton *button = [[UIButton alloc]initWithFrame:CGRectMake(0.0,0.0,SCREEN_WIDTH/3,self.tabBar.height)];
        //防止 button 的 image 被压缩变形
        UIImage *buttonImage = [[UIImage imageNamed:@"publish"] resizableImageWithCapInsets:UIEdgeInsetsMake(0,0,0,0)];
        [button setImage:buttonImage forState:UIControlStateNormal];
        
        button.center = CGPointMake(SCREEN_WIDTH/2,self.tabBar.height/2);
    
        [button addTarget:self action:@selector(publishClick) forControlEvents:UIControlEventTouchUpInside];
        [self.tabBar addSubview:button];
    //按钮置顶
    //[self.tabBar bringSubviewToFront:button];
    
      //    选择指定的控制器视图显示,不可以选择1.
        [self setSelectedIndex:2];
    
     }
    
    • 计算每个月的天数

    /**
     计算每个月的天数
     @param year 年份
     @param month 月份
     @return 返回天数
     */
     - (NSInteger)DaysfromYear:(NSInteger)year andMonth:(NSInteger)month
     {
        NSInteger num_year  = year;
        NSInteger num_month = month;
        
        //判断是否是闰年 整除以4、100、400 则为闰年
        BOOL isrunNian = num_year%4==0 ? (num_year%100==0? (num_year%400==0?YES:NO):YES):NO;
        switch (num_month) {
            case 1:case 3:case 5:case 7:case 8:case 10:case 12:{
                [self setdayArray:31];
                return 31;
            }
            case 4:case 6:case 9:case 11:{
                [self setdayArray:30];
                return 30;
            }
            case 2:{
                if (isrunNian) {
                    [self setdayArray:29];
                    return 29;
                }else{
                    [self setdayArray:28];
                    return 28;
                }
            }
            default:
                break;
        }
        return 0;
    }
    
    • tabView 的 cell 重用混乱问题,两个不同的解决办法
        //指定不同的 identity 
        NSString *ident = [NSString stringWithFormat:@"InfoCell%zd%zd",indexPath.section,indexPath.row];
        InfoCell *cell = [tableView dequeueReusableCellWithIdentifier:ident];
        
        //指定位置
        InfoCell *cell = [tableView cellForRowAtIndexPath:indexPath];
    
    • 使用系统的搜索框,自定义样式,重写。

    重写的样式
    //重写 searchBar ,继承 UIsearchBar
     -(void)layoutSubviews{
        for (UIView *view in self.subviews) {
            
            for (UIView *subView in view.subviews) {
                
                if ([subView isKindOfClass:[UITextField class]]) {
    
                    subView.frame = CGRectMake(0, 0, self.bounds.size.width,  self.bounds.size.height);
                } 
            }
        }
    }
    
    • 线程问题,串行异步,一个子线程循环执行任务

    dispatch_queue_t queueA = dispatch_queue_create("bufujquigj", DISPATCH_QUEUE_SERIAL);
        for (NSInteger i = 1; i<nn+1; i++) {
            dispatch_async(queueA, ^{   
                dispatch_async(dispatch_get_main_queue(), ^{       
                   //刷新 UI
                });  
                [NSThread sleepForTimeInterval:1.0/nn]; 
                NSLog(@"jbfkjsdkjsdjf:       %ld    %@",(long)i    ,[NSThread currentThread]);    
                if (i == nn) {    
                    //用来判断第几次执行,不要将这个判断放在外边。
                }
            });
        }
    
    • 根据两点坐标计算方位角

        double rads = 0;//角度
        double currentX = _currentLocalPoint.x;
        double nextX    = nextPoint.x;
        double currentY = _currentLocalPoint.y;
        double nextY    = nextPoint.y;
       
        rads = sin(currentX)*sin(nextX) + cos(currentX)*cos(nextX)*cos(nextY-currentY);
        rads = sqrt(1-rads*rads);
        rads = cos(currentX)*sin(nextY - currentY)/rads;
        rads = asin(rads) * 180 / M_PI;//夹角是正数,按需判断转换
      if (_currentLocalPoint.y > nextPoint.y) {
            rads = -rads;
        }
    

    相关文章

      网友评论

          本文标题:iOS 杂记(持续更新)

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