1、imageView上的按钮无法点击
 UIImageView默认没有交互。
 _imageView.userInteractionEnabled = YES;

 2、图片显示不出来的时候,用以下解决办法
  [button setImage:[[UIImage imageNamed:[NSString stringWithFormat:@"tab_%d",i]]imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal] forState:UIControlStateNormal];

 3、设置字体font
 label.font = [UIFont systemFontOfSize:10.0];

 4、如果button不设置button.tintColor = [UIColor clearColor];则button被选中后会变为高亮状态。

 5、取视图中的某个控件的tag值        
 _selectedLabel = (UILabel *)[_imageView viewWithTag:button.tag + 9];

 6、根据类名创建类
  Class cls = NSClassFromString(classNames[i]);
  UIViewController *vc = [[cls alloc] init];

 7、设置button的背景图片
 [button setImage:[[UIImage imageNamed:[NSString stringWithFormat:@"tab_%d.png", i]] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal] forState:UIControlStateNormal];

 8、维护有一个数组的视图或者控制器
 —1、UITabBarController维护了一个数组,数组元素是视图控制器(UIViewController),
     可以通过该数组的索引值来选择不同的视图

 —2、


 —3、

 9、自定义的UITabBarController需要把系统的隐藏掉
 通过初始化init函数
 [self.tabBar setHidden:YES]; // 把系统的隐藏掉


 10、UIView简单动画
     UIView基于block的动画

 动画效果
         [UIImageView beginAnimations:nil context:nil];
         [UIImageView setAnimationDuration:0.5];
     //动画内容
         CGRect frame = _imageView1.frame;
         frame.origin.x = button.frame.origin.x;
         _imageView1.frame = frame;

         [UIImageView setAnimationDelegate:self];
         [UIImageView commitAnimations];

 11、关于代理方面的概念
 【反向传值】
 //A(委托方)对象要发送数据给B(代理方)对象,A是委托方,B是代理方。A:声明id指针,B:遵从协议。
 【回调】
 //当我们需要完成某个功能模块,但不知道使用功能模块的是哪个对象,通过协议,可以规定接受数据的对象通过哪个方法获得数据。调用该方法的过程称为回调。

 [self.delegate buyMacbook] delegate是带协议的id指针,该指针可以调用协议中声明的方法。


 12、判断某个方法是否存在
 [self.delegate respondsToSelector:@selector(controllerDismiss:)]


 13、视图控制器之间通过add和remove进行view的添加和移除
 childViewController需要注意的地方
 // 添加
     [vc willMoveToParentViewController:self];
         [self addChildViewController:vc];
     [self.view addSubVie:vc.view];
     [vc didMoveToParentViewController:self];

      // 移除
     [vc willMoveToParentViewController:nil];
     [vc.view removeFromSuperview];
     [vc removeFromParentViewController];

 14、模态方式跳转   
     //通过present的方式弹出另一个视图控制器,这种切换视图控制器的方式称为“模态方式”,即通过模态方式跳        转到另外一个视图控制器
     [self presentViewController:controller animated:YES completion:nil];
 令当前视图控制器消失pop
     [self dismissViewControllerAnimated:YES completion:nil];


 15、特殊的函数
 NSLog(@"%s",__func__)   //打印当前函数的名称   -[RootViewController viewWillAppear:]
 NSLog(@"%@", NSStringFromSelector(_cmd));  //打印当前函数名称   viewWillAppear:


 16、动画
     doveImageView.animationImages = doves;//animationImages是个数组,所谓的动画就是,不断变换呈现数组中的元素
     doveImageView.animationDuration = 1.5;
     doveImageView.animationRepeatCount = 0;
     [doveImageView startAnimating];
      [doveImageView stopAnimating];

 17、随机生成一个没有重复元素的可变数组

 把整型数据存储到可变数组中时,需要将整型数据转换成字符串对象;比较两个整数是否相同的时候,不能转换为整型进行判断,按照字符串的比较方法[  isEqualWith  ]来进行比较。


 18、视图的边界
 self.view.bounds 类似于self.view.bounds


 19、判断两个frame有无交集
  bool ret = CGRectIntersectsRect(bullet.frame, enemy.frame);

 20、OC区分函数,不管参数类型

 21、继承于UIResponder的控件都可以响应手势,继承与UIView的控件都可以动画

 22、在数组中添加整型数据
     _array[0]=@2;
     NSLog(@"%d",[_array[0] intValue]);

 23、red green blue    #FF FF FF    255 255 255

 24、用随机数函数生成需要的浮点型数据时,写成arc4random()%256.0/255这样,可能会报错
     解决办法:    arc4random()%256/255.0n

 25、UIAlertView视图不需要添加到任何视图当中,它调用的显示函数是[alert show];

 26、常见手势应用
     [self addTapGesture];//添加点击手势
     [self addPanGesture];//拖动手势
 //    [self addLongPress];//长按
     [self addPinchGesture];//捏合
     [self addRotationGesture];//旋转
     [self addSwipeGesture];//快速滑动
     /**
      1、长按的话,返回的是longPress的状态(longPress.state)
      2、捏合返回的是一个范围scale,修改transform
         通过该函数CGAffineTransformScale(_imageView.transform, pinch.scale, pinch.scale);
      3、旋转 返回的是一个rotation,旋转的角度,修改的是transform
         通过该函数CGAffineTransformRotate(_imageView.transform, rotation.rotation);
      4、快速滑动   
      设置swipeDown.direction = UISwipeGestureRecognizerDirectionDown;方向
         //默认清扫手势的方向为向右
         //如果要同时支持多个方向,必须对不同的swipe对象添加不同的方向

 27、//隐藏状态栏
 - (BOOL)prefersStatusBarHidden{
     return YES;
 }

 28、//从plist文件中读取数据
     NSArray *array =[NSArray arrayWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"AlbumData" ofType:@"plist"]];


 29、通过以下方式获得图片系统不会缓存
     NSArray *array = [imageName componentsSeparatedByString:@"."];
     NSString *filePath = [[NSBundle mainBundle]pathForResource:array[0] ofType:array[1]];//根据字符串生成一个路径
     UIImage *image = [UIImage imageWithContentsOfFile:filePath];

 30、类A继承于类B,在类A中添加方法称之为添加类别

 31、 [mArray removeObjectsInArray:self.removeArray];//把两个数组中相同的元素删除

 32、UITableView 里面的复用方法
     // 复用
     // dequeue: 出队,出队列
     // tableView维护了一个队列,当有空闲cell的时候,先从队列中取空闲cell, 如果没有空闲cell, 则创建
     // 刚开始的时候,UITableView里面维护的这个队列是空的,什么都没有
  static NSString *cellID = @"cellID";
     UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID];
     if(cell == nil){
         cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellID];//UITableViewCellStyleSubtitle这种样式才能显示出分数
     }

 
33、    
    // 面试题:什么时候用block, 什么时候用delegate
 
    // delegate和block都能用来不同的对象之间传值
     // 如果回调方法有很多,建议用delegate
     // block简单好用

     代码块使用方法一:
         SecondViewController向RootViewController 传值。
     首先,在SecondViewController声明block类型的代码块指针typedef void (^BlockHandlerType)(NSString *str);,其次定义该代码块类型的变量,并声明一个使用该变量的函数,然后在.m文件中调用这个方法_myBlock(str);,最后在RootViewController中调用该方法,因为方法的参数是该代码块,代码块的参数就可以传给RootViewController了,代码块的实现在RootViewController中实现。
         //可以理解成:_myBlock它指向了一个代码块,而这片代码块却是写在第一个视图控制器中,我们在这里调用_myBlock(str),实际上是调用了在第一个视图控制器的中的一片代码块


 34、根据文本的大小计算label的Size,举例如下
    CGSize textSize = [str boundingRectWithSize:CGSizeMake(self.label.frame.size.width, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:18.0]} context:nil].size;
 参数:    
     //字体
     //constraintedSize
     //换行模式
 35、在UITableViewController里面维护了一个UITableView
     也就是说,在各种controller里面都维护了一个相应的view


 36、instancetype 和id类型用法一样但是,instancetype更好一些

 + (instancetype)stringWithString:(NSString *)string;

 37、结构体怎么赋值(脑子进水了,绝对是)举例:
 typedef struct {
     Color color;
     Number num;
 }PokerCard;

 PokerCard m = {heart,A};
 顺便提一下:用typedef给结构体或者是枚举起别名的时候,可以省略原先的名字,直接写别名

 37、1,self  是什么 ,super 是什么
    > 在动态方法中,self代表着"对象"
    > 在静态方法中,self代表着"类"
    > 万变不离其宗,记住一句话就行了:self代表着当前方法的调用者
 self 和 super 是oc 提供的 两个保留字。 但有根本区别,
     self是类的隐藏的参数变量,指向当前调用方法的对象(类也是对象,类对象),另一个隐藏参数是_cmd,代表当前类方法的selector。
     super并不是隐藏的参数,它只是一个"编译器指示符"

 38、显示小角标
 此外UITabBarItem还有一个属性badgeValue,通过设置该属性可以在其右上角显示一个小的角标,通常用于提示用户有新的消息,使用很简单。
 在对应的TabView中实现以下语句即可。
 self.navigationController.tabBarItem.badgeValue=@"5";
 如果没有前置的naviegationController.就直接调用self.tabBarItem.badgeValue=@"5";

 39、 打印当前方法   
 NSLog(@"%@",NSStringFromSelector(_cmd));

 40、  观察者模式
   // - (void)addObserver:(id)observer selector:(SEL)aSelector name:(NSString *)aName object:(id)anObject;
     // observer 观察者
     // aName:通知的名字
     // aSelector: 方法
     // 通知,观察者模式
     // anObject谁发的通知,一般写为nil就行了
     // [NSNotificationCenter defaultCenter]通知中心
     [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playEnd) name:MPMoviePlayerPlaybackDidFinishNotification object:nil];
     // 点击done按钮->视频播放器会自动通过通知中心发送MPMoviePlayerPlaybackDidFinishNotification这条广播
     // [[NSNotificationCenter defaultCenter] postNotificationName:MPMoviePlayerPlaybackDidFinishNotification object:nil];
     //每个应用程序有且只有一个通知中心的对象(单例),可以理解为广播站,任何对象都可以通过通知中心发送广播
     //任何对象都可以通过通知中心注册成为某条广播的观察者(具有接收/收听某条广播能力的对象)
     //在通知中心注册self为MPMoviePlayerPlaybackDidFinishNotification广播的观察者,一旦有其他对象发送这条广播,self就能接收到并触发playBack方法
     //addObserver 添加观察者, selector 触发的方法,name:广播的名称