开发小结


1.UITabBar选中的图片默认渲染颜色为蓝色 如果不想改变图片的颜色 可做如下操作

[objc]  view plain  copy
  1. UIImage *image = [UIImage imageNamed:@"app_slogan"];  
  2.     image = [image imageWithRenderingMode:(UIImageRenderingModeAlwaysOriginal)];  
  3.     vc.tabBarItem.image = image;  

或者找到对应的图片 如图所示  最下面的 Render As → Original Image

开发小结_第1张图片


2.通过appearance统一设置所有UITabBarItem的文字属性

方法后面带有UI_APPEARANCE_SELECTOR的方法都可以通过appearance的对象来统一设置


3.通过代码自定义的控件,需要重写- (instancetype)initWithFrame:(CGRect)frame方法


4.UI控件的坐标及大小可以通过为UIView类添加Category 来实现

需要注意 :在分类中声明只会生成方法的声明 不会生成方法的实现和带有下划线的成员变量 需要手写setter 和 getter方法 width height x y


5.自定义打印 在pch文件内

如果是调试阶段#define DXYLog(...) NSLog(__VA_ARGS__)

如果是发布程序 #define DXYLog(...)

[objc]  view plain  copy
  1. /** 如果是调试阶段 DXYLog == NSLog */  
  2. #ifdef DEBUG  
  3. #define DXYLog(...) NSLog(__VA_ARGS__)  
  4. /** 如果是发布程序 DXYLog替换为空 */  
  5. #else  
  6. #define DXYLog(...)  
  7. #endif  

6 .分类category比继承的优势在于不会产生新的类 生成的类方法简洁明了


7.

[objc]  view plain  copy
  1.  /** 自适应内容 */  
  2.    [button sizeToFit];  
  3.    
[objc]  view plain  copy
  1. //        button.contentMode = UIViewContentModeLeft; imageView一般用这个左对齐  
  2.         /** 让按钮内部的所有内容左对齐 此方法一般用于UIButton */  
  3.         button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;  
  4.           
  5.         button.contentEdgeInsets = UIEdgeInsetsMake(0, -1000);  


8.

[objc]  view plain  copy
  1. /** 当push的时候隐藏下面的tabBar */  
  2.         viewController.hidesBottomBarWhenPushed =YES;  

9.DXTTabBarViewController是继承自UINavigationController 命名的时候没有注意 - -

如果使用[UINavigationBar appearance]方法设置,那么所有的自定义的导航栏都会改变

注: 像appearance这种一次性设置的方法最好放在initialize中设置,在viewDidLoad里调用次数取决于生成该类对象的个数

[objc]  view plain  copy
  1. /** 当第一次使用的时候会调用一次 */  
  2. + (void)initialize {  
  3.     /** 当导航栏用在DXYTabBarViewController中,appearance设置才会生效 */  
  4.     UINavigationBar *bar = [UINavigationBar appearanceWhenContainedInInstancesOfClasses:@[[self class]]];  
  5.     [bar setBackgroundImage:[UIImage imageNamed:@"navigationbarBackgroundWhite"] forBarMetrics:(UIBarMetricsDefault)];  
  6. }  

[objc]  view plain  copy
  1. + (void)initialize {  
  2.     NSMutableDictionary *dic = [NSMutableDictionary dictionary];  
  3.     dic[NSFontAttributeName] = [UIFont systemFontOfSize:13];  
  4.     dic[NSForegroundColorAttributeName] = [UIColor grayColor];  
  5.       
  6.     NSMutableDictionary *selectedDic = [NSMutableDictionary dictionary];  
  7.     selectedDic[NSFontAttributeName] = [UIFont systemFontOfSize:13];  
  8.     selectedDic[NSForegroundColorAttributeName] = [UIColor redColor];  
  9.       
  10.     /** 通过appearance统一设置所有UITabBarItem的文字属性 */  
  11.     /** 后面带有UI_APPEARANCE_SELECTOR的方法,都可以通过appearance的对象来统一设置 */  
  12.     UITabBarItem *item = [UITabBarItem appearance];  
  13.     [item setTitleTextAttributes:dic forState:(UIControlStateNormal)];  
  14.     [item setTitleTextAttributes:selectedDic forState:(UIControlStateSelected)];  
  15. }  


