项目中的坑

指针

指针问题

例如:int * p 代表这个指针指向的类型是int;

例如:int numbers[4] = {10,20,30,40};

打印:NSLog(@"%p",numbers);打印结果:0x7fff5fbff810。是这个数组的首地址
打印:NSLog(@"%p",&numbers[0]);打印结果:0x7fff5fbff810。也是这个数组的首地址
打印:
    for (NSInteger i = 0; i< 4; i++) {
            NSLog(@"&numbers[%zd] == %p",i,&numbers[i]);
        }
    结果:
2016-05-25 11:59:19.295 JX-指针[2139:86165] &numbers[0] == 0x7fff5fbff810
2016-05-25 11:59:19.295 JX-指针[2139:86165] &numbers[1] == 0x7fff5fbff814
2016-05-25 11:59:19.295 JX-指针[2139:86165] &numbers[2] == 0x7fff5fbff818
2016-05-25 11:59:19.295 JX-指针[2139:86165] &numbers[3] == 0x7fff5fbff81c

地址每个地址之间相差4,是类型占用的字节数
打印:int *p;
        p = &numbers[0];
        NSLog(@"%p,%p",p,p+1);
结果:0x7fff5fbff810,0x7fff5fbff814

结论:指针 + 1 会根据指针所指向的类型来自动判断地址
打印:NSLog(@"%p  -- %p",numbers,numbers + 1);
结果:0x7fff5fbff810  -- 0x7fff5fbff814
结论:数组名也是相当于数组元素的首地址指针,当期+1之后的结果也跟其类型有关
打印:NSLog(@"%p  -- %p",numbers,numbers + 1);
     NSLog(@"%p  -- %p",&numbers,&numbers + 1);
结果:0x7fff5fbff810  -- 0x7fff5fbff814 // 跨度为4
     0x7fff5fbff810  -- 0x7fff5fbff820 // 跨度为16
     int nmbers[4] = {10203040};
     int *p = (int *)(&numbers +1):
     *(p - 1);
     &numbers指的是整个数组,
     + 1 就是跨度为整个数组,指向了数组最后一位的后一位,超出数组范围
     (int *)就是将其强转成int类型,赋值给指针p
     之后指针p - 1 :因为其指针类型已经是int,所以就向后跨度一个类型字节,就是指向了40

指针 P + N : 代表P中存储的地址 + N * P所指向的类型实际占用的字节数

指针 P - N : 代表P中存储的地址 - N * P所指向的类型实际占用的字节数

P = &numbers[0]:代表指针P指向的是数组中10所在的地址

数组名:代表数组地址,也是数组元素的首地址;也相当与指向数组元素的指针

numbers:代表&numbers[0],也等价于指针numbers[0]的指针

&numbers:等价于指向numbers的指针,所以跨度就是整个指针, + 1 就是代表整个数组所占的空间的字节

指针存储

UICollectionViewController中的cell点击不能执行代理方法

其中可能的原因就是在其上添加了tap点击手势,拦截了代理方法

小项目总结

微博动画

类似微博启动动画

  1. 自己封装一个动态控件,因为只是一个固定的布局,使用xib。
  2. 在使用xib创建好类,继承自UIView,关联
  3. 关联好之后先写一个类方法来加载xib
  4. 在控件添加到控制器上之后来设置动画
// 这个方法是当添加到父控件上时候调用
- (void)didMoveToSuperview
#import "JXWelcome.h"

@interface JXWelcome ()
@property (weak, nonatomic) IBOutlet UIImageView *shareImage;
@property (weak, nonatomic) IBOutlet UIImageView *iconImage;
@property (weak, nonatomic) IBOutlet UILabel *welcomeLabel;

@end

@implementation JXWelcome

+ (instancetype)welcome {
    return [[[NSBundle mainBundle] loadNibNamed:NSStringFromClass(self) owner:nil options:nil] lastObject];
}


// 当将要加载到父视图上的时候
- (void)didMoveToSuperview {
    // 设置头像属性
    self.iconImage.layer.cornerRadius = self.iconImage.bounds.size.width / 2;
    self.iconImage.clipsToBounds = YES;
    self.iconImage.transform = CGAffineTransformMakeTranslation(0, 100);

    // 添加微博标志动画,
    [UIView animateKeyframesWithDuration:1 delay:0 options:UIViewKeyframeAnimationOptionCalculationModeLinear animations:^{
        // 隐藏微博问候语
        self.shareImage.alpha = 0;
    } completion:^(BOOL finished) {

        self.iconImage.hidden = NO;
        // 设置头像动画
        [UIView animateWithDuration:1 delay:0 usingSpringWithDamping:0.5 initialSpringVelocity:0 options:UIViewAnimationOptionCurveLinear animations:^{
            self.iconImage.transform = CGAffineTransformIdentity;
        } completion:^(BOOL finished) {
            self.welcomeLabel.alpha = 0;
            self.welcomeLabel.hidden = NO;
            // 设置欢迎文字
            [UIView animateWithDuration:1 animations:^{
                self.welcomeLabel.alpha = 1;
            } completion:^(BOOL finished) {
                [self removeFromSuperview];
            }];
        }];
    }];

}
@end

