(IOS开发)关于- (CGRect)titleRectForContentRect:(CGRect)contentRect 方法调用时机的个人浅析

  本文乃个人调试观点,若有错误恳请DS不吝赐教!

  MJ网络视频的网易彩票项目中,视频“彩票08-自定义导航栏标题按钮”和视频“彩票09-多版本处理”的前半段,大部分时间都在谈论awakefromnib 以及 - (CGRect)titleRectForContentRect:(CGRect)contentRect 方法的调用时机。可我在用xcode7实际运行时,发现了不一样的地方。

上代码:

#import "MJTitleButton.h"  //    提示:MJTitleButton继承自UIButton

@interface MJTitleButton()

 @property (nonatomic, strong) UIFont *titleFont;

@end

 

@implementation MJTitleButton

/**

 *  当一个对象从xib或者storyboard中加载完毕后,就会调用一次

 */

- (void)awakeFromNib

{

    NSLog(@"---MJTitleButton---awakeFromNib--");

    self.titleFont = [UIFont systemFontOfSize:14];

//    self.titleLabel.font = self.titleFont;  //  第a行

//        self.imageView.contentMode = UIViewContentModeCenter;   //  第b行

 }

 

/**

 *  从文件中解析一个对象的时候就会调用这个方法

 */

//- (instancetype)initWithCoder:(NSCoder *)aDecoder

//{

//    NSLog(@"---MJTitleButton---initWithCoder--");

//    if (self = [super initWithCoder:aDecoder]) {

//        self.titleFont = [UIFont systemFontOfSize:14];

//        self.titleLabel.font = self.titleFont;

//        // 图片居中

//        self.imageView.contentMode = UIViewContentModeCenter;

//    }

//    return self;

//}

 

- (CGRect)titleRectForContentRect:(CGRect)contentRect

{

    NSLog(@"----MJTitleButton----titleRectForContentRect---");

    CGFloat titleX = 0;

    CGFloat titleY = 0;

    NSDictionary *attrs = @{NSFontAttributeName : self.titleFont};

    CGFloat titleW;

    if (IOS7) { // 提示:IOS7 是个宏,意为系统版本大于等于7才能运行下面代码

        titleW = [self.currentTitle boundingRectWithSize:CGSizeMake(MAXFLOAT, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin attributes:attrs context:nil].size.width;

    }else{

        titleW = [self.currentTitle sizeWithFont:self.titleFont].width;

    }

    CGFloat titleH = contentRect.size.height;

    return CGRectMake(titleX, titleY, titleW, titleH);

}

 

- (CGRect)imageRectForContentRect:(CGRect)contentRect

{

    CGFloat imageH = contentRect.size.height;

    CGFloat imageW = 30;

    CGFloat imageY = 0;

    CGFloat imageX = contentRect.size.width - imageW;

    return CGRectMake(imageX, imageY, imageW, imageH);

}

  上面代码和视频09第2分钟(以下简称视频02)的演示相同,当时MJ用的Xcode5,根据打印显示,运行后调用了titleRectForContentRect方法,awakeFromNib方法并没有调用,而我在Xcode7运行中刚好相反,titleRectForContentRect方法不调用,awakeFromNib方法调用。 

  我实际调试能明确的是,titleRectForContentRect方法只在用的时候才会调用,比如打开第a行,或者第b行,由于访问self.titleLabe、 self.imageView属性都会调用该方法以获得title的frame。

  而视频02给我的感觉是不访问self.titleLabe或者self.imageView,刚运行成功也会调用1次titleRectForContentRect方法。可是再看4分48秒,注释掉awakeFromNib,并打开上面的initWithCoder方法后,共调用了3次titleRectForContentRect方法。注意,刚刚说了实际xcode7运行后,titleRectForContentRect只在用的时候才会调用。那就存在疑问:若按照视频02所演示,不访问属性也会调用titleRectForContentRect方法,那视频4分末在访问属性后,调用次数应该是1 +  3 = 4次,而不是3次。可视频中就是3次,正好我调试也是3次,如果这能说明titleRectForContentRect也是在使用时候才调用,那就和视频02得到的反馈不对。

  我调试可以肯定的是,awakeFromNib和titleRectForContentRect 调用顺序没有必然关系,titleRectForContentRect调用与否要看是否用的上,awakeFromNib是在initWithCoder方法将对象解析完后,发现对象是来自storyboard才会调用。如果initWithCoder方法中访问的属性需要调用titleRectForContentRect方法,那么titleRectForContentRect早于awakeFromNib调用,如果在awakeFromNib方法才访问属性,那先调用awakeFromNib再调用titleRectForContentRect。

  虽然视频02的演示会让我们对titleRectForContentRect方法调用时机产生质疑。庆幸的是我们不需要为此担忧,可以根据自己代码调试后,再实事求是的决定将上面2个属性赋值代码是放在initWithCoder还是awakeFromNib方法中。保险的方式,当然是放在initWithCoder方法中,确保属性确实赋值。awakeFromNib方法不太靠谱。

   titleRectForContentRect方法我个人相信是在用的时候才调用,对视频02不明所以就调用titleRectForContentRect存在疑问,如果有大神知道,还恳请留言赐教!

posted on 2015-12-13 23:52  X强人艺  阅读(629)  评论(0)    收藏  举报