证明如图:

开发小结_第2张图片

只打印一次


开发小结_第3张图片

打印了4次


宏定义如下图



10.  #ffff00   代表红色  R 对应 ff  G 对应 ff B 对应 00 24bit 每个8bit 2位


11.水平居中就是使文字在这行、单元格、编辑范围内处在中间;垂直居中就是使文字在这列、单元格、编辑范围内处在中间。


12.UIlabel 约束宽度后 可以自适应高度 注:自动换行


13.在sb或xib上 若在UILabel上文字需要换行显示 做法:option键 + 回车键 效果如图

开发小结_第4张图片


14.

[objc]  view plain  copy
  1. /** 当cell的selection为None时,即使cell被选中,内部的子控件也不会进入高亮状态 下面的代码就会失效 */  
  2. //    self.textLabel.textColor = DXYRGBColor(78, 78, 78)  
  3. //      
  4. //    /** 选中当前cell 显示的颜色 */  
  5. //    self.textLabel.highlightedTextColor = DXYRGBColor(219, 21, 26)  
  6.       
  7. //    UIView *bg = [[UIView alloc] init];  
  8. //    bg.backgroundColor = [UIColor clearColor];  
  9. //    self.selectedBackgroundView = bg;  

开发小结_第5张图片

[objc]  view plain  copy
  1. /** 可以在这个方法中监听cell的选中和取消选中 */  
  2. - (void)setSelected:(BOOL)selected animated:(BOOL)animated {  
  3.     [super setSelected:selected animated:animated];  
  4.       
  5.     self.selectedIndicatorView.hidden = !selected;  
  6.       
  7.     if (selected) {  
  8.         self.textLabel.textColor = DXYRGBColor(2192126)  
  9.     }  
  10.     else {  
  11.         self.textLabel.textColor = DXYRGBColor(787878)  
  12.     }  
  13. }  


15.利用正则表达式验证邮箱是否正确

[objc]  view plain  copy
  1. //利用正则表达式验证  
  2. +(BOOL)isValidateEmail:(NSString *)email  
  3. {  
  4.     NSString *emailRegex = @"[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}";  
  5.     NSPredicate *emailTest = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", emailRegex];  
  6.     return [emailTest evaluateWithObject:email];  
  7. }  

16.KVO实现原理

基于Runtime运行时实现 动态生成继承自被观察对象的之类,调用被观察属性的setter方法 内部再调用observeValueForKeypath

当某个类的对象第一次被观察时 系统就会在运行期动态地创建该类的一个派生类 在这个派生类中任何被观察属性的setter方法 派生类在被重写的setter方法实现真正的通知机制(Person → NSKVONotifying_Person)


17.是否可以把比较耗时的操作放在NSNotificationCenter中  不可以,通知中心所做的操作在主线程 比较耗时的一般开启一个线程单独去跑


14.渲染自定义格式字符串的UILabel
通过NSAttributeString类

15.客户端安全性
1.网络数据传输(敏感数据\账号\密码\银行卡)
协议的问题(自定义协议,游戏代练)
2.本地文件存储(游戏存档)
3.源代码

16.下载图片如何优化
1.开辟子线程
2.使用占位图片
3.对较大图片,考虑多线程断点下载

17.对Button切圆角代码写如下
[objc]  view plain  copy
  1. //    self.loginButton.layer.cornerRadius = 5;  
  2. //    self.loginButton.layer.masksToBounds = YES;  

如果使用xib的话,操作步骤如下:  使用KVC赋值
选中对应button
开发小结_第6张图片

18.

