OC的那些事

  1. NSObject * __weak someObject = [[NSObject alloc] init];, 这个someObject没有对象强引用他, 所以这行代码之后会立马被置为nil, NSObject * __weak someObject = self.someObject, 这个someObject在这行代码之后不会立刻被置为nil, 而是会在所在的代码块结束后被置为nil。

  2. oc中的对象是动态管理(内存)的, 是分配在heap(堆)上所以需要一个指针来指向它(才能访问), 所以对象类型需要用 星号 NSString * str;

  3. 比较是否相同: 使用 if(a==b) {}, 如果a,b是对象类型, 那么比较的是指针是否相同, 而不是比较值是否相同, 如果a, b是基本类型(int, double...), 那么比较的是值是否相同; 使用if ([a isEqual: b]) { }, 则比较的是a,b的值是否相同。

4. 初始化基本类型的时候尽量设置初始值, 因为编译器分配的初始值并不确定, 但是对象类型会默认初始化为nil。

oc中属性的getter和setter@property (nonatomic) NSString *name;

例如当有这样一个name属性的时候, 默认是readWrite的, 编译器会自动生成一个set (setName:)和get(-(NSString *)name)方法, 这个时候可以通过set或者get方法访问到name, 如果申明为(readonly), 那么将只会生成get方法

[self setName:@"set name"];

NSString *getName = [self name];

也可以通过点语法访问(实际上是会自动调用set和get方法)

self.name = @"set name";

NSString *dotName = self.name;

同时你可以重写name的get(懒加载...)和setter(拦截set方法)...对应name属性, 编译器会生成(synthesize)一个 _name 允许我们直接通过指针访问变量, 而不会调用get方法, 所以通过_xx访问的变量不会调用懒加载(get方法), 所以在写懒加载方法的时候, 不能使用self.xx(造成死循环), 而要使用_xx -

(NSString *)name {
// 这里面不能使用self.name , 因为点语法会调用这个get方法, 造成死循环
if (_name == nil) {
_name = @"name";
}
return _name;
}

同时这个synthesize的名字我们是可以自己修改的, 使用如下的语法@synthesize name = customName;

那么这个时候就不能通过 __name访问到name了, 因为我们已经指定了通过customName才能访问到了NSString *getName = customName;

当然如果, 你是这样写的 @synthesize name;, 并没有指定名字, 这个时候访问的时候就直接使用变量名而不需要加下划线( _ )了 name = @"set name"; ??这个时候就比较爽了, 和swift,java这些一样, 不需要self,this了;

5,分类(category)定义的函数和属性在运行时中和原生的class中定义的东西并没有区别At runtime, there’s no difference between a method added by a category and one that is implemented by the original class

6,不过分类中定义的属性, 编译器并不会自动生成getter和setter, 以及_XX变量来访问,需要自己提供getter和setter, 并且需要使用运行时才能绑定这个属性到这个类中, 实现原生类中定义的属性的效果

///例如可能是这样的使用

static const void *propertyKey = &propertyKey;

/// 将value通过运行时绑定到self

objc_setAssociatedObject(self, propertyKey, value, OBJC_ASSOCIATION_RETAIN_NONATOMIC);

/// 将value在运行时中通过propertyKey取出绑定的值

id value = objc_getAssociatedObject(self, propertyKey);

7,同时分类也可以用来将一个复杂的类中的代码分块(swift的extension可以有相似的作用), 使得代码组织更好, 例如可以将tableView的delegate, 和Datasource在分类中实现。

@implementation ViewController(tableview)
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {

}

@end

8,但是在使用category来扩展Cocoa的原生类的时候, 要注意函数的命名如果是和原生已有的函数名相同,那么将会发生不可预料的结果(不能确定哪一个方法在运行时会被调用), 因此建议在自己的函数名前面加上前缀, 就像重写 +load() 来实现各种黑魔法的时候也是可能会发生不可预料的结果, 因为同一个项目中可能有多个地方重写了这个类的 +load方法

9,初始化NSArray的时候, 如果通过NSArray *arr1 = @[object1, object2];, 不需要以nil结尾, 如果通过构造方法初始化, 则需要传入nil结尾, 同时, 如果中间的对象有nil, 那么将在中间nil就结束了, NSArray *arr2 = [NSArray arrayWithObjects:object1, object2, object3, nil, object4, object5, nil] 这个arr2只可能会存储第一个nil前的对象

