【iOS】内存管理

2023-11-10


前言

内存管理:
在Objective-C这样的面向对象的语言里,内存管理是很重要的概念。理解了内存管理模型的种种细节之后,Objective-C的内存管理就没有那么复杂了。尤其是有了“自动引用计数(ARC)”之后,更为简单。ARC几乎把所有的内存管理事宜都交给了编译器处理,开发者只需注重业务逻辑。


提示:以下是本篇文章正文内容,下面案例可供参考

理解引用计数

Objective-C使用引用计数来管理内存。每个对象都有可以递增或递减的计数器。
如果要使某个对象存活,递增其引用计数。用完之后,递减其计数,计数变为0的时候,就没人关注此对象了,销毁它。

引用计数原理

在引用计数架构下,对象有一个计数器,用以表示当前有多少个事物想令此对象继续存活下去。这在Objectiv-C中叫做“保留计数”,也可以叫“引用计数”。

Retain 递增保留计数
release 递减保留计数
autorelease 待稍后清理“自动释放池”时,再递减保留计数。
  • 查看保留计数的方法叫做retainCount,此方法不太有用。
  • 对象创造出来时,引用计数至少为1.若想令其继续存活,则调用retain方法。要是某部分代码不在使用此对象,不想令其继续存活,就调用release或者autorelease方法。当保留计数归零时,对象就回收(deallocated)了,系统会将占用的内存标记为“可重用”。此时,所有指向该对象的引用也都变得无效了。
    请添加图片描述
  • 应用程序在其生命周期中会创建很多对象,这些对象都相互联系着。相互关联的对象就构成了一张“对象图”。对象如果持有指向其他对象的强引用,那么前者就“拥有”后者。也就是说,对象向令其所引用的那些对象继续存活,就可以将其“保留”。等用完之后,在做释放。请添加图片描述
  • 在图示中,ObjectB和ObjectC都引用了ObjectA。若ObjectB和ObjectC都不在使用ObjectA,则其保留计数降为0,此时可以摧毁ObjectA。如果还有其他对戏那个想令ObjectB和ObjectC继续存活,而应用程序里又有另外一些对象想令那些对象继续存活。如果按“引用计数”回溯,那么最终会发现一个“根对象”。在Mac OS X应用程序中,此对象就是NSAppliction对象。而在iOS应用程序中,是UIApplication对象。两者都是应用程序启动时创建的单例。
  • 如果代码中直接调用release方法,ARC下就无法编译。在Objective-C中,调用alloc方法所返回的对象由调用者所拥有。也就是说,调用者已经通过alloc方法表达了想令该对象继续存活下去的意愿。此时保留计数至少为1。保留计数绝不一定是某个值,只能说执行的操作是递增了还是递减了该计数
  • 如果调用release方法之后,基于某些原因,其保留计数降为0,此时对象所占内存可能会回收。这样的话,在调用NSLog kennel就会使程序崩溃。对象所占的内存在“解除分配”后,只是放回“可用内存池”,如果执行NSLog时还未覆写对象内存,那么该对象仍然有效,此时程序不会崩溃。因过早释放对象所导致的bug很难查找
  • 为避免使用无效对象,一般调用完release之后都会清空指针。就可以保证不会出现指向无效对象的指针,这种指针通常称为“悬挂指针”。

属性存取方法中的内存管理

  • 对象图由互相关联的对象构成,树枝通过在其元素上调用retain方法来保留那些对象。其他对戏那个也可以保留别的对象,一般通过属性来实现。访问属性时,会调用相关实例变量的获取方法及设置方法。若属性为“strong”关系,则设置的属性值会保留。
 - (void)setFoo:(id)foo{
    [foo retain];
    [_foo release];
    _foo = foo;
}
  • 此方法会保留新值并释放旧值,然后更新实例变量,令其指向新值。顺序很重要,假如还未保留新值就先把旧值释放了,而且两个值又指向同一个对象,那么先执行的release操作就可能导致系统将此对象永久回收。而后的retain操作无法令已经彻底回收的对象复生,于是实例变量就变成了悬挂指针。

自动释放池