[objc]  view plain  copy
  1. /** 获取成员变量 */  
  2. + (void)getIvars {  
  3.       
  4.     unsigned int count = 0;  
  5.     /** 拷贝出所有的成员变量列表 */  
  6.     Ivar *ivars = class_copyIvarList([UITextField class], &count);  
  7.     for (int i = 0; i < count; i ++) {  
  8.         /** 取出成员变量 */  
  9.         Ivar ivar = *(ivars + i);  
  10.         /** 打印成员变量名字 */  
  11.         DXYLog(@"%s",ivar_getName(ivar));  
  12.     }  
  13.     /** 释放 */  
  14.     free(ivars);  
  15. }  
  16.   
  17. /** 获取属性 */  
  18. + (void)getProperties {  
  19.       
  20.     unsigned int count1 = 0;  
  21.     /** 拷贝出所有的属性列表 */  
  22.     objc_property_t *properties = class_copyPropertyList([UITextField class], &count1);  
  23.     for (int i = 0; i < count1; i ++) {  
  24.         /** 取出属性 */  
  25.         objc_property_t property = *(properties + i);  
  26.         /** 打印属性名字 */  
  27.         DXYLog(@"%s ------ %s",property_getName(property),property_getAttributes(property));  
  28.     }  
  29.     /** 释放 */  
  30.     free(properties);  
  31. }  


[objc]  view plain  copy
  1. /** 运行时(runtime) 苹果官方一套C语言库 能做很多底层操作(比如访问隐藏的一些成员变量\成员方法) */  
  2.   
  3. + (void)initialize {  
  4.       
  5.     unsigned int count = 0;  
  6.     /** 拷贝出所有的成员变量列表 */  
  7.     Ivar *ivars = class_copyIvarList([UITextField class], &count);  
  8.     for (int i = 0; i < count; i ++) {  
  9.         /** 取出成员变量 */  
  10.         Ivar ivar = *(ivars + i);  
  11.         /** 打印成员变量名字 */  
  12.         DXYLog(@"%s",ivar_getName(ivar));  
  13.     }  
  14.     /** 释放 */  
  15.     free(ivars);  
  16. }  

打印结果如下

开发小结_第7张图片


19.

[objc]  view plain  copy
  1.     /** 通过KVC取隐藏的成员属性 并进行相关操作 */  
  2. //    UILabel *placeholderLabel = [self valueForKey:@"_placeholderLabel"];  
  3. //    placeholderLabel.textColor = [UIColor redColor];  
  4.       
  5.     [self setValue:[UIColor cyanColor] forKeyPath:@"_placeholderLabel.textColor"];  
以上两种方法都能实现

20.

[objc]  view plain  copy
  1. - (void)awakeFromNib {  
  2.       
  3.     /** 解决view控件frame设定好却实际没有达到效果的问题 autoresizing影响了我们自己的布局 */  
  4.     self.autoresizingMask = UIViewAutoresizingNone;  
  5. }  

21.

[objc]  view plain  copy
  1. - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {  
  2.       
  3.     /** 取出帖子模型 */  
  4.     DXYTopicModel *model = self.topics[indexPath.row];  
  5.       
  6.    
  7.     /** 通过字体大小计算文字高度 在此方法里调用会重复计算好多次 */  
  8. //    CGFloat textH = [model.text boundingRectWithSize:CGSizeMake(kScreenWidth - 40, 10000000) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName : [UIFont systemFontOfSize:14]} context:nil].size.height;  
  9.   
  10.     /** 返回这个模型对应的cell的高度 */  
  11.     return model.cellHeight;  
  12. }  

22.获取图片的后缀名 来判断是否隐藏gif标志

[objc]  view plain  copy
  1. /** 在不知道图片扩展名情况下 如何知道图片的真实类型? 
  2.         取出图片数据的第一个字节,就可以判断出图片的真实类型 */  
  3. 例如:SDWebImage  


[objc]  view plain  copy
  1. /** 判断是否为gif */  
  2.     NSString *extension = [model.small_image.pathExtension lowercaseString];  
  3.     self.gifView.hidden = ![extension isEqualToString:@"gif"];  


23. 只需要确定高度或宽度其中一个就可等比例缩放 约束高度较好

