美文网首页
iOS开发小技巧(持续更新)

iOS开发小技巧(持续更新)

作者: yuandiLiao | 来源:发表于2017-06-02 15:57 被阅读0次
    1.去除导航栏底部线条和去除Tabbar顶部的线条

    我们自定义NavigationController和自定义UITabbar的时候,想去掉他们自带的细线,通过设置下面的可以达到效果

    //去除导航栏底部线条
      [self.navigationBar setBackgroundImage:[UIImage new] forBarMetrics:UIBarMetricsDefault];
      [self.navigationBar setShadowImage:[UIImage new]];
    
    //如果上面的达不到效果
    //那绘制一个空白的image来设置,亲测两种方法都可以
      //去掉下面线条
        CGRect rect1 = CGRectMake(0, 0, HFScreenWidth, HFScreenHieght);
        UIGraphicsBeginImageContext(rect1.size);
        CGContextRef context = UIGraphicsGetCurrentContext();
        CGContextSetFillColorWithColor(context, [[UIColor clearColor] CGColor]);
        CGContextFillRect(context, rect1);
        UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
        [self.navigationBar setBackgroundImage:img forBarMetrics:UIBarMetricsDefault];
        [self.navigationBar setShadowImage:img];
    
    
    //去除Tabbar顶部的线条
     [self.tabBar setBackgroundImage:[UIImage new]];
     [self.tabBar setShadowImage:[UIImage new]];
    
    //如果上面的达不到效果
    //那绘制一个空白的image来设置,亲测两种方法都可以
      //去掉下面线条
        CGRect rect1 = CGRectMake(0, 0, HFScreenWidth, HFScreenHieght);
        UIGraphicsBeginImageContext(rect1.size);
        CGContextRef context = UIGraphicsGetCurrentContext();
        CGContextSetFillColorWithColor(context, [[UIColor clearColor] CGColor]);
        CGContextFillRect(context, rect1);
        UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
        [self.tabBar setBackgroundImage: img];
        [self.tabBar setShadowImage: img];
    
    
    2.图片处理

    有时候网络加载回来的图片比例有点不适应,这时候就需要我们剪裁处理了,不然的话图片就会被压缩变形
    我们可以给UIImageView添加一个类别,然后在类别里面设置contentMode达到效果

    //imageview的content适应图片的比例大小,然后再剪裁掉多余的部分
    -(void)fitImageView
    {
        [self setContentScaleFactor:[[UIScreen mainScreen] scale]];
        self.contentMode =  UIViewContentModeScaleAspectFill;
        self .clipsToBounds  = YES;
    }
    //如果图片的frame小于原图大小,显示原图的大小,然后再剪裁掉多余的部分,如果图片的frame大于原图大小,在图片中间显示原图大小
    -(void)fitCenterImageView
    {
        [self setContentScaleFactor:[[UIScreen mainScreen] scale]];
        self.contentMode =  UIViewContentModeCenter;
        self .clipsToBounds  = YES;
    }
    
    
    3.导航栏标题和Tabbar标题的设置
      //这个单独设置tabbar的title
      self.navigationController.title = @"yoyoyo";
      //这个单独设置navgation的title
      self.navigationItem.title = @"哟哟";
      //这个是tabbar和navgation一块设置的
      self.title = @"啃爹";
    
    
    4.给view绘制指定的圆角

    使用赛贝尔曲线绘制需要的圆角
    typedef NS_OPTIONS(NSUInteger, UIRectCorner) {
    UIRectCornerTopLeft = 1 << 0,
    UIRectCornerTopRight = 1 << 1,
    UIRectCornerBottomLeft = 1 << 2,
    UIRectCornerBottomRight = 1 << 3,
    UIRectCornerAllCorners = ~0UL
    };

        CGRect frame = self.backImageView.bounds;
        frame.size.width = self.frame.size.width;
        UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:frame byRoundingCorners:UIRectCornerTopLeft | UIRectCornerTopRight cornerRadii:CGSizeMake(5, 5)];
        CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init];
        maskLayer.frame = frame;
        maskLayer.path = maskPath.CGPath;
        self.backImageView.layer.mask = maskLayer;
    
    5.scrollView传递点击事件

    有时候我们会在tableView的cell上面嵌进来scrollview,这时候scrollview就会截取掉,这样tableViewcell的点击事件就无法响应,所以我们需要他点击事件传递下去。给scrollview添加类别,然后重写响应事件,传递到父视图即可

    #import "UIScrollView+TouchEvent.h"
    
    @implementation UIScrollView (TouchEvent)
    
    //tableviewcell的scrollview会截取到点击事件,将这个事件传递下去给cell
    - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
    
    {
        //因为collectionView是继承自scrollview,所以如果把collectionview的点击事件也传递下去了,collectionview的点击事件就被其superview接受,没有点击事件了
        if ([self isKindOfClass:[UICollectionView class]] || [self isKindOfClass:[UITableView class]]) {
            return;
        }
        [self.superview touchesBegan:touches withEvent:event];
    }
    - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
    
    {
        if ([self isKindOfClass:[UICollectionView class]]||[self isKindOfClass:[UITableView class]]) {
            return;
        }
        [self.superview touchesEnded:touches withEvent:event];
    
    }
    @end
    
    
    6.UITextField和UItextview

    1.UITextField的placeholder的字体改变

       [self.nameTextView setValue:[UIColor blackColor] forKeyPath:@"_placeholderLabel.color"];
    
    

    2.改变键盘的类型和return键

     self.textField.keyboardType = UIKeyboardTypeNumberPad;
     self.textView.returnKeyType = UIReturnKeyDone;
    

    3.捕捉return键响应进行操作

    - (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text{
        if ([text isEqualToString:@"\n"]){ //判断输入的字是否是回车,即按下return
            //在这里做你响应return键的代码
            [textView resignFirstResponder];
            return NO; //这里返回NO,就代表return键值失效,即页面上按下return,不会出现换行,如果为yes,则输入页面会换行
        }
        return YES;
    }
    
    
    7.横竖屏的转换
    //强制横屏
    - (void)forceOrientationLandscape
    {
        AppDelegate *appdelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
        appdelegate.allowRotation = 1;
        if ([[UIDevice currentDevice] respondsToSelector:@selector(setOrientation:)]) {
            SEL selector = NSSelectorFromString(@"setOrientation:");
            NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[UIDevice instanceMethodSignatureForSelector:selector]];
            [invocation setSelector:selector];
            [invocation setTarget:[UIDevice currentDevice]];
            int val = UIInterfaceOrientationLandscapeRight;
            [invocation setArgument:&val atIndex:2];
            [invocation invoke];
        }
    
    }
    
    //强制竖屏
    - (void)forceOrientationPortrait
    {
        _isDirectionScreen = NO;
        AppDelegate *appdelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
          appdelegate.allowRotation = 0;
        [appdelegate application:[UIApplication sharedApplication] supportedInterfaceOrientationsForWindow:self.view.window];
        //设置屏幕的转向为竖屏
        [[UIDevice currentDevice] setValue:@(UIDeviceOrientationPortrait) forKey:@"orientation"];
        //刷新
        [UIViewController attemptRotationToDeviceOrientation];
    }
    
    
    8.调试时打印,正式环境打包不打印
    /**
     *  调试时打印,正式环境打包不打印
    */
    // 日志输出
    #ifdef DEBUG
    #define HFLog(...) NSLog(__VA_ARGS__)
    #else
    #define HFLog(...)
    #endif
    
    9.常见的基础概念
    • Class:定义Objective-C类
    • Ivar定义对象的实例变量,包括类型和名字。
    • Protocol:定义正式协议。
    • objc_property_t:定义属性。叫这个名字可能是为了防止和Objective-C 1.0中的用户类型冲突,那时候还没有属性。
    • Method:定义对象方法或类方法。这个类型提供了方法的名字(就是选择器)、参数数量和类型,以及返回值(这些信息合起来称为方法的签名),还有一个指向代码的函数指针(也就是方法的实现)。
    • SEL:定义选择器。选择器是方法名的唯一标识符。
    • IMP:定义方法实现。这只是一个指向某个函数的指针,该函数接受一个对象、一个选择器和一个可变长参数列表(varargs),返回一个对象
    10.缓存URL图片和读取
    dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_CONCURRENT);
        dispatch_async(queue, ^{
            NSData *data = [NSData dataWithContentsOfURL:[NSURL  URLWithString:urlString]];
            UIImage *image = [UIImage imageWithData:data]; // 取得图片
            // 本地沙盒目录
            NSString *path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
            // 得到本地沙盒中名为"MyImage"的路径,"MyImage"是保存的图片名
            NSString *imageFilePath = [path stringByAppendingPathComponent:@"watermark.png"];
            NSLog(@"file:%@",imageFilePath);
            // 将取得的图片写入本地的沙盒中 UIImageJPEGRepresentation,UIImagePNGRepresentation两种格式存储
            BOOL success = [UIImagePNGRepresentation(image) writeToFile:imageFilePath atomically:YES];
            if (success){
               dispatch_async(dispatch_get_main_queue(), ^{
                  //  获取图片
                   NSData *data = [[NSData alloc] initWithContentsOfFile:imageFilePath];
                   UIImage *waterMarkImage = [UIImage imageWithData:data];
                });
            }
        });
    
    11.获取沙河目录

    Documents:保存应用运行时生成的需要持久化的数据,iTunes 同步设备时会备份该目录。例如,游戏应用可 将游戏存档保存在该目录。 tmp:保存应用运行时所需的临时数据,使用完毕后再将相应的文件从该目录删除。应用没有运行时,系统也 可能会清除该目录下的文件。iTunes 同步设备时不会备份该目录。 Library/Caches:保存应用运行时生成的需要持久化的数据,iTunes 同步设备时不会备份该目录。一般存储体 积大、不需要备份的非重要数据。
    Library/Preference:保存应用的所有偏好设置,iOS 的 Settings(设置)应用会在该目录中查找应用的设置信息。 iTunes 同步设备时会备份该目录。
    总结:
    1、体积大(itunes 不会备份)
    (1) tmp(里面的内容可能会被系统随机清除)
    (2) Library/Caches
    2、体积小(itunes 会备份)
    (1) Documents
    (2) Library/Preference
    Home目录

    NSString *homeDirectory = NSHomeDirectory();  
    

    Document目录

    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);    
    NSString *path = [paths objectAtIndex:0];  
    

    Cache目录

    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);    
    NSString *path = [paths objectAtIndex:0];  
    

    Libaray目录

    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);   
    NSString *path = [paths objectAtIndex:0];  
    
    12.openURL

    UIApplication 有个功能十分强大的 openURL:方法

    - (BOOL)openURL:(NSURL*)url;
    

    openURL:方法的部分功能:
    (1)打电话

    UIApplication *app = [UIApplication sharedApplication];
    [app openURL:[NSURL URLWithString:@"tel://10086"]];
    

    (2)发短信

    [app openURL:[NSURL URLWithString:@"sms://10086"]];
    

    (3)发邮件

    [app openURL:[NSURL URLWithString:@"mailto://12345@qq.com"]]; 
    

    (4)打开一个网页资源(自动跳转到浏览器打开)

    [app openURL:[NSURL URLWithString:@"http://ios.itcast.cn"]];
    

    (5)打开其他 app 程序

    [app openURL:[NSURL URLWithString:@"........"]];
    
    13.自定义弹出的键盘
    self.inputField.inputView = myView
    

    按文本框弹出的键盘不再是普通文字输入键盘,而是我们设置的 myView。一般把这个方法写在 viewDiDLoad 方法中。

    也可以在键盘上方增加一个 View:

    self. inputField.inputAcessoryView = myView;
    

    之后就可以在键盘上侧显示 myView。

    14.判断系统版本
    if([[UIDevice currentDevice].systemVersion doubleValue]>=7.0) {
         //是 IOS7 至以上版本
     }else{
        //IOS7 以下版本
     }
    
    15.禁止左划手势
     if([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)]) {
            self.navigationController.interactivePopGestureRecognizer.enabled = false;
        }
    

    自定义导航栏左划返回手势

        self.interactivePopGestureRecognizer.delegate = (id)self;
    
    
    16.KVO

    viewcontroller本身不能使用KVO监听其持有的array变化

    17.导航栏半透明

    导航栏半透明时改变坐标原点

     self.automaticallyAdjustsScrollViewInsets = YES;
     self.edgesForExtendedLayout = UIRectEdgeNone;
    

    这样设置之后导航栏和tabbar会变灰色而不是半透明,再加上这两个设置就好了

    self.navigationController.navigationBar.translucent = NO;
    self.tabBarController.tabBar.translucent = NO;
    

    18 oc文件转成c,c++语言文件,后缀名为cpp

    cd到你所要转成c语言文件的目录里:

    clang  -rewrite-objc 目标文件(例如 main.m)
    

    成功会在你所cd的目录下面多了一个后缀名是cpp的文件。

    在arc模式下,使用weak修饰符时clang -rewrite-objc xxx.m时会提示编译错误:

    cannot create __weak reference because the current deployment target does
          not support weak references
        __attribute__((objc_ownership(weak))) NSObject *obj2 = obj;
    

    解决方法:

    clang -rewrite-objc -fobjc-arc -stdlib=libc++ -mmacosx-version-min=10.7 -fobjc-runtime=macosx-10.7 -Wno-deprecated-declarations 目标文件(例如 main.m)
    

    19.load和initialize

    问:Category中有load方法吗?load方法是什么时候调用的?load 方法能继承吗?
    答:Category中有load方法,load方法在程序启动装载类信息的时候就会调用。load方法可以继承。调用子类的load方法之前,会先调用父类的load方法

    问:load、initialize的区别,以及它们在category重写的时候的调用的次序。
    答:区别在于调用方式和调用时刻
    调用方式:load是根据函数地址直接调用,initialize是通过objc_msgSend调用
    调用时刻:load是runtime加载类、分类的时候调用(只会调用1次),initialize是类第一次接收到消息的时候调用,每一个类只会initialize一次(父类的initialize方法可能会被调用多次)

    调用顺序:先调用类的load方法,先编译那个类,就先调用load。在调用load之前会先调用父类的load方法。分类中load方法不会覆盖本类的load方法,先编译的分类优先调用load方法。initialize先初始化父类,之后再初始化子类。如果子类没有实现+initialize,会调用父类的+initialize(所以父类的+initialize可能会被调用多次),如果分类实现了+initialize,就覆盖类本身的+initialize调用。

    20.事件传递和事件响应

    首先UIApplication会捕获到事件(先进行传递再进行响应),传递到最上层(根据subviews)
    然后从最上层开始做响应事件,判断最上层是否能响应事件,如果可以,就响应。无就传递到下一层(nextResponder)往下传递

    事件传递:下 ---> 上
    事件响应: 上 ---> 下

    相关文章

      网友评论

          本文标题:iOS开发小技巧(持续更新)

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