当前位置: 首页 > 面试题库 >

iOS中属性修饰符的作用?

宗政招
2023-03-14
本文向大家介绍iOS中属性修饰符的作用?相关面试题,主要包含被问及iOS中属性修饰符的作用?时的应答技巧和注意事项,需要的朋友参考一下

ios5之前是MRC,内存需要程序员进行管理,ios5之后是ARC,除非特殊情况,比如C框架或者循环引用,其他时候是不需要程序员手动管理内存的。
  ios中当我们定义属性@property的时候就需要属性修饰符,下面我们就看一下不同属性修饰符的作用。有错误和不足的地方还请大家谅解并批评指正。

主要的属性修饰符有下面几种:

  • copy
  • assign
  • retain
  • strong
  • weak
  • readwrite/readonly (读写策略、访问权限)
  • nonatomic/atomic (安全策略)

如果以MRC和ARC进行区分修饰符使用情况,可以按照如下方式进行分组:

 1. MRC: assign/ retain/ copy/  readwrite、readonly/ nonatomic、atomic  等。
 2. ARC: assign/ strong/ weak/ copy/ readwrite、readonly/ nonatomic、atomic  等。

属性修饰符对retainCount计数的影响。

  1. alloc为对象分配内存,retainCount 为1 。
  2. retain MRC下 retainCount + 1。
  3. copy 一个对象变成新的对象,retainCount为 1, 原有的对象计数不变。
  4. release 对象的引用计数 -1。
  5. autorelease 对象的引用计数 retainCount - 1,如果为0,等到最近一个pool结束时释放。

不管MRC还是ARC,其实都是看reference count是否为0,如果为0那么该对象就被释放,不同的地方是MRC需要程序员自己主动去添加retain 和 release,而ARC apple已经给大家做好,自动的在合适的地方插入retain 和 release类似的内存管理代码,具体原理如下,图片摘自官方文档。

MRC 和 ARC原理

下面就详述上所列的几种属性修饰符的使用场景,应用举例和注意事项。

一、copy

使用场景

  1. 一般情况下,copy可以用于对不可变容易的属性修饰中,主要是NSArray /NSDictionary/NSString, 也可以用来修饰block。
  2. 在MRC和ARC下都可以使用。
  3. 其setter方法,与retain处理流程一样,先旧值release,再copy出新的对象。

应用举例

@property (nonatomic, copy) NSString* name;
@property (nonatomic, copy) void(^typeBlock)(BOOL selected);
@property (nonatomic, copy) void(^cancelBlock)();

注意事项

  1. 要注意的就是深浅拷贝,这个也是使用copy这个属性修饰符最重要的地方,这以后会在另一篇文章里面单独讲。
  2. MRC 和 ARC 都可以用copy。
  3. copy下的setter方法。
-(void)setName: (id)newName {
      if (name != newName) {
        [name release];
        name = [newName copy];
     }
}
  1. 用copy修饰block时在MRC和ARC下的区别
  • MRC环境下
    (1)block访问外部局部变量,block存放在栈里面。
    (2)只要block访问整个app都存在的变量,那么肯定是在全局区。
    (3)不能使用retain引用block,因为block不在堆区里面,只有使用copy才会把block放在堆区里面。

  • ARC环境下
    (1)只要block访问外部局部变量,block就会存放在堆区。
    (2)可以使用strong去引用,因为本身就已经存放在堆区了。
    (3)也可以使用copy进行修饰,但是strong性能更好。

  1. 当使用block的时候注意循环引用,引起内存无法释放,造成内存泄漏

AddSignHeaderView.h文件中定义block
@property (nonatomic, copy) void (^addMembersBtnOnClick)();

AddSignViewController.m文件中调用block

// 懒加载控件
- (AddSignHeaderView *)headerView {
    if (!_headerView) {
        _headerView = [[AddSignHeaderView alloc] initWithFrame:CGRectMake(0, 0, ScreenWidth, 170)];
    }
    return _headerView;
}

// 调用block
-(void) viewDidLoad {
    __weak typeof(self) weakSelf = self;
    self.headerView.addMembersBtnOnClick = ^() {
        AddSignContactsSelectVC *addSign = [[AddSignContactsSelectVC alloc] initWithBlockSelectedUsernames:weakSelf.contactsSource];
        addSign.hidesBottomBarWhenPushed = YES;
        addSign.title = @"选择联系人";
        addSign.delegate = weakSelf;
        [weakSelf.navigationController pushViewController:addSign animated:YES];
    };
}


 类似资料:
  • private private修饰符是我们使用的最限制的修饰符。它表示它只能被自己所在的文件可见。所以如果我们给一个类声明为private,我们就不能在定义这个类之外的文件中使用它。 另一方面,如果我们在一个类里面使用了private修饰符,那访问权限就被限制在这个类里面了。甚至是继承这个类的子类也不能使用它。 所以一等公民,类、对象、接口……(也就是包成员)如果被定义为private,那么它们只

  • Kotlin中这些修饰符是与我们Java中的使用是有些不同的。在这个语言中默认的修饰符是public,这节约了很多的时间和字符。但是这里有一个详细的解释关于在Kotlin中不同的可见性修饰符是怎么工作的。

  • 问题内容: 在类的前面和构造函数的前面使用修饰符(在本例中为package- private)有什么区别?我认为构造函数前面的修饰符意味着可以实例化该类的实例。但是班级前面的修饰符呢? 问题答案: 首先,由3个访问修饰符创建4个访问级别。 公共-随处可见 受保护-可在同一个包装中以及儿童中使用 默认-仅在同一程序包中可访问 私人-仅在同一班级可以访问。 您是正确的-构造函数级别的修饰符与类的实例直

  • 我在中定义了一个实例变量,并希望在的方法中初始化它。 在中有什么方法可以做到这一点吗?

  • JAVA访问修饰符的可访问性 公众 在 同一班级 同一套餐 子类 宇宙/其他软件包 我在互联网上寻找这些问题的答案,因为我有多个答案。一个视频说未声明的访问修饰符是公共的,而我看到另一个书面来源说未声明的访问修饰符在子类和其他包中没有限制。试图确认哪个是真的。

  • 我的application.properties(读取环境变量) MyService类: 给它赋值并不能解决问题。例如,用 null 对于我所读的内容,我需要一个委托的(https://kotlinlang.org/docs/reference/delegated-properties.html),但我不能完全理解它。另外,如果有一个“更干净”的解决方案,我不想编写另一个方法来设置属性。有什么想法