开发小结_第8张图片


效果如下


开发小结_第9张图片


开发小结_第10张图片


25.pop是由facebook开发的

/** 
    pop和Core Animation的区别
    1.Core Animation的动画只能添加到layer上
    2.pop的动画能添加到任何对象
    3.pop的底层并非基于Core Animation,是基于CADisplayLink
    4.Core Animation的动画仅仅是表象 并不会真正修改对象的frame\size
    5.pop的动画实时修改对象的属性,真正修改了对象属性
*/
//- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
//    
//    POPSpringAnimation *animation = [POPSpringAnimation animationWithPropertyNamed:kPOPViewCenter];
//    animation.fromValue = [NSValue valueWithCGPoint:CGPointMake(100, 100)];
//    animation.toValue = [NSValue valueWithCGPoint:CGPointMake(200, 200)];
//    animation.springBounciness = 20;
//    animation.springSpeed = 20;
//    animation.beginTime = CACurrentMediaTime() + 1;
//    [self.sloganView pop_addAnimation:animation forKey:nil];
//}

26.

25.  window.windowLevel 优先级高于statusBar 会遮住状态栏
注:达到半透明效果 能看清后面的内容 可创建一个新的window 下面视图的点击事件就都隔离开了
UIWindow *window;
- (void)buttonClick:(UIButton *)button {
    /** 窗口级别
     UIWindowLevelNormal < UIWindowLevelStatusBar < UIWindowLevelAlert
     */
    window = [[UIWindow alloc] init];
    window.frame = CGRectMake(0, 0, 375, 20);
    window.backgroundColor = [UIColor cyanColor];
    window.windowLevel = UIWindowLevelStatusBar;
    window.hidden = NO;

27.一行代码计算size

/** 计算label的宽度 */
    CGFloat messageW = [message sizeWithAttributes:@{NSFontAttributeName : [UIFont systemFontOfSize:12]}].width;

28.UIAlertController的用法

- (IBAction)more:(id)sender {
    
    UIAlertController *alertC = [UIAlertController alertControllerWithTitle:nil message:nil preferredStyle:(UIAlertControllerStyleActionSheet)];
    
    UIAlertAction *collectAction = [UIAlertAction actionWithTitle:@"收藏" style:(UIAlertActionStyleDefault) handler:nil];
    UIAlertAction *reportAction = [UIAlertAction actionWithTitle:@"举报" style:(UIAlertActionStyleDefault) handler:nil];
    UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"取消" style:(UIAlertActionStyleCancel) handler:nil];
    
    [alertC addAction:collectAction];
    [alertC addAction:reportAction];
    [alertC addAction:cancelAction];
    
    [[UIApplication sharedApplication].keyWindow.rootViewController presentViewController:alertC animated:YES completion:nil];
}

29.在控制器将要销毁的时候要移除观察者 取消AFNetworking执行的所有任务

- (void)dealloc {
    
    [[NSNotificationCenter defaultCenter] removeObserver:self];
    
    /** 恢复帖子的top_cmt */
    if (self.save_top_cmt) {
        self.model.top_cmt = self.save_top_cmt;
        [self.model setValue:@0 forKeyPath:@"cellHeight"];
    }
    
    /** 取消所有任务 */
//    [self.manager.tasks makeObjectsPerformSelector:@selector(cancel)] (这个方法不够彻底 取消之前旧任务 新任务可执行);
    [self.manager invalidateSessionCancelingTasks:YES];
}

30.继承控件具备UIMenuController

/** 系统自带UIMenuController的控件有 UITextfield UITextView UIWebView */

/** 重写UILabellabel具备该功能 */


#import "DXYLabel.h"

@implementation DXYLabel

- (void)awakeFromNib {
    
    [self setUp];
}

- (instancetype)initWithFrame:(CGRect)frame {
    
    if (self = [super initWithFrame:frame]) {
        [self setUp];
    }
    return self;
}

- (void)setUp {
    
    self.userInteractionEnabled = YES;
    [self addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(labelClick)]];
}