调用release方法会立即递减保留计数(还有可能让系统回收此对象)。如果改用autorelease,此方法会稍后递减计数,通常是在下一次“事件循环”时递减,也可能更早一些。

 - (NSString*)stringValue {
    NSString* str = [[NSString alloc] initWithFormat:@"I am this :%@", self];
    return str;
}
  • 这个方法返回的str对象的保留计数比预期值多1。因为调用alloc方法会令保留计数加1,没有与之对应的释放操作。需要想办法如何将多出来的这个一次保留抵消掉。
  • 不能在方法内释放str,否则还没等方法返回,系统就把对象回收了。这里应该使用autorelease,他会在稍后释放对象。从而给调用者留下足够长的时间,使其可以在需要时先保留返回值。此方法可以保证对象在跨越“方法调用边界”后一定存活。释放操作会在清空最外层的自动释放池时执行,除非有自己的释放池,否则这个时机就是当前线程的下一次事件循环。
 - (NSString*)stringValue {
    NSString* str = [[NSString alloc] initWithFormat:@"I am this :%@", self];
    return [str autorelease];
}
  • 此时,此对象必然存活。由于返回的str对象将与稍后自动释放,无需再执行内存管理操作。因为自动释放池中的释放操作要等到下一次事件循环时才会执行。NSLog中使用str对象前就不需要手工执行保留操作。如果要持有此对象,那就需要保留,并于稍后释放。

保留环

保留环是值呈现环状的相互引用的多个对象。他容易导致内存泄漏。因为循环中的对象的保留计数不会降为0.对于每个循环中的每个对象来说,至少还有另一个对象引用着它。

请添加图片描述

  • 图示即为保留环,在垃圾收集系统下,所有的对象的引用计数至少为1。在垃圾收集系统中,通常将这种情况认定为“孤岛”。此时,垃圾收集器会把三个对象全部回收走。在Objective-C的引用计数中,通常采用“弱引用”来解决问题,或是从外界命令循环中的某个对象不在保留另一个对象。这两种方法都能打破保留环,从而避免内存泄漏。

以ARC简化引用计数

需要执行保存和释放操作的地方很容易就能看出来。Clang编译器自带一个“静态分析器”,用于指明程序里引用计数出问题的地方。

if ([self shouleLogMessage]) {
    NSString* message = [[NSString alloc] initWithFormat: @"I am object, %p", self ];
    NSLog (@"message = %@". message);
}
  • 此代码存在内存泄漏问题。因为if语句末尾并未释放message对象。而在if语句之外又无法调用message对象,此时message对象所占的内存就泄漏了。如果调用NSString的alloc方法所返回的message对象的保留计数比期望值多1,内存泄漏。
  • “静态分析器”要做的事就是套用判断内存是否泄漏的规则,分析出内存泄漏问题的对象。
  • 自动引用计数这一思路是“静态分析器根据需要,预先加入适当的保留或者释放操作以避免一些问题。”自动引用计数所做的事情与其名称相符,就是自动管理引用计数。
  • 使用ARC时一定要记住,引用计数实际上还是执行的,只不过保留和释放操作现在是由ARC自动添加。除了为方法所返回的对象正确运用内存管理语义之外,ARC还有更多的功能。
  • ==ARC会自动执行retain,release。autorelease,delloc等操作。在ARC下调用这些内存管理方法都是非法的。==直接调用这些方法都会产生编译错误,ARC要分析何处应该自动调用内存管理方法,所以如果手动调用,会干扰其工作。
  • 在ARC调用这些方法时,不通过OC的消息派发机制,而是直接调用底层C语言版本。这样做性能更好。

使用ARC时必须遵守的命名规则

  • 将内存管理语义在方法名中表示出来早已成为OC的管理,ARC将它确立为硬性规定。这些规则简单的体现在方法名上,如果方法名以下列词语开头,则其返回的对象归调用者所有。如:alloc,new,copy,mutableCopy。
  • 归调用者所有的意思是:调用上述四种方法的代码要负责释放方法所返回的对象。也就是说,这些对象的保留计数是正值,而调用了这四种方法的那段代码要将其中一次保留的操作抵消掉。如果还有其他对象保留此对象,并对其调用了autorelease,那么其保留计数的值可能比1大。
  • 若方法名不以上述四个词语开头,则其返回的对象并不归调用者所有。在这种情况下,返回的对象会自动释放,其值在跨越方法时调用边界后依然有效。如果想让对象多存活一段时间,必须令调用者保留它才行。
  • ARC通过命名约定内存管理规则标准化。除了会自动调用“保留”与“释放”之外,使用ARC可以执行一些手工操作很难甚至无法完成的优化。ARC也包含运行期组件,此时执行的优化很有意义。在ARC环境下编译代码时,必须考虑“向后兼容性”,以兼容那些不适应ARC的代码。
  • ARC可以在运行期检测到这一对多余的操作,也就是autorelease及紧跟其后的retain。为了优化代码,在方法中返回自动释放的对象时,要执行一个特殊函数。此时不直接调用对象的autorelease方法,而是改用objc_autoreleaseReturnValue。此函数会检视当前方法返回之后即将要执行的那段代码。如果发现那段代码要在返回的对象上执行retain操作,则设置全局数据结构中的一个标志位,而不执行autorelease操作。与之相似,如果方法返回了一个自动释放的对象,而调用方法的代码要保留此对象,那么此时不直接执行retain,而改为执行objc_retainAutoreleaseedReturnValue函数。此函数要检测刚才提到的标志位,如果已经置位,则不执行retain操作。并设置检测标志位,要比autorelease和retain快
  • 将内存管理交由编译器和运行期组件来做,,可以使代码得到多种优化。