导航栏

// 如果要设置背景图片,必须填UIBarMetricsDefault,默认导航控制器的子控制器的view尺寸会变化。
// 设置导航条背景图片,一定要在导航条显示之前设置
// 直接在子控制器上的viewDidLoad这个方法中使用的话,因为控制器的view都是懒加载,所以在使用的时候,设置导航栏背景是无用的

获取当前所有的导航栏,这里可以一次性设置所有的导航栏

   // 但是设置这个属性的时候回改变系统的导航栏,例如调用相册的时候,真机调试的时候会有bug
    UINavigationBar * bar = [UINavigationBar appearance];
    [bar setBackgroundImage:[UIImage imageNamed:@"NavBar64"] forBarMetrics:UIBarMetricsDefault];

但是这个方法会一次性设置全部的导航栏,包括我们系统的默认的导航栏

      // 获取哪个类,在ios9之后我们可以使用这个来设置我们自定义的类的导航栏
    UINavigationBar * bar = [UINavigationBar appearanceWhenContainedInInstancesOfClasses:@[[self class]]];
    [bar setBackgroundImage:[UIImage imageNamed:@"NavBar64"] forBarMetrics:UIBarMetricsDefault];
 // iOS9之前的方法
    UINavigationBar * bar = [UINavigationBar appearanceWhenContainedIn:self,nil];
    [bar setBackgroundImage:[UIImage imageNamed:@"NavBar64"] forBarMetrics:UIBarMetricsDefault];

// 当前类或者他的子类第一次使用的时候才会调用,而且只会调用一次
+ (void)initialize {
    // 获取当前所有的导航栏
    // 设置导航栏属性,不需要考虑是否存在导航条,只需要执行一次
    // 但是设置这个属性的时候回改变系统的导航栏,例如调用相册的时候,真机调试的时候会有bug
//    UINavigationBar * bar = [UINavigationBar appearance];
//    [bar setBackgroundImage:[UIImage imageNamed:@"NavBar64"] forBarMetrics:UIBarMetricsDefault];

    // 获取哪个类
    UINavigationBar * bar = [UINavigationBar appearanceWhenContainedInInstancesOfClasses:@[[self class]]];
    [bar setBackgroundImage:[UIImage imageNamed:@"NavBar64"] forBarMetrics:UIBarMetricsDefault];
    // 设置导航条文字颜色
    [bar setTintColor:[UIColor whiteColor]];
    // 设置导航栏标题颜色
    NSMutableDictionary * dict = [NSMutableDictionary dictionary];
    dict[NSForegroundColorAttributeName] = [UIColor whiteColor];
    dict[NSFontAttributeName] = [UIFont boldSystemFontOfSize:18];
    [bar setTitleTextAttributes:dict];
}

调用方法

// 当前类或者他的子类第一次使用的时候才会调用,而且只会调用一次
+ (void)initialize {}

@property在类扩展中使用的话,只会生成set,get方法,不会生成_成员属性,以及方法的实现、

self.view.frame这个frame就是在类别中使用

类方法中不能访问成员属性,需要使用类.属性来访问。

// 在.h文件中
#import "JXMenuView.h"
#import "JXMenuModel.h"
#define kCols 3

@interface JXMenuView ()
/** 测试属性 */
@property (nonatomic,strong) NSArray * array;
@end

@implementation JXMenuView

+ (void)show {
    JXMenuView * menu = [[self alloc] init];
    menu.array;// 这样子来调用访问属性
}

设置导航栏背景

// 设置导航栏背景颜色,必须在导航栏还没有显示的时候设置,如果自定义导航栏,在其中设置了背景颜色,那么这里设置就会失败
    // 图片尺寸不够需要拉伸
    UIImage * image = [UIImage imageNamed:@"NLArenaNavBar64"];
    image = [image stretchableImageWithLeftCapWidth:image.size.width * 0.5 topCapHeight:image.size.height * 0.5];
    [self.navigationController.navigationBar setBackgroundImage:image forBarMetrics:UIBarMetricsDefault];

重写,自定义控制器view

// 重写,自定义控制器view
- (void)loadView {
    UIImageView * imageView = [[UIImageView alloc] initWithFrame:JXBouns];
    imageView.image = [UIImage imageNamed:@"NLArenaBackground"];
    // 打开交互
    imageView.userInteractionEnabled = YES;
    self.view = imageView;

}