- (void)labelClick {
    
    /** 1.让label成为第一响应者 (作用是:告诉UIMenuController支持哪些操作,这些操作如何处理) */
    [self becomeFirstResponder];
    
    /** 2.显示MenuController */
    UIMenuController *menu = [UIMenuController sharedMenuController];
    /** targetRect:menuController需要指向的矩形框
        targetView:以target的左上角为坐标原点
     */
    [menu setTargetRect:self.bounds inView:self];
    [menu setMenuVisible:YES animated:YES];
}

/** 让label有资格成为第一响应者 */
- (BOOL)canBecomeFirstResponder {
    
    return YES;
}

/** label能执行哪些操作(比如copy,paste等等) */
- (BOOL)canPerformAction:(SEL)action withSender:(id)sender {
    if (action == @selector(cut:) || action == @selector(paste:) || action == @selector(copy:)) return  YES;
    return NO;
}

- (void)cut:(UIMenuController *)sender {
    
    [self copy:sender];
    
    /** 清空文字 */
    self.text = nil;
}

- (void)copy:(UIMenuController *)sender {
    
    /** 将自己的文字复制到粘贴板 */
    UIPasteboard *board = [UIPasteboard generalPasteboard];
    board.string = self.text;
}

- (void)paste:(UIMenuController *)sender {
    
    /** 将粘贴板复制到自己的文字 */
    UIPasteboard *board = [UIPasteboard generalPasteboard];
    
    self.text = board.string;
}

31.UITabBarController可通过属性找到当前的索引值 和 当前选中的控制器

开发小结_第11张图片


32.如果你设置某些东西的时候没有实现应有效果 可以考虑强制更新一下试试

/** 强制更新 */
    [self.navigationController.navigationBar layoutIfNeeded];

33.有导航栏的视图中,继承自UIScrollView的控件都会自动计算64的顶部间距 (UITextView)

34.setNeedsDisplay:会在恰当的时候自动调用drawRect方法

     setNeedsLayout:会在恰当的时候调用layoutSubViews方法

 
  

35.如果控制器是从xib创建的,在viewDidLoad里拿到的size是初始化时的尺寸

36.

/** VC 模态出 addVC */
    [VC presentViewController:addVC animated:YES completion:nil];
    /** 通过属性找出对应的控制器 */
    addVC.presentingViewController -> VC
    VC.presentationController -> addVC

37.拿到一个数组中所有对象的某一属性

第一种:遍历

NSMutableArray *tags = [NSMutableArray array];
    for (DXYTagButton *button in self.tagButtons) {
        [tags addObject:button.currentTitle];
    }


第二种:KVC

 NSArray *tags = [self.tagButtons valueForKeyPath:@"currentTitle"];

38.从xib加载视图,一开始的frame可能不是真实数据. 如果要根据视图的size进行子控件的创建与布局,可以把相对布局放在

- (void)layoutSubviews方法里,在创建完子控件后,执行

/** 重新布局子控件 */

    [selfsetNeedsLayout];

就会调用- (void)layoutSubviews方法,重新布局


39.

/** 如果滑动移除控制器的功能失效 清空代理(让导航控制器重新设置这个功能) */
    self.interactivePopGestureRecognizer.delegate = nil;

40.沙盒文件路径

NSString *sanBox = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];


41.通过block遍历

    /** 找出高度最短的一列 */
    __block NSInteger destColumn = 0;
    __block CGFloat minColumnHeight = MAXFLOAT;
    [self.columnHeights enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        CGFloat columnHeight = [(NSNumber *)obj doubleValue];
        if (columnHeight < minColumnHeight) {
            minColumnHeight = columnHeight;
            destColumn = idx;
        }
    }];

42.
/** 更换tabBar self.tabBar 只读特性 不能直接赋值 可以使用KVC*/
//    self.tabBar = [[DXYTabBar alloc] init];
    [self setValue:[[DXYTabBar alloc] init] forKeyPath:@"tabBar"];



你可能感兴趣的:(项目总结)