变量的内存管理语义

  • ARC也会处理局部变量和实例变量的内存管理。默认情况下,每个变量都是指向对象的强引用。
  • ARC会用一种安全的方法来设置:先保留新值,再释放旧值,最后设置实例变量。在应用程序中,可以用下列修饰符来改变局部变量和实例变量的语义。
_ _strong: 默认语义,保留其值
_ _unsafe_unretained: 不保留此值,这么做不太安全,因为等到再次使用变量时,变量有可能已经被回收了
__weak: 不保留此值,但是变量可以安全使用,因为如果系统把这个对象回收了,那么变量也会自动清空
__autoreleasing: 把对象“按引用传递”给方法时,使用这个特殊的修饰符,此值在方法返回时自动释放。

请添加图片描述

  • 不论采用哪种写法,在设置实例变量时都不会保留其值。只有在使用新版运行期程序库时,加了_weak修饰的weak引用才会自动清空。
  • 我们经常给局部变量加上修饰符,用以打破由“块”所引入的“保留环”。块会自动保留其所捕获的对象,而如果其中有某个对象又保留了块本身,就可能导致“保留环”。可以使用_weak局部变量来打破这种“保留环”

ARC如何清理实例变量

要管理内存,ARC就必须在“回收分配给对象的内存”时生成必要的清理代码。凡是具备强引用的变量,都必须释放,ARC会在dealloc方法中插入这些代码。

  • 用了ARC后,就不要编写[obj dealloc]这样的方法了。因为ARC会借用Objective-C++的一项特性来生成清理例程。回收Objective-C++对象时,待回收的对象就会调用所有C++对象的析构函数。编译器如果发现某个对象里含有C++对象,就会生成名为.cxx_destruct的方法。
  • 如果有非Objective-C的对象,仍需要清理内存。

覆写内存管理的方法

不使用ARC时,可以覆写内存管理方法。在实现单里类的时候,因为单例不可释放,所以我们经常覆写release方法。将其替换为“空操作”。但在ARC环境下不能这样做,因为会干扰到ARC分析对象生命周期的工作。

在dealloc方法中只释放应用并解除监听

