wq's blogs

王乾


  • 首页

  • 分类

  • 标签

  • 归档

在block内如何修改block外部变量?

发表于 2020-04-13 | 分类于 iOS开发技巧

在block内如何修改block外部变量?

1、Block中不允许修改外部变量的值。这里所说的外部变量的值,指的是栈中指针的内存地址。__block修饰之后,立马将“外部变量在栈中的内存地址放到堆中”,如果不做特殊修改就一直在堆中,进而做到在block内部修改外部变量。

2、大小比较:堆地址要小于栈地址。iOS中一个进程的栈区内存只有1M,Mac也只有8M。

3、这里的a已经由基本数据类型,变成了对象类型。block会对对象类型的指针进行copy,copy到堆中,但并不会改变该指针所指向的堆中的地址

__block int a = 5;
NSLog(@"定义前:%p",&a); // 1、栈中
void (^foo)(void) = ^{
    a = 6;
    NSLog(@"block内部:%p",&a); //3、堆中
};
NSLog(@"定义后:%p",&a);//2、堆中
foo();

定义前:0x16fda86f8
定义后:0x155b22fc8
block内部: 0x155b22fc8


NSMutableString *a = [NSMutableString stringWithString:@"Tom"];
NSLog(@"\n 定以前:------------------------------------\n\
      a指向的堆中内存对象的地址:%p;a在栈中的指针地址:%p", a, &a);
void (^foo)(void) = ^{
    a.string = @"Jerry";
    NSLog(@"\n block内部:------------------------------------\n\
     a指向的堆中内存对象的地址:%p;a在栈中的指针地址:%p", a, &a);
//        a = [NSMutableString stringWithString:@"William"];
};
foo();
NSLog(@"\n 定以后:------------------------------------\n\
      a指向的堆中内存对象的地址:%p;a在栈中的指针地址:%p", a, &a);
阅读全文 »

autoreleasepool

发表于 2020-04-08 | 分类于 iOS开发技巧

objc使用什么机制管理对象内存?

通过 retainCount 的机制来决定对象是否需要释放。 每次 runloop 的时候,都会检查对象的 retainCount,如果retainCount 为 0,说明该对象没有地方需要继续使用了,可以释放掉了。

ARC通过什么方式帮助开发者管理内存?

ARC相对于MRC,不是在编译时添加retain/release/autorelease这么简单。应该是编译期和运行期两部分共同帮助开发者管理内存。
在编译期,ARC用的是更底层的C接口实现的retain/release/autorelease,这样做性能更好,也是为什么不能在ARC环境下手动retain/release/autorelease,同时对同一上下文的同一对象的成对retain/release操作进行优化(即忽略掉不必要的操作);ARC也包含运行期组件,这个地方做的优化比较复杂,但也不能被忽略。

阅读全文 »

iOS中常用的几种_持久化存储方式

发表于 2020-04-03 | 分类于 iOS开发技巧

前言

iOS中常用的持久化存储方式有好几种:

  • 偏好设置(NSUserDefaults)
  • plist文件存储
  • 归档
  • SQLite3
  • Core Data
  • KeyChain

    沙盒

每个iOS应用都有自己的应用沙盒(应用沙盒就是文件系统目录),与其他文件系统隔离。应用必须待在自己的沙盒里,其他应用不能访问该沙盒。沙盒下的目录如下:

  • Application:存放程序源文件,上架前经过数字签名,上架后不可修改
  • Documents: 保存应⽤运行时生成的需要持久化的数据,iTunes同步设备时会备份该目录。例如,游戏应用可将游戏存档保存在该目录
  • tmp: 保存应⽤运行时所需的临时数据,使⽤完毕后再将相应的文件从该目录删除。应用 没有运行时,系统也可能会清除该目录下的文件。iTunes同步设备时不会备份该目录。
  • Library/Caches: 保存应用运行时⽣成的需要持久化的数据,iTunes同步设备时不会备份 该目录。⼀一般存储体积大、不需要备份的非重要数据,比如网络数据缓存存储到Caches下
  • Library/Preference: 保存应用的所有偏好设置,如iOS的Settings(设置) 应⽤会在该目录中查找应⽤的设置信息。iTunes同步设备时会备份该目录
阅读全文 »

runloop

发表于 2020-04-02 | 分类于 iOS开发技巧

runloop和线程有什么关系?

总的说来,Run loop,正如其名,loop表示某种循环,和run放在一起就表示一直在运行着的循环。实际上,run loop和线程是紧密相连的,可以这样说run loop是为了线程而生,没有线程,它就没有存在的必要.每个线程包括程序的主线程(main thread)都有与之对应的run loop对象。

1、主线程的run loop默认是启动的。

iOS的应用程序里面,程序启动后会有一个如下的main()函数

int main(int argc, char * argv[]) {
   @autoreleasepool {
   return UIApplicationMain(argc, argv, nil,     NSStringFromClass([AppDelegate class]));
   }
}

重点是UIApplicationMain()函数,这个方法会为main thread设置一个NSRunLoop对象,这就解释了:为什么我们的应用可以在无人操作的时候休息,需要让它干活的时候又能立马响应。