当UITabViewController中的单元格是固定的,我们可以用静态单元格,静态单元格的设置方法

静态单元格

加载的时候使用方法,这里不需要绑定类

// 发现
    // 采用storyBoard设置
    UIStoryboard * storyBoard = [UIStoryboard storyboardWithName:@"JXDiscoverViewController" bundle:nil];
    JXDiscoverViewController * discover = [storyBoard instantiateInitialViewController];

自定义UIButton,定义图片在文字右边

- (void)layoutSubviews {
    [super layoutSubviews];
    CGFloat titleX = self.titleLabel.width;
    CGFloat imageX = self.imageView.x;
    if (self.imageView.x < self.titleLabel.x) { // 当图片在文字左边的时候调用
        self.titleLabel.x = imageX;
        self.imageView.x = titleX;
    }

}

当更改UIButton中内容的时候,我们需要设置[self sizeToFit];为自适应。我们可以重写设置方法,来调用的时候自动刷新

- (void)setTitle:(NSString *)title forState:(UIControlState)state {
    [super setTitle:title forState:state];
    // 自适应,自动计算宽度高度
    [self sizeToFit];
}

获取segue线

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    UIViewController * vc = segue.destinationViewController;// 目的控制器
    UIViewController * vc = segue.sourceViewController; // 源控制器
    vc.hidesBottomBarWhenPushed = YES;
}

获取版本号码

// 获取info.plist文件中
[NSBundle mainBundle].infoDictionary

启动效果

启动效果,启动检测有更新,会显示引导图,引导图上动画是向左滑动的时候图片从右向左进入,向右滑动的时候图片从右向左进入

    CGFloat offsetX = scrollView.contentOffset.x;
    CGFloat distance = offsetX - self.oldOffsetX;

    // 先将位置移动到下一个位置
    self.guideLargetView.x += distance * 2;
    self.guideSmallView.x += distance * 2;
    self.guideView.x += distance * 2;

    [UIView animateWithDuration:0.5 animations:^{
        self.guideView.x -= distance;
        self.guideSmallView.x -= distance;
        self.guideLargetView.x -= distance;
    }];
    int page = offsetX / JXWidth + 1;
    // 修改控件的内容
    self.guideView.image = [UIImage imageNamed:[NSString stringWithFormat:@"guide%d",page]];
    self.oldOffsetX = offsetX;

当push的时候隐藏栏

  - (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated { // 当导航控制器push的时候回调用这个方法。

    if (self.viewControllers.count != 0) { // 第一次的时候还没走到super这个方法,所以self.viewControllers.count还是为0,当不为0的时候就隐藏
        viewController.hidesBottomBarWhenPushed = YES;
    }

    [super pushViewController:viewController animated:animated];

}

自定义导航控制器

// 当前类或者他的子类第一次使用的时候才会调用,而且只会调用一次
+ (void)initialize {
    // 获取当前所有的导航栏
    // 设置导航栏属性,不需要考虑是否存在导航条,只需要执行一次
    // 但是设置这个属性的时候回改变系统的导航栏,例如调用相册的时候,真机调试的时候会有bug
//    UINavigationBar * bar = [UINavigationBar appearance];
//    [bar setBackgroundImage:[UIImage imageNamed:@"NavBar64"] forBarMetrics:UIBarMetricsDefault];

    // 获取哪个类
    UINavigationBar * bar = [UINavigationBar appearanceWhenContainedInInstancesOfClasses:@[[self class]]];
    [bar setBackgroundImage:[UIImage imageNamed:@"NavBar64"] forBarMetrics:UIBarMetricsDefault];

    // 设置导航栏标题颜色
    NSMutableDictionary * dict = [NSMutableDictionary dictionary];
    dict[NSForegroundColorAttributeName] = [UIColor whiteColor];
    dict[NSFontAttributeName] = [UIFont boldSystemFontOfSize:18];
    [bar setTitleTextAttributes:dict];

  // 设置导航返回图片
   // 当不是跟控制器的时候设置返回按钮
        UIImage * image = [UIImage imageWithRenderingOriginalImage:@"NavBack"];
        UIBarButtonItem * bar = [[UIBarButtonItem alloc] initWithImage:image style:UIBarButtonItemStylePlain target:self action:@selector(back:)];
        viewController.navigationItem.leftBarButtonItem = bar;
}

设置返回按钮


    [bar setTintColor:[UIColor whiteColor]];
    [[UIBarButtonItem appearance] setBackButtonTitlePositionAdjustment:UIOffsetMake(0, -100) forBarMetrics:UIBarMetricsDefault];

results matching ""

    No results matching ""