对象在经历其生命周期后,最终会被系统回收。此时要执行dealloc方法。在每个对象的生命期内,此方法仅执行一次,也就是当保留计数降为0时。

  • 我们应该在dealloc方法中释放对象所拥有的引用,也就是把所有的Objective-C对象都释放掉,ARC会通过自动生成的.cxx_destruct方法,在dealloc中为你自动添加这些释放代码。对象所拥有的其他非Objective-C的对象也要释放。
  • 在dealloc方法中,我们通常还要把原来配置过的观测行为都清理掉。如果给对象发送某种通知,一般都应该在此处注销通知。
  • 如果手动管理引用计数不使用ARC,那么最后还要调用[super dealloc]。ARC会自动执行此操作,这再次表明其比手动管理更简单,更安全。若选择手动管理,还要将当前对象所拥有的全部Objective-C对象逐个释放。
  • 开销较大或系统内存稀缺的资源不在dealloc中释放引用。比如文件描述符,套接字,大块内存等,都属于这种资源。不能依赖dealloc方法必定会在某个特定的时机调用,因为有一些无法预料的对象可能也持有此对象。在这种情况下,如果我们一定要等到系统调用dealloc方法的时候才释放,那么保留这些稀缺资源的时间就过长了,这么做不合适。通常的做法是:实现另外一个方法,当应用程序用完资源对象后,就调用此方法。
  • 在清理方法而非dealloc方法中清理资源是因为系统不能保证每个创建出来的dealloc都会执行。极个别情况下,当应用程序终止时,仍有对象处于存活状态,这些对象没有收到dealloc消息。当应用程序终止后,其占用的资源也会返回给操作系统,所以实际上这些对象也就等于是消亡了。不调用dealloc方法是为了优化程序效率。这也说明了系统未必会在每个对象上调用dealloc方法。
  • 如果对象管理着某些资源,那么在dealloc中也要调用“清理方法”,以防止开发者忘了清理这些资源。有时可能不想只输出一条错误消息,而是要抛出异常来表明不调用某个方法是严重的错误
  • 编写dealloc方法时还应该注意,不要在其中随便调用其他方法。如果调用了其他方法,那么等到那些人物执行完毕的时候,系统研究把当前这个待回收的对象彻底摧毁了。经常导致应用程序崩溃,因为那些任务执行完毕后,要回调此对象,告诉该对象任务已经完成,而此时如果对象已经摧毁,回调操作就会出错。
  • 调用dealloc方法里的那个线程会执行“最终的释放操作”,令对象的保留计数为0。但是某些方法必须在特定的线程里调用才行。若在dealloc里调用了那些方法,无法保证当前这个线程就是那些方法所需要的线程。
  • 在dealloc方法里也不要调用属性的存取方法,因为有人可能会覆写这些方法,并于其中做一些无法在回收阶段安全执行的操作。属性可能正处于“键值观测”机制的监控之下,该属性的观察者可能会在属性值改变时“保留”或使用这个歌即将回收的对象,这种做法会令运行期系统状态完全失调,从而导致一些莫名其妙的错误。

编写“异常安全代码”时留意内存管理问题

Objective-C和C++支持“异常”这一特性。在当前的运行期系统里,C++和Objective-C的异常相互兼容,也就是说,从其中一门语言里抛出的异常能用另外一门语言所编写的“异常处理程序”来捕获。

  • Objective-C的错误模型表明,异常应该在发生严重错误后抛出。但是有时仍然需要编写代码捕获并处理异常。当使用Objective-C++编码时,或者编码中使用到了第三方程序库而此程序库所抛出的异常又不受你控制时,就需要捕获及处理异常了。有些系统库也会用到异常。
  • ARC能生成安全处理异常的附加代码。-fobjc-are-exceptions这个编译标志用来开启此功能。但是默认情况下不开启这个功能。因为在OC中,只用当应用程序必须因异常状况而终止时才应该抛出异常。因此,如果应用程序即将终止,那么是否还会发生内存泄漏就已经无关紧要里。在应用程序必须立即终止的情况下,还去添加安全处理异常所用的附加代码时没有意义的。
  • 当处于Objective-C++模式时,编译器会自动把-fobjc-arc-exceptions标志打开。
  • 如果手动管理引用计数,而且必须捕获异常,那么要设法保证所编代码能把对象正确清理干净。若使用ARC切必须捕获异常,打开编译器的-fobjc-arc-exceptions标志

以弱引用避免保留环

几个对象都以某种方式相互引用,形成“环”。这种情况会泄漏内存,因为最后没有别的东西引用环中的对象。环里的东西无法为外界所访问,但是对象之间尚有引用,这些引用使他们继续存活下去,不被系统回收。

  • 最简单的保留环是两个对象互相引用。请添加图片描述
  • 把classA的一个属性设置成ClassB的类的实例,把ClassB的一个属性设置成ClassA的一个实例,就会出现保留环。请添加图片描述
  • 保留环会导致内存泄漏。如果只剩一个引用还指向保留环中的实例,而现在又把这个引用移除,那么整个保留环都泄漏了。也就是说,没办法在继续访问其中对象了。
  • 避免保留环的方式就是弱引用。弱引用经常表示“非拥有关系”。将属性声明称为unsafe_unretained。这个词表示,属性可能不安全,而且不归此实例所拥有。如果系统已经把属性所指的那个对象回收了,那么在其上调用方法可能会使应用程序崩溃。由于此对象不保留属性对象,因此极有可能为系统所回收。
  • unsafe_unretained修饰的属性特性,语义和assign特质等价。assign用于“整型类型”(int,float,结构体等),unsafe_unretained多用于对象类型。这个词本身表明其修饰的属性可能无法安全使用。
  • OC中还有一项和ARC相伴的运行期特性,可以令开发者安全使用弱引用。weak属性特质。它与unsafe_unretained的作用完全相同。然而只要系统把属性回收,属性值就会自动设为nil。请添加图片描述
  • 当指向ClassA的实例引用移除后,unsafe_unretained属性仍然指向那个已经回收的实例,weak指向nil。
  • 使用weak比unsafe_unretained更安全。应用程序可能现实错误的数据,不会直接崩溃。==只要在所指对象已经彻底崩溃后还继续使用弱引用,那它就依然是一个bug。
  • 一般来说,如果不再拥有某对象,那就不要保留它。collection除外,collection虽然不直接拥有其内容,但是他要代表自己所属的那个对象来保留这些元素。
  • weak引用可以自动清空,也可以不自动清空。自动清空是随着ARC而引入的新特性,有运行期系统来实现。在具备自动清空的弱引用上,可以随意读取数据,这种引用不会指向已经回收过的对象。