2、对其它线程来说,run loop默认是没有启动的,如果你需要更多的线程交互则可以手动配置和启动,如果线程只是去执行一个长时间的已确定的任务则不需要。

3、在任何一个Cocoa程序的线程中,都可以通过以下代码获取当前线程的run loop

NSRunLoop *runloop = [NSRunLoop currentRunLoop];
阅读全文 »

Objective-C 中对 self 和 super 的理解

发表于 2020-03-23 | 分类于 iOS开发技巧

Objective-C 中对 self 和 super 的理解

@implementation Son
- (instancetype)init {
self = [super init];
if (self) {

    // 1、self 是类的隐藏参数,指向当前调用方法的这个类的实例
    // 2、super 是一个 Magic Keyword, 它本质是一个编译器标示符,和 self 是指向的同一个消息接受者
    // 3、当使用 self 调用方法时,会从当前类的方法列表中开始找,如果没有,就从父类中再找;而当使用 super 时,则从父类的方法列表中开始找。然后调用父类的这个方法
    NSLog(@"%@",NSStringFromClass([self class]));   // 输出 Son
    NSLog(@"%@",NSStringFromClass([super class]));  // 输出 Son
}
return self;
}

疑问点:父类中此时若使用点语法( self.lastName )也即 setter 设置方法,那么调用将会是子类的设置方法,为什么?

阅读全文 »

objc中向一个nil对象发送消息将会发生什么

发表于 2020-03-20 | 分类于 iOS开发技巧

objc中向一个nil对象发送消息将会发生什么

在 Objective-C 中向 nil 发送消息是完全有效的——只是在运行时不会有任何作用:

objc是动态语言,每个方法在运行时会被动态转为消息发送,即:objc_msgSend(receiver, selector)。

objc在向一个对象发送消息时,runtime库寻找对象的isa指针,然后会根据对象的isa指针找到该对象实际所属的类,然后在该类中的方法列表以及其父类方法列表中寻找方法运行,然后在发送消息的时候,objc_msgSend方法不会返回值,所谓的返回内容都是具体调用时执行的。 那么,回到本题,如果向一个nil对象发送消息,首先在寻找对象的isa指针时就是0地址返回了,所以不会出现任何错误。

阅读全文 »

一个objc对象如何进行内存布局

发表于 2020-03-19 | 分类于 iOS开发技巧

一个objc对象如何进行内存布局?(考虑有父类的情况)

所有的父类的成员变量和自己的成员变量都在该对象所对应的存储空间中。

每一个对象内部都有一个isa指针指向类对象,类对象存放本对象的以下内容

  1. 对象方法列表
  2. 成员变量列表
  3. 属性列表
  4. 每个类对象内部也有一个isa指针指向元对象(meta class),元对象内部存放 类方法列表
  5. superclass指针,指向对象的父类对象。
阅读全文 »

runtime消息转发机制

发表于 2020-03-18 | 分类于 iOS开发技巧

什么时候会报unrecognized selector的异常?

简单来说:

当调用该对象上某个方法,而该对象上没有实现这个方法的时候, 可以通过“消息转发”进行解决。简单的流程如下,

objc是动态语言,每个方法在运行时会被动态转为消息发送,即:objc_msgSend(receiver, selector)。
objc在向一个对象发送消息时,runtime库寻找对象的isa指针,然后根据对象的isa指针找到该对象实际所属的类,然后在该类中的方法列表以及其父类方法列表中寻找方法运行,如果,在最顶层的父类中依然找不到相应的方法时,程序在运行时会挂掉并抛出异常unrecognized selector sent to XXX 。但是在这之前,objc的运行时会给出三次拯救程序崩溃的机会:

阅读全文 »

synthesize和dynamic分别有什么作用?

发表于 2020-03-05 | 分类于 iOS开发技巧

@synthesize和@dynamic分别有什么作用?

  1. @property有两个对应的词,一个是 @synthesize,一个是 @dynamic。如果 @synthesize和 @dynamic都没写,那么默认的就是@syntheszie var = _var;
  2. @synthesize 的语义是如果你没有手动实现 setter 方法和 getter 方法,那么编译器会自动为你加上这两个方法
  3. @dynamic 告诉编译器:属性的 setter 与 getter 方法由用户自己实现,不自动生成。(当然对于 readonly 的属性只需提供 getter 即可)。假如一个属性被声明为 @dynamic var,然后你没有提供 @setter方法和 @getter 方法,编译的时候没问题,但是当程序运行到 instance.var = someVar,由于缺 setter 方法会导致程序崩溃;或者当运行到 someVar = var 时,由于缺 getter 方法同样会导致崩溃.
  4. 动态绑定:编译时没有问题,运行时才执行相应的方法。
阅读全文 »

property的本质

发表于 2019-12-30 | 分类于 iOS开发技巧

@property 的本质是什么

1、“属性” (property)作为 Objective-C 的一项特性,主要的作用就在于封装对象中的数据。“属性” (property)有两大概念:ivar(实例变量)、存取方法(access method = getter + setter)。

2、property在runtime中是objc_property_t定义:

typedef struct objc_property *objc_property_t;

阅读全文 »
123
王乾

王乾

在成为最厉害最厉害最厉害的道路上。

27 日志
4 分类
5 标签
RSS
GitHub E-Mail
© 2020 王乾