10,如果在数组中一定要存储nil, 那么只能用NSNull来代替

11,如果NSArray中存储的是NSArray, NSDictionary, NSString, NSData, NSDate , NSNumber这些类型的对象, 那就可以直接写入disk并且读取disk的数据做持久化数据操作[array writeToURL:fileURL atomically:YES], 但是如果是有其他的类型, 就需要使用归档来实现了

12,在oc中block是object类型的, 所以是可以存储在NSArray...中, 同时在调用block的时候, 如果block为nil(未赋值), 那么程序将crash.

13,oc中block可以捕获变量, 什么意思呢 --- 就是block会默认捕获到变量的值, 在之后不受到原来变量的改变的影响, 例如

int anInteger = 42;

void (^testBlock)(void) = ^{

NSLog(@"Integer is: %i", anInteger);

};

anInteger = 84;

testBlock(); ---- 输出的值仍然为 42

14,第二种block捕获变量的方式, 是捕获变量的指针, 被捕获的变量值改变, 则block中的变量值也改变了,不过需要对变量进行__block标记, 例如上面的代码, 只改变一点, 结果就变了

__block int anInteger = 42;

void (^testBlock)(void) = ^{

NSLog(@"Integer is: %i", anInteger);

};

anInteger = 84;

testBlock(); --- 输出值这时是 84

15,preferredMaxLayoutWidth用来制定最大的宽,一般用在多行的UILabel中

systemLayoutSizeFittingSize方法能够获得view的高度

iOS7有两个很有用的属性,topLayoutGuide和bottomLayoutGuide,这个两个主要是方便获取UINavigationController和UITabBarController的头部视图区域和底部视图区域。

16,AutoLayout关于更新的几个方法的区别:

setNeedsLayout:告知页面需要更新,但是不会立刻开始更新。执行后会立刻调用layoutSubviews。

layoutIfNeeded:告知页面布局立刻更新。所以一般都会和setNeedsLayout一起使用。如果希望立刻生成新的frame需要调用此方法,利用这点一般布局动画可以在更新布局后直接使用这个方法让动画生效。

layoutSubviews:系统重写布局

setNeedsUpdateConstraints:告知需要更新约束,但是不会立刻开始

updateConstraintsIfNeeded:告知立刻更新约束

updateConstraints:系统更新约束.

17,AutoLayout情况如何计算UITableView的变高高度

主要是UILabel的高度会有变化,所以这里主要是说说label变化时如何处理,设置UILabel的时候注意要设置preferredMaxLayoutWidth这个宽度,还有ContentHuggingPriority为UILayoutPriorityRequried

CGFloat maxWidth = [UIScreen mainScreen].bounds.size.width - 10 * 2;
textLabel = [UILabel new];
textLabel.numberOfLines = 0;
textLabel.preferredMaxLayoutWidth = maxWidth;
[self.contentView addSubview:textLabel];
[textLabel mas_makeConstraints:^(MASConstraintMaker *make) {
   make.top.equalTo(statusView.mas_bottom).with.offset(10);
   make.left.equalTo(self.contentView).with.offset(10);
   make.right.equalTo(self.contentView).with.offset(-10);
   make.bottom.equalTo(self.contentView).with.offset(-10);
}];
[_contentLabel setContentHuggingPriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisVertical];
如果版本支持最低版本为iOS 8以上的话可以直接利用UITableViewAutomaticDimension在tableview的heightForRowAtIndexPath直接返回即可。
tableView.rowHeight = UITableViewAutomaticDimension;
tableView.estimatedRowHeight = 80; //减少第一次计算量,iOS7后支持

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
   // 只用返回这个!
   return UITableViewAutomaticDimension;
}

但如果需要兼容iOS 8之前版本的话,就要回到老路子上了,主要是用systemLayoutSizeFittingSize来取高。步骤是先在数据model中添加一个height的属性用来缓存高,然后在table view的heightForRowAtIndexPath代理里static一个只初始化一次的Cell实例,然后根据model内容填充数据,最后根据cell的contentView的systemLayoutSizeFittingSize的方法获取到cell的高。具体代码如下