以“自动释放池块”降低内存峰值

Objective-C对象的生命周期取决于引用计数。释放对象有两种方式:一种是调用realse方法,使其保留计数立即递减。另一种是调用autorelease方法,将其加入“自动释放池”。自动释放池用于存放那些需要在稍后某个时刻释放的对象。清空(drain)自动释放池时,系统会自动向其中的对象发送realse消息。

  • 如果没有创建自动释放池,向对象发送autorelease消息,控制台会输出一条信息。一般情况下不用担心自动释放池的创建问题。系统会自动创建一些线程,这些线程默认有自动释放池。
  • 每次执行“事件循环”时,就会将其清空。不需要自己创建“自动释放池”。通常只有在main函数里需要创建自动释放池。
  • main函数的末尾恰好就是应用程序的终止处,此时操作系统会把程序所占的全部内存都释放掉。自动释放池于左花括号处创建,右花括号处自动清空。位于自动释放池内的对象,在此范围末尾处收到realse消息。
  • 内存峰值是指应用程序在某个特定的时间段内的最大内存用量。
  • 自动释放池就像“栈”用于,系统创建好自动释放池后,就将其推入栈中,而清空自动释放池,相当于将其从栈中弹出。在对象上执行自动释放操作,就相当于将其放入栈顶的那个池里。
  • 是否应该使用池来优化效率,取决于具体的应用程序。首先得监控内存用量,判断其中有没有需要解决的问题。进了不要额外的建立自动释放池。
  • 还有一种写法,使用NSAutoreleasePool对象。它专门用来表示自动释放池,就像新语法中的自动释放池块一样。这种写法不会在每次for循环时都清空池,此对象更为“重量级”,通常用来创建那种偶尔需要清空的池。
  • @autoreleasepool还有一个好处,每个自动释放池均有其范围,可以避免无意间误用了那些清空池后已经 被系统回收的对象。

用“僵尸对象”调试内存管理问题

  • 业内向以回收的对象发送消息是不安全的,这么做有时可以,有时不行。能否这样做取决于对象所占内存也没有为其他内容所覆写。这块内存也没有另作它用又无法确定,因此,程序只是偶尔崩溃。在没有崩溃时,那块内存可能只是复用了其中一部分,所以对象中的某些二进制数据依然有效。还可能是那块内存恰好为另外一个有效且存活的对象占据。这个时候,运行期系统会把消息发到新对象那里,而此对象也许能回答,也许不能。如果能,程序就不会崩溃。
  • 启用调试功能后,运行期系统会把所有的已经回收的实例转化成特殊的“僵尸对象”,而不会真正回收他们。这种对象的核心内存无法复用,所以不可能覆写。僵尸对象收到消息后,会抛出异常,其中准确说明了发送过来的消息,并描述了回收之前的那个对象。僵尸对象是调试内存管理问题的最佳方式。将NSZombieEnabled环境变量设置为YES,就可以开启这个功能
  • 僵尸对象的实现代码深植于Objective-C的运行期程序库,Foundation框架及CoreFoundation框架中。系统在相爱即将回收对象时,如果发现通过环江变量启用了僵尸对象功能,那么还将指向一个附加步骤。这一步就是把对象转化为僵尸对象,不在彻底回收。
  • 僵尸类是从名为_NSZombie的模板类里复制出来的。这些僵尸类没有多少事情可以做,只是充当一个标记。
  • 给僵尸对象发送消息后,系统可以由此知道该类对象所属的原来的类。加入吧所以僵尸对象都归到_NSZombie类里,那原来的类名就丢失了。僵尸类没有超类,是一个“根类”,只有一个实例变量,叫做isa,所有OC得根类都必须有此变量。由于这个轻量级的类没有实现任何方法,所以发送给他的全部信息都要经过“完整的消息转发机制”。

不要使用retainCount

  • 方法:“-(NSUInteger)retainCount”不能在ARC种调用。
  • 保留计数的绝对值数值一般都于开发者所应留意的事情完全无关。即便只在调试时才调用此方法,通常也没有什么用。
  • 这个方法返回的保留计数只是某个给定时间的上的值。该方法并未开绿道系统会稍后把自动释放池清空,因而不会将后续的释放操作从返回值里减去。这样的话,就未必能真实反映实际的保留计数了。
  • 对象的保留计数看似有用,实则不然,因为任何给定时间的上的“绝对保留计数”(abusolute retain count)都无法反应对象生命周期的全貌。
  • 在引入ARC之后,苹果公司已经废弃了retainCount,所以绝对不要使用这个方法。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【iOS】内存管理 的相关文章

  • 当前图像选择模式会擦除 UI

    我下面有一个非常简单的视图控制器 UI 实际上只是一个带有底部标签栏的按钮 import UIKit class ImageAdderViewController UIViewController override func viewDid
  • 我可以在 Swift 3 项目中使用 Swift 2.3 框架吗?

    在我的项目中 我将所有私有 swift 2 3 文件迁移到 swift 3 我想使用用 swift 2 3 编写的遗留框架 直到它们有 swift 3 版本 我尝试添加 使用旧版 Swift 版本 是 清除 构建我的项目 但我仍然遇到一些麻
  • 未安装 Apple 的全球开发者关系 (WWDR) 中间证书

    我今天无法通过 Appcelerator Titanium 发布我的应用程序 AdHoc 我开始收到此错误 错误 未安装 Apple 的全球开发者关系 WWDR 中间证书 错误 这将阻止您为 iOS 设备构建应用程序或用于分发的软件包 我上
  • 如何让 Chrome Cast 在 iOS 后台运行?

    我有一个简单的问题 当您进入 iPhone 的主屏幕并且不退出应用程序时 chrome Cast 设备会停止在屏幕上播放视频 当应用程序在后台运行时 我如何才能保持播放状态 如果您有一个视频应用程序并且它在投射设备中运行 您可能需要以下行为
  • iOS SecItemCopyMatching RSA 公钥格式?

    我正在尝试从已生成的密钥对 两个SecKeyRefs 以便通过线路发送 我所需要的只是一个简单的 modulus exponent 对 它应该正好占用 131 个字节 模数为 128 指数为 3 但是 当我获取关键信息时NSData对象 我
  • Draggable Boxview 不更新 Xamarin

    我的第一个问题是框视图生成在左上角 而不是我指定的设计网格第 10 行和网格第 3 列 第二个问题在于可拖动视图 在代码本地可拖动视图的第一部分中 它正确地调用了触摸事件 但也许它没有在GUI中更新
  • 从 iOS 设备向 Google App Engine 进行身份验证

    我正在开发一个 iPhone 应用程序 它使用 Google 应用程序引擎来托管后端 我需要通过 Google 进行身份验证 但我似乎无法找到从我的应用程序中执行此操作的方法 看来我要做一个UIWebView让用户登录到我从 Google
  • SKScene和SKView的paused属性之间的区别

    我使用以下代码暂停 SKScene self paused YES 然而 根据这个answer https stackoverflow com a 21593852 2043580 by 安德烈 戈尔杰耶夫 https stackoverf
  • 在 UITableViewCell 内动态更改标签宽度

    我正在尝试建立一个自定义表格视图 正如您在图片中看到的 我在故事板一侧将标签的宽度默认设置为 160 磅 并在加载表格时动态更改宽度 我通过修改 cellForRowAtIndexPath 委托方法来实现此目的 因此 根据日期的长度 我设置
  • 添加 AFNetworking 后出现 APPLE MACH-O 链接错误

    只是将 AFNetworking 添加到我的项目中 在 B R 后 我收到如下错误 Undefined symbols for architecture i386 SecCertificateCopyData referenced from
  • Objective C 宏附加到字符串

    我认为这是一件非常简单的事情 但由于我是 iOS 开发和 Objective C 的新手 所以我无法弄清楚 define RESTFUL PATH PREFIX https gogch com gch restful define LOGI
  • 在两个可移动 uiview 之间画线

    我有一个带有节点的 滚动视图 UIViews 可以拖动 我正在尝试在选定的之间绘制边缘UIViews使用 calayer 但我不知道当视图位置发生变化时如何重新绘制线条 In my viewControllerI 类在节点数组中添加第一个和
  • 使用什么来移动 UIView self.frame 或 self.transform 属性?

    这个问题我有点困惑 我知道我可以改变观点self frame origin 但我发现有一个名为 变换 的属性 我认为这是用于在屏幕上移动我的视图等 也许我有点不明白 所以我想知道 我必须使用哪个房产来搬家UIView 或者它的子类 另一个类
  • 增量后清除推送通知徽章

    我正在研究 iPhone 中的推送通知 当我收到推送通知时 它在我的应用程序图标上显示 1 下次显示 2 3 4 如果我打开应用程序 它是 0 下次它应该是 1 2 3 4 但它显示最后一个数字和 1 我想在打开应用程序后重置推送通知徽章
  • UIView 周围的虚线边框

    如何在周围添加虚线边框UIView 像这样的东西 如果您喜欢子层 还有另一种方法 在您的自定义视图的 init 中 输入以下内容 border 是 ivar border CAShapeLayer layer border strokeCo
  • 使用 UIWebView 显示 PDF 不起作用

    因此 我意识到有关使用 UIWebView 在应用程序 在 iPad 上 中显示 PDF 存在很多问题 我已经审查了我能找到的所有内容 但似乎找不到任何满意的东西 我想做的事情非常基本 所以我真的不知道为什么它不起作用 我需要做的就是在 U
  • iOS Twitter NSURLErrorDomain 代码=-1012

    我正在尝试通过在我的应用程序中注册 Twitter 来获取用户的联系方式 我发现this https github com malcommac DMTwitterOAuthgithub上的项目看起来非常好 我只遇到一个问题 如果我使用来自
  • 如何将NSTextView的格式化内容转换为字符串

    我需要将 NSTextView 的内容从 Mac 应用程序传输到 iOS 应用程序 我使用 XML 作为传输文件格式 所以我需要将 NSTextView 的内容 文本 字体 颜色等 保存为字符串 有什么办法可以做到这一点吗 一种方法是存档
  • 如何删除以前的 ViewController

    我是一名学生 对编程还很陌生 我正在尝试在业余时间学习 Objective C Swift 我使用 spriteKit 和 swift 制作了一个游戏 有多个菜单 场景 我正在尝试从一个视图控制器转换到另一个视图控制器 为此 我使用了以下代
  • GCD 与自定义队列

    我想知道这两者的性能有什么区别 dispatch async dispatch get global queue DISPATCH QUEUE PRIORITY HIGH 0 perform complex operation dispat