//在model中添加属性缓存高度
@interface DataModel : NSObject
@property (copy, nonatomic) NSString *text;
@property (assign, nonatomic) CGFloat cellHeight; //缓存高度
@end

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
   static CustomCell *cell;
   //只初始化一次cell
   static dispatch_once_t onceToken;
   dispatch_once(&onceToken, ^{
       cell = [tableView dequeueReusableCellWithIdentifier:NSStringFromClass([CustomCell class])];
   });

   DataModel *model = self.dataArray[(NSUInteger) indexPath.row];
   [cell makeupData:model];
   if (model.cellHeight <= 0) {
       //使用systemLayoutSizeFittingSize获取高度
       model.cellHeight = [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height + 1;
   }
   return model.cellHeight;
}

18,UILayoutFittingCompressedSize 表示返回最小可能的值

UILayoutFittingExpandedSize 表示返回最大可能的值

19,使用masonry进行label的多行显示设置时,主要是如下两个参数的设置

1、@property(nonatomic)CGFloat preferredMaxLayoutWidth

2、- (void)setContentHuggingPriority:(UILayoutPriority)priority forAxis:(UILayoutConstraintAxis)axis

//如下

UILabel *label3 = [[UILabelalloc] initWithFrame:CGRectZero];

[self.viewaddSubview:label3];

label3.backgroundColor = [UIColorcolorWithWhite:0.5alpha:0.3];

label3.text =@"Masonry是一个轻量级的布局框架与更好的包装AutoLayout语法。Masonry有它自己的布局方式,描述NSLayoutConstraints使布局代码更简洁易读。Masonry支持iOS和Mac OS X。Masonry github地址:https://github.com/SnapKit/Masonry";

label3.preferredMaxLayoutWidth = (WidthScreen -10.0 * 2);

[label3 setContentHuggingPriority:UILayoutPriorityRequiredforAxis:UILayoutConstraintAxisVertical];
label3.numberOfLines =0;
[label3 mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.mas_equalTo(10.0);
make.right.mas_equalTo(-10.0);
make.top.mas_equalTo(10.0);
}];


分类
Category的作用
可以在不修改原来类的基础上, 为这个类扩充一些方法

一个庞大的类可以分模块开发

一个庞大的类可以由多个人来编写,更有利于团队合作

Category的使用注意:



分类只能增加方法,不能增加成员变量

在分类方法的实现中可以访问原来类的成员变量

分类中可以重新实现原来类的方法,但是会覆盖原来的方法

方法的调用优先级:分类->原来的类->父类

类的启动过程



+load方法



在程序启动的时候会加载所有的类和分类,并调用所有类和分类的+load方法(只会调用一次)

先加载父类,再加载子类;也就是先调用父类的+load,再调用子类的+load

先加载元原始类,再加载分类

不管程序运行过程有没有用到这个类,都会调用+load加载

+initialize



在第一次使用某个类时(比如创建对象等),只会调用一次+initialize方法

一个类只会调用一次+initialize方法,先调用父类的,再调用子类的


打开文件共享权限:在Info.plist文件中添加Application supports iTunes file sharing ,并设置为YES,即可通过iTunes直接导出来



手机上自动安装应用:

`itms-services://?action=download-manifest&url=https://www.xxxxx.com/abc......`
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,189评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,577评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,857评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,703评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,705评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,620评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,995评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,656评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,898评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,639评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,720评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,395评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,982评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,953评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,195评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,907评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,472评论 2 342

推荐阅读更多精彩内容

  • 1.ios高性能编程 (1).内层 最小的内层平均值和峰值(2).耗电量 高效的算法和数据结构(3).初始化时...
    欧辰_OSR阅读 29,299评论 8 265
  • 摘自: http://www.cocoachina.com/ios/20150803/12872.html 说明...
    program袁阅读 872评论 1 3
  • 1.设计模式是什么? 你知道哪些设计模式,并简要叙述? 设计模式是一种编码经验,就是用比较成熟的逻辑去处理某一种类...
    司马DE晴空阅读 1,277评论 0 7
  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 11,084评论 1 32
  • 何为职场之道 逼迫出的世故的笑 无奈的左右逢源 掩饰自己的不愿 ——若是掩饰的滴水不落也可称为道 但没人可以伪装一...
    伍丁零阅读 486评论 0 1