随机推荐

  • 人工智能机器人是什么编程

    人工智能机器人是什么编程 说起孩子的学习一直都是家长们非常关心和重视的一件事情 家长会给孩子选择一些能够有利于孩子成长的课程 就拿现在很多的家长想要孩子去学习机器人编程的课来说 有的家长对于人工智能机器人是什么编程并不是很清楚 今天我们就一
  • java pointer_Java EE 8 JSON Pointer讲解

    Java EE 8包含JSON处理API的更新 并为最新的JSON标准提供最新的IEFT标准 他们是 JSON Pointer RFC 6901 JSON Patch RFC 6902 JSON Merge Patch RFC 7396 入
  • TCP中 滑动窗口RWND 和 拥塞窗口 CWND的区别

    滑动窗口RWND 和 拥塞窗口 CWND的区别 参考文章 What is CWND and RWND 文章如有错误 希望指正 共同学习 RWND Receiver Window 滑动窗口 滑动窗口技术是TCP的流量控制的核心 存在于TCP的
  • shell的字符串和数字的转化(数字自动做字符串处理,变量名做字符串输出用单引号)

    shell里面怎么样把字符串转换为数字 例如 a 024 1 用 a 2 用let达到 运算效果 let num 0123 echo num 83 3 双括号运算符 a 1 2 echo a 等同于 a expr 1 2 而数字会默认做字符
  • mfc 服务器文件拷贝到本地,mfc服务器客户端间传输文件

    mfc服务器客户端间传输文件 内容精选 换一换 要访问您的文件系统 如果是Linux云服务器 您需要在Linux云服务器上安装NFS客户端后使用挂载命令挂载文件系统 如果是Windows云服务器 您需要在Windows云服务器上安装NFS客
  • 设计模式二三事

    设计模式是众多软件开发人员经过长时间的试错和应用总结出来的 解决特定问题的一系列方案 现行的部分教材在介绍设计模式时 有些会因为案例脱离实际应用场景而令人费解 有些又会因为场景简单而显得有些小题大做 本文会结合在美团金融服务平台设计开发时的
  • 为什么连接HBase报错:Will not attempt to authenticate using SASL (unknown error)?

    问题现象 访问CloudTable的HBase连接不上 出现如下所示的错误信息 Opening socket connection to server 192 168 0 107 192 168 0 107 2181 Will not at
  • Java-主流框架—(1)Spring--IoC

    1 Spring介绍 1 1什么是框架 软件工程框架 经过验证的 具有一定功能的 半成品软件 经过验证 具有一定功能 半成品 1 2框架的作用 1 3Spring是什么 Spring是分层的JavaSE EE应用full stack轻量级开
  • 泛型应用

    region 私有方法
  • flask 框架

    Flask本身只是建立了一个Web框架 很多功能都需要在Flask基础上进行扩展 如果是高手 可以手打一个Flask Extension 普通人可以用已经开源扩展进行二次开发 用过的几个Flask的扩展库 目前为止Flask Securit
  • 【C++】Windows系统&Linux系统获取uuid统一通用代码

    ConsoleApplication1 cpp 定义控制台应用程序的入口点 include stdafx h include
  • Qt进程间通信

    简述 进程间通信 就是在不同进程之间传播或交换信息 通信方式 管道 pipe 管道是一种半双工的通信方式 数据只能单向流动 而且只能在具有亲缘关系的进程间使用 进程的亲缘关系通常是指父子进程关系 有名管道 named pipe 有名管道也是
  • java中访问修饰符的权限

    在java中 最常见的访问修饰符有以下四个 public default 默认 即不写修饰符 protected private 它们主要用来规定所修饰成员的开放程度 用来保护成员不被随意调用和修改 在新建一个类时 只能用public和de
  • 【区块链】深度长文:2018新风口,区块链3.0时代即将来临?

    徐小平说 区块链将掀起一场革命 1月9日 徐小平在真格投资组合群里分享了一段关于拥抱区块链时代的内容 并表示不能外传 被泄露的微信截图 岂料 很快去传了出去 他表示 这本是其与被投公司间的 低调 内容分享 现在被人擅自传出去 也没办法 最后
  • Express基本认识

    express是一个基于nodejs 且快速 开放的一个web开发框架 安装命令 yarn add express 查看express的所有版本 npm view express versions 搭建基本的express程序 const
  • ./configure --prefix=

    一直用这个选项prefix 但不知道 啥意思 转载自 inux安装软件采用源码安装灵活自由 适用于不同的平台 维护也十分方便 源码的安装一般由3个步骤组成 配置 configure 编译 make 安装 make install 具体的安装
  • centos7设置开机为命令行启动

    图形界面默认安装之后 每次启动都是图形界面启动 图形界面需要占用系统大量的内存和CPU资源 对于个人电脑和服务器 将Centos 默认启动改为文本方式 会显著提高运行效率 方法一 不修改默认启动方式 root模式下 init 3 gt 切换
  • sqlserver查看执行计划

    方式一 通过Microsoft sql server management studio工具栏中的 显示估计的执行计划 按钮 选中SQL 然后点击该按钮 SQL就会给我们选中SQL的图形执行计划 方式二 set showplan all o
  • 【无监督学习】0、有监督学习、无监督学习、半监督学习

    文章目录 一 有监督学习 二 半监督学习 三 无监督学习 3 1 对比式学习 一 有监督学习 有监督学习最大的特点就是数据集是带标签的 如有监督分类任务 就是给每张图都分配一个真实标签 表示这张图是 dog cat 或者是 bird 而标签
  • 【iOS】内存管理

    文章目录 前言 理解引用计数 引用计数原理 属性存取方法中的内存管理 自动释放池 保留环 以ARC简化引用计数 使用ARC时必须遵守的命名规则 变量的内存管理语义 ARC如何清理实例变量 覆写内存管理的方法 在dealloc方法中只释放应用