iOS编程基础-OC(六)-专家级技巧:使用ARC

2023-10-27

该系列文章系个人读书笔记及总结性内容,任何组织和个人不得转载进行商业活动!


     第6章 专家级技巧:使用ARC

     

     本章是第一部分的最后一章;

         本章介绍ARC内存管理中的细微之处;

         如直接桥接对象使用ARC的方法;

     

     6.1 ARC和对象所有权

     

     我们已经知道OC代码创建的对象存储在以动态方式分配的内存(堆内存)中;需要内存管理;

         确保将不再使用的对象从该内存区域中移除;

         确保不错误地移除仍在使用中的对象;

     

     OC通过引用计数模式实现内存管理,该模式通过计算对象的被引用数量判定对象是否在使用中;

     ARC通过在编译时,插入代码,使向对象发送的retain和release消息达到平衡,从而自动化该任务;

         ARC禁止程序员手动控制对象的生命周期;

         也不能通过发送retain和release消息控制对象的所有权;

     

     了解ARC内存管理中的对象所有权规则很重要;

     

     6.1.1 声明对象的所有权

     

     OC能够通过获得由名称以alloc new copy mutableCopy开头的方法创建的任何对象的所有权;

         A * a = [[A alloc] init];//这里使用alloc方法创建了A对象,也就声明了对象的所有权;

         在编写的代码中,如果使用copy消息创建块对象,也可以获得这类对象的所有权;

     

     注:

         块是指闭包的实现代码,这类函数允许访问它们作用范围之外的变量;后续会详细介绍;

     

     6.1.2 释放对象的所有权

     

     ARC禁止以手动方式向对象发送release、autorelease、dealloc或其他相关的消息;

     当你编写的代码执行下列操作时,会放弃对象的所有权:

         1)重新分配变量;

         2)将nil赋予变量;

         3)释放对象的所有者;

     

     1.重新分配变量:

         变量中指向以动态方式创建的对象更改为指向另一个对象,那么原来对象就会失去一个所有者;

         在编译时,ARC会插入向这个对象发送release消息的代码;此时如果该对象没有其他的所有者,那么它就会被释放;

     

     2.将nil赋予变量:

         如果是以动态的方式创建的对象的变量设置为nil,该对象也会失去一个所有者;

         ARC会在将变量设置为nil的语句后面,插入向这个对象发送release消息的代码;

     

     3.释放对象的所有者:

         释放对象的所有者既与对象的所有权有关;又与ARC管理对象(包括对象图和对象集)生命周期的方式有关;

     

     对象图:(Object graph)

         面向对象的程序由相互关联的对象网络组成;这些对象通过OOP继承或合成法连接到一起,统称为对象图;

     

     在对象图中,对象通过合成法规则引用其他(子)对象;

         如果某个(父)对象创建另一个(子)对象,那么这个父对象就声明了它拥有孩子对象的所有权;

         我们定义了C6OrderEntry类及C6OrderItem、C6Address类,通过对象图创建了一段程序;

(注:类实现代码附在文末,建议先浏览一下代码)

    C6OrderEntry * entry = [[C6OrderEntry alloc] initWithId:@"001" name:@"AD"];
    NSLog(@"OrderEntry:%@ \nOrderItem:%@ name:%@",entry.orderId,entry.item,entry.item.name);

      如上述代码所示:

          当程序创建并初始化了一个OrderEntry对象后,其初始化方法还会创建其他两个子类的实例;

          因此,这个OrderEntry对象会声明它拥有这些子对象的所有权;

          当程序释放OrderEntry对象时,ARC会自动向其子类对象发送release消息;

      

      值得注意的是:

          在编译时ARC还会为这个OrderEntry对象插入dealloc方法(没有的话);

          并为它的每个子类对象插入一条release消息;

          然后向OrderEntry对象的父类发送一条dealloc消息;

      

      上述代码的log如下:

      2017-11-17 15:30:09.834033+0800 精通Objective-C[36322:2311019] Initial orderEntry object with ID 001

      2017-11-17 15:30:09.834217+0800 精通Objective-C[36322:2311019] Initial OrderItem object AD

      2017-11-17 15:30:09.834369+0800 精通Objective-C[36322:2311019] OrderEntry:001

      OrderItem:<C6OrderItem: 0x60400000f790> name:AD

      2017-11-17 15:30:09.834463+0800 精通Objective-C[36322:2311019] Dealloc orderEntry object with ID 001

      2017-11-17 15:30:09.834546+0800 精通Objective-C[36322:2311019] Dealloc OrderItem object AD

      

      这样ARC就实现了对象图生命周期管理的自动化;

      

      Foundation框架中还有各种集合类,当一个对象存储在集合类的一个实例中时,该集合类会声明该对象的所有权;

          当这个集合类被释放时,ARC会自动向该集合类中的每个对象发送一条release消息;

      

      

     6.2 扩展订单条目工程

      

      (Code)

      类C6OrderEntry;

      类C6OrderItem;

      

      基于上述类测试声明对象所有权,以及释放对象所有权的几种方式,我们会发现:ARC以正确的方式管理了这些对象图的生命周期;

      

      我们来写一段程序测试一下:

  

 NSLog(@"Entering autoreleasepool block");
    @autoreleasepool{
        C6OrderEntry * entry1 = [[C6OrderEntry alloc] initWithId:@"A-1" name:@"Hot dog"];
        C6OrderEntry * entry2 = [[C6OrderEntry alloc] initWithId:@"A-2" name:@"Potato"];

        NSArray * entrys = [[NSArray alloc] initWithObjects:entry1,entry2, nil];
        NSLog(@"Setting entry2 to nil");
        entry2 = nil;
        NSLog(@"Setting entrys to nil");
        entrys = nil;
        NSLog(@"Setting entry1 to nil");
        entry1 = nil;
        
        NSLog(@"Leaving autoreleasepool block");
    }

       log:

       2017-11-17 16:43:10.115083+0800 精通Objective-C[36981:2402627] Entering autoreleasepool block

       2017-11-17 16:43:10.115430+0800 精通Objective-C[36981:2402627] Initial orderEntry object with ID A-1

       2017-11-17 16:43:10.115565+0800 精通Objective-C[36981:2402627] Initial OrderItem object Hot dog

       2017-11-17 16:43:10.115658+0800 精通Objective-C[36981:2402627] Initial orderEntry object with ID A-2

       2017-11-17 16:43:10.115736+0800 精通Objective-C[36981:2402627] Initial OrderItem object Potato

       2017-11-17 16:43:10.115820+0800 精通Objective-C[36981:2402627] Setting entry2 to nil

       2017-11-17 16:43:10.115905+0800 精通Objective-C[36981:2402627] Setting entrys to nil

       2017-11-17 16:43:10.116067+0800 精通Objective-C[36981:2402627] Dealloc orderEntry object with ID A-2

       2017-11-17 16:43:10.116966+0800 精通Objective-C[36981:2402627] Dealloc OrderItem object Potato

       2017-11-17 16:43:10.117205+0800 精通Objective-C[36981:2402627] Setting entry1 to nil

       2017-11-17 16:43:10.118076+0800 精通Objective-C[36981:2402627] Dealloc orderEntry object with ID A-1

       2017-11-17 16:43:10.118704+0800 精通Objective-C[36981:2402627] Dealloc OrderItem object Hot dog

       2017-11-17 16:43:10.118909+0800 精通Objective-C[36981:2402627] Leaving autoreleasepool block

  

  NSLog(@"Entering autoreleasepool block");
    @autoreleasepool{
        C6OrderEntry * entry3 = [[C6OrderEntry alloc] initWithId:@"A-3" name:@"Hot dogs"];
        printf("entry3 retain count = %ld\n",CFGetRetainCount((__bridge CFTypeRef)(entry3)));
        NSLog(@"%@",entry3.item.name);
        printf("entry3 retain count = %ld\n",CFGetRetainCount((__bridge CFTypeRef)(entry3)));

        C6OrderEntry * entry4 = [[C6OrderEntry alloc] initWithId:@"A-4" name:@"Potatos"];
        NSLog(@"%@",entry4.item.name);
        
        NSArray * entrys = [[NSArray alloc] initWithObjects:entry3,entry4, nil];
        NSLog(@"Setting entry3 to nil");
        entry3 = nil;
        NSLog(@"Setting entrys to nil");
        entrys = nil;
        NSLog(@"Setting entry4 to nil");
        entry4 = nil;
        
        NSLog(@"Leaving autoreleasepool block");
    }

    

     log:

     2017-11-17 16:48:27.110462+0800 精通Objective-C[37036:2409143] Entering autoreleasepool block

     2017-11-17 16:48:27.110675+0800 精通Objective-C[37036:2409143] Initial orderEntry object with ID A-3

     2017-11-17 16:48:27.110892+0800 精通Objective-C[37036:2409143] Initial OrderItem object Hot dogs

     entry3 retain count = 1

     2017-11-17 16:48:27.111098+0800 精通Objective-C[37036:2409143] Hot dogs

     entry3 retain count = 1

     2017-11-17 16:48:27.111325+0800 精通Objective-C[37036:2409143] Initial orderEntry object with ID A-4

     2017-11-17 16:48:27.112664+0800 精通Objective-C[37036:2409143] Initial OrderItem object Potatos

     2017-11-17 16:48:27.112762+0800 精通Objective-C[37036:2409143] Potatos

     2017-11-17 16:48:27.112848+0800 精通Objective-C[37036:2409143] Setting entry3 to nil

     2017-11-17 16:48:27.112929+0800 精通Objective-C[37036:2409143] Setting entrys to nil

     2017-11-17 16:48:27.113455+0800 精通Objective-C[37036:2409143] Dealloc orderEntry object with ID A-3

     2017-11-17 16:48:27.114057+0800 精通Objective-C[37036:2409143] Dealloc OrderItem object Hot dogs

     2017-11-17 16:48:27.115738+0800 精通Objective-C[37036:2409143] Setting entry4 to nil

     2017-11-17 16:48:27.115833+0800 精通Objective-C[37036:2409143] Dealloc orderEntry object with ID A-4

     2017-11-17 16:48:27.115927+0800 精通Objective-C[37036:2409143] Dealloc OrderItem object Potatos

     2017-11-17 16:48:27.116019+0800 精通Objective-C[37036:2409143] Leaving autoreleasepool block


     

     我们实现了两段代码:区别在于后一种的orderItem对象通过entry对象的属性读取器进行了获取;

         当前所学书籍中描述:通过属性读取器读取之后,ARC会自动插入向对象发送retain和autorelease消息的代码,从而避免对象被过早的释放;以此描述,OrderItem对象将在自动释放池末尾被释放;

         但如上我们所做的测试,在进行对象属性读取前后,OrderItem的引用计数并为发生变化,这个可能是ARC在后续版本中进行了修改;关键的是我们理解了ARC为管理对象内存所做的事;

     

       

     6.3 将ARC与苹果公司提供的框架和服务一同使用

     

     苹果公司提供的常用框架和服务:

         应用框架:AppKit、UIKit;

         应用服务:音频&视频、图形&动画、数据管理、网络&因特网、用户应用、次级框架;

         核心服务:启动服务、Carbon Core、Core Foundation、Foundation;

     

     这些软件库,有些是用OC编写的,因而可以直接使用;而大多数软件库的API是使用ANSC C编写的,要在OC程序中直接使用,还需要做一些事;

         ARC能够自动管理OC对象和块对象的内存,苹果提供的基于C语言的API软件库没有与ARC整合;

         因此,当你通过动态的方式为这些基于C语言的API分配内存时,必须手动管理内存;

     

     实际上,ARC不允许在OC对象指针和其他数据类型指针(苹果提供的基于C的API中的)之间进行直接转换;

         为了方便在OC中使用基于C语言的API,苹果提供了多种机制,如 桥接 和 ARC桥接转换;

     

     我们来分别看一下这两种机制;

     

     

     6.4 OC直接桥接

     

     Core Foundation框架是基于C语言的;

     Foundation是基于OC的;

     两者之中的许多数据类型之间苹果为之提供了互通性——这种功能成为“直接桥接”(toll free bridging);

         通过直接桥接你可以在Core Foundation函数中调用和OC消息的接收器中使用数据类型相同的参数;

         你可以通过将一种数据类型转换为另一种数据类型,防止编译器报警;

     

     以下是一些较为常用的直接桥接数据类型,其中包括Core Foundation数据类型和对应的Foundation框架数据类型;

         Core Foundation数据类型                     Foundation框架数据类型

         CFArrayRef                                  NSArray

         CFDataRef                                   NSData

         CFDateRef                                   NSDate

         CFDictionaryRef                             NSDictionary

         CFMutableArrayRef                           NSMutableArray

         CFMutableDataRef                            NSMutableData

         CFMutableDictionaryRef                      NSMutableDictionary

         CFMutableSetRef                             NSMutableSet

         CFMutableStringRef                          NSMutableString

         CFNumberRef                                 BSNumber

         CFReadStreamRef                             NSInputStream

         CFSetRef                                    NSSet

         CFStringReg                                 NSString

         CFWriteStreamRef                            NSOutputStream


     通过直接桥接,编译器能够将数据在Core Foundation和Foundation框架之间进行转换;

         示例:

    CFStringRef cstr = CFStringCreateWithCString(nil, "Hello Flower!", kCFStringEncodingASCII);
    NSArray * array = [NSArray arrayWithObject:(__bridge id _Nonnull)(cstr)];
    NSArray * array1 = [NSArray arrayWithObject:(__bridge NSString *)(cstr)];

    NSLog(@"array:%@",array);
    NSLog(@"array1:%@",array1);


     这里的__bridge稍后会介绍,先看其他的;

     我们初始化数组的方法需要一个OC对象指针,我们传入的是直接桥接的CFStringRef数据类型,所以参数会被隐式装换为NSString对象;当然你也可以显示转换;

     

     通过上一节,我们已经知道:

         OC编译器不会自动管理Core Foundation框架数据类型对象的生命周期;

         因此,要在使用ARC的OC程序中,使用Core Foundation框架直接桥接数据类型,就必须手动管理这些对象的内存;

         这也是上边ARC环境下出现__bridge的原因;

     

     在编写使用ARC的OC程序时,必须设置直接桥接数据是由ARC管理内存还是手动管理内存;

         通过ARC桥接转换可以做到这一点;

     

     我们先简单介绍一下ARC桥接转换:

         在使用ARC时,通过ARC桥接转换 可以使用 直接桥接数据类型;

         这些操作必须使用一些特殊标记作为前缀:

             __bridge、__bridge_retained和__bridge_transfer;

     

     __bridge:

         使用__bridge标记 可以在不改变所有权的情况下,将对象从Core Foundation框架数据类型转换为Foundation框架数据类型(反之亦然);

         1)ARC下,Foundation框架对象,通过直接桥接将它的数据类型转换为Core Foundation框架下的;此时,

             通过__bridge标记可以使编译器知道这个对象的生命周期仍旧由ARC管理;

         2)Core Foundation框架对象,直接桥接为Foundation框架的数据类型;此时,

             通过__bridge标记可以告诉编译器这个对象的生命周期仍旧是以手动方式管理的(不是ARC);

         注意:使用该标记可以使编译器不报错,但是不会改变对象的所有权,因此在使用它解决内存泄漏和悬挂指针问题时应多加小心;

 

     __bridge_retained:

         使用__bridge_retained标记可以将Foundation框架数据类型对象 转换为Core Foundation框架数据类型对象;

         并从ARC接管对象所有权;这样你就可以手动管理直接桥接数据的生命周期;

     

     __bridge_transfer:

         使用__bridge_transfer标记可以将Core Foundation框架数据类型对象 转换为Foundation框架数据类型对象;

         并且会将对象的所有权交给ARC管理;这样会由ARC管理对象的声明周期;

     

     使用桥接转换标记的语法:

         (桥接转换标记 目的数据类型)变量名

     

     了解了ARC桥接转换的三中标记的含义,相信可以看出之前示例代码中的问题了,在下一节我们详细分析下,我们修改之后的代码如下:   

    CFStringRef cstr1 = CFStringCreateWithCString(nil, "Hello Flower!", kCFStringEncodingASCII);
     NSArray * array3 = [NSArray arrayWithObject:(__bridge_transfer NSString *)(cstr1)];

     这里__bridge_transfer标记会将桥接对象的所有权交给ARC,这样该对象的生命周期就会由ARC管理;

      

      了解了概念之后,让我们来看看ARC桥接转换的用法;

      

      

     6.5 使用ARC桥接转换

      

      示例1:

      还是上边的代码示例(使用__bridge标记的那一段);

      我们使用Analyze选项分析该程序,就会发现变量cstr中存在潜在的内存泄漏问题;


      (Pic1)

      

      出现这个问题的原因是使用__bridge标记无法改变直接桥接对象的所有权,因此,必须手动管理变量cstr的生命周期;

          这段代码创建了该CFStringRef对象,所以他拥有这个以动态方式创建的对象,并且可以向该对象发送release消息;

          例如:CFRelease(cstr);

      

      这是一种解决方式;

      

      更好的选择:使用__bridge_transfer才是更好的选择;(上一节中__bridge_transfer标记的那一段)

          这样就不会再检查到内存泄漏了;

      

      示例2:

   NSNumber * counting = [[NSNumber alloc]initWithFloat:5];
    CFNumberRef cscounting = (__bridge CFNumberRef)counting;
    CFShow(cscounting);
    NSLog(@"greeting:%@",counting);

    

     这段代码编译是没有问题的,但存在潜在的悬挂指针问题;

         因为在执行桥接转换时,ARC会立即向NSNumber对象发送一个release消息;

         解决这个问题,可以这样修改代码;

 

   NSNumber * counting1 = [[NSNumber alloc]initWithFloat:5];
    CFNumberRef cscounting1 = (__bridge_retained CFNumberRef)counting1;
    CFShow(cscounting1);
    CFRelease(cscounting1);

    

     使用__bridge_retained标记可以从ARC接管该对象,从而避免ARC向该对象发送release消息;

     亦因此,你必须手动管理这个对象的生命周期;

         现在已经转换为CFStringRef类型;

         在使用结束之后调用CFRelease方法;

     

     可以看到:

     __bridge:并不能修改对象所有权,之前是手动管理/ARC的,使用它标记之后,仍然需要手动管理/ARC;

     __bridge_retained:可以修改对象所有权,而且不是简单的修改,而是接管,适用于手动管理从ARC的接管对象所有权;

     __bridge_transfer:也可以修改对象所有权,而且不是简单的修改,而是将所有权交给ARC,适用于手动管理交给ARC对象所有权;

     

     

     6.6 小结

     

     本章深入研究了ARC内存管理方式;ARC也是苹果推荐的内存管理方式;

     

     要点:

     1)ARC禁止通过手动方式,向对象发送release、autorelease、dealloc消息,以及与对象有关的其他消息;

         当执行下列操作的时候,程序会放弃对象的所有权:

             a.重新分配变量;-编译时,ARC会插入向该对象发送一条release消息的代码;

             b.将nil赋予变量;-编译时,ARC会插入向该对象发送一条release消息的代码;

             c.释放对象的拥有者;-使用集合类实例时会出现释放所有者的情况,集合类实例被释放时,ARC会自动向该集合中的每一个对象发送一条release消息;

     2)苹果公司提供的基于C语言的API软件库没有与ARC整合,因此,当您在程序中以动态的方式为这些API分配内存时,必须手动管理内存;

     3)ARC禁止在OC对象指针和其他类型指针之间进行标准转换;为此提供了相应的机制:直接桥接 和 ARC桥接转换;

         以方便在OC中使用基于C的API;

     4)Core Foundation和Foundation框架中有很多非常有用的直接桥接数据类型,从而使你编写的程序 能够在调用Core Foundation框架和 接收OC消息时 使用相同的数据类型;

         数据类型转换可以消除编译器警告;但在ARC下,无法直接转换 直接桥接的数据类型,而必须使用特殊的ARC桥接转换标记才能进行转换;

     

     注:直接桥接 桥接的是数据类型;

         ARC桥接转换 转换的是对象所有权;

     

     5)通过ARC桥接装换,可以使用ARC的同时,使用直接桥接数据类型;这些转换操作以特殊的转换标记开始(__bridge、__bridge_retained、__bridge_transfer);


     到本章为止,OC基础知识就介绍完了,接下来我们开始介绍OC运行时系统;

     

代码实现:

C6OrderEntry


#import <Foundation/Foundation.h>

#import "C6OrderItem.h"
#import "C6Address.h"

@interface C6OrderEntry : NSObject{
    C6Address * shippingAddress;
}

@property (readonly) NSString * orderId;
@property (readonly) C6OrderItem * item;

-(id)initWithId:(NSString *)oid name:(NSString *)order;

@end


#import "C6OrderEntry.h"

@implementation C6OrderEntry

-(id)initWithId:(NSString *)oid name:(NSString *)order{
    if (self = [super init]) {
        NSLog(@"Initial orderEntry object with ID %@",oid);

        _orderId = oid;
        shippingAddress = [[C6Address alloc] init];
        _item = [[C6OrderItem alloc]initWithName:order];
    }
    return self;
}
-(void)dealloc{
    NSLog(@"Dealloc orderEntry object with ID %@",self.orderId);
}
@end

C6OrderItem

#import <Foundation/Foundation.h>

@interface C6OrderItem : NSObject

@property (readonly) NSString * name;

-(id)initWithName:(NSString *)itemName;

@end

#import "C6OrderItem.h"

@implementation C6OrderItem
-(id)initWithName:(NSString *)itemName{
    if (self = [super init]) {
        NSLog(@"Initial OrderItem object %@",itemName);
        _name = itemName;//对于自动补全属性来说,实例变量的标准命名约定为在属性名称中加下划线前缀
    }
    return self;
}
-(void)dealloc{
    NSLog(@"Dealloc OrderItem object %@",self.name);
}

@end

C6Address





本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

iOS编程基础-OC(六)-专家级技巧:使用ARC 的相关文章

  • 如何在 Swift 编程中获得基于导航的模板功能

    我的项目需要一个导航控制器 并且我的应用程序最初有一个社交登录 一旦验证通过 用户将被推送到另一个视图 我在其中显示一个具有 2 个选项卡的选项卡控制器 我不知道如何在 Swift 编程中做到这一点 我已将视图控制器嵌入到导航控制器中 一旦
  • Xcode 4 Core Data:如何使用在数据模型编辑器中创建的获取属性

    如何在 Xcode 4 中实现获取的属性 Here is an example of two entities a book and a page 我按照此处的指南创建了一个获取的属性 该属性使用变量 FETCH SOURCE 引用来自源实
  • 我可以对图像进行动画处理吗 iOS8 LaunchScreen.xib

    问题 有没有方法可以为针对 iOS 8 1 部署的 Xcode 6 项目的 LaunchScreen xib 文件中的任何内容设置动画 Context 我正在寻找制作简单的动画来传达活动或在用户等待时分散他们的注意力 例子 加载栏 活动指示
  • 从 iOS 中的 App Delegate 调用当前视图控制器中的方法

    我有两个视图控制器 BuildingsViewController 和 RoomsViewController 它们都使用应用程序委托中名为上传的函数 上传函数基本上执行一个 HTTP 请求 如果成功或不成功 都会触发 uialertvie
  • Swift - 停止 avaudioplayer

    我正在尝试将音板构建到应用程序中 并找到了一种使用标签来控制播放声音的有效方法 不过 我现在正在尝试集成一个可以与 stop 方法上的AVAudioPlayer但是我当前的代码出现错误 EXC BAD ACCESS 这就是我现在正在使用的
  • UITextInputMode currentInputMode 已弃用。建议更换?

    在我们的应用程序中 我们想检测当前的键盘语言 例如 如果用户在 设置 gt 常规 gt 键盘 gt 键盘 下设置了多种语言键盘 我们想知道他们正在输入什么语言 并在发生变化时从 NSNotificationCenter 收到通知 void
  • 如何在pop UIViewController中删除UIParallaxDimmingView?

    我有一个UIViewController vc1这是在之后推送的UIViewController vc2 Both vc1 and vc2具有透明背景 问题 当我尝试弹出时vc2使用交互式弹出手势 从边缘平移 在我看来堆栈显得很神秘UIPa
  • 手动设置时间和日期时,iOS 10 中的重复每日本地通知不会被触发?

    我正在尝试通过触发每日通知来测试 iOS 10 中的本地通知 我正在使用以下示例项目 通知UI 演示 https github com appcoda NotificationsUI Demo 该应用程序中有以下代码之一 let calen
  • 应用程序更新后 PFUser currentUser nil

    我已经在 App Store 中更新了我的 iOS 应用程序 对于安装更新的用户来说似乎存在一个错误 他们的PFUser currentUser正在返回nil 知道为什么会发生这种情况吗 要添加信息 我在我的应用程序中使用此代码启用自动用户
  • “Firebase Storage”,用于图像 - 但是,获取实际的 URL?

    正在将图像发送到 Firebase Storage 系统 sr a StorageReference ie FIRStorageReference let task sr putData data task observe success
  • 在 Swift 中将 gif 保存到 iOS 照片库

    我正在尝试保存位于已使用 Regift 代码创建的临时文件中的 GIF 图像 Regift https github com matthewpalmer Regift https github com matthewpalmer Regif
  • 从 iPhone 设备查找当前国家/地区

    我必须在 iPhone 设置中获取当前国家 地区 谁能告诉我如何在 iPhone 应用程序中获取当前国家 地区 我必须使用当前国家 地区来解析需要传递当前国家 地区的 RSS 提要 请帮我找到那个国家 提前致谢 要查找用户选择的语言所在的国
  • 在 iOS 上不显示数字键盘

    根据苹果的文档 http developer apple com library safari documentation AppleApplications Reference SafariHTMLRef Articles InputTy
  • 具有自签名证书的 Alamofire / ServerTrustPolicy

    我想使用 Alamofire 通过带有自签名证书的 https 连接与我的服务器进行通信 我的环境在本地主机上运行 我尝试连接 但响应始终如下所示 Success false Response String nil 我用下面的代码完成了它
  • 使用 iOS swift AVPlayer 在横向模式下不全屏

    我将视频视图设置为全屏 然而 在模拟器中玩时 它并没有全屏运行 此问题仅适用于 iPad 不适用于 iPhone 这是我的代码 override func viewDidAppear animated Bool super viewDidA
  • 自定义 OpenVPN iOS 客户端 [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我正在开发一个自定义 iOS OpenVPN 客户端 我找到了这个原生 OpenVPN 客户端核心源码https staging op
  • 启动使用 Simperium 的应用程序时 objectFromJSONString 崩溃

    我得到了一个JSON当我尝试启动使用 Simperium 框架的应用程序时崩溃 NSCFString objectFromJSONString unrecognized selector sent to instance 0x6c561a0
  • 如何快速从解析中加载图像?

    我想知道是否有人可以帮助我 我是应用程序开发的新手 我正在从我的应用程序上传图像以在解析文档的帮助下毫无问题地进行解析 let imageData UIImagePNGRepresentation scaledImage let image
  • 了解 React Native 中的默认字体大小

    在过去的几个月里 我一直在开发一个 React Native 应用程序 但有些事情总是让我困惑 而我现在正试图弄清楚它的真相 我正在尝试标准化应用程序中的字体大小 正文 标题等 并且正在努力了解 React Native 究竟从哪里获取默认
  • 使用 Metal 高效计算 UIImage/CIImage 中有多少透明像素

    我们可以计算有多少个透明像素的最快方法是什么CIImage UIImage 例如 如果我们谈论效率 我的第一个想法是使用Metal Kernel使用任一CIColorKernel左右 但我不明白如何使用它来输出 计数 我还有其他想法 使用某

随机推荐

  • 英特尔® 硬件加速执行管理器安装指南 — Microsoft Windows*

    介绍 本文将指导您安装英特尔 硬件加速执行管理器 英特尔 HAXM 这是一款可以使用英特尔 虚拟化技术 VT 加快 Android 开发速度的硬件辅助虚拟化引擎 管理程序 前提条件 英特尔 HAXM 要求首先安装 Android SDK 版
  • 几行代码搞定Android底部导航栏

    底部导航栏的实现也不难 就是下边是几个Tab切换 上边一般是一个FrameLayout 然后FrameLayout中切换fragment 网上有不少关于Android底部导航栏的文章 不过好像都只是关于下边Tab切的 没有实现Tab与fra
  • Hexo搭建博客教程-基于Butterfly主题

    title Hexo搭建博客教程 tags Hexo 博客教程 categories Hexo keywords Hexo 博客教程 description Hexo搭建博客 以及主题butterfly中一些常规配置 cover https
  • sqlite3交叉编译

    1 交叉编译sqllite3可以先从官网下载最新最新的源码进行编译 sqlite3下载sqlite3有两种版本的源代码 sqlite amalgamation 3420000 zip这种是将所有的操作放到sqlite3中进行使用的 虽然官方
  • synchronized 的原理

    文章目录 前言 通过一系列的问题 了解synchronized 总结 前言 synchronized 是一个关键字 在多线程中 为了同步代码块 或者同步方法就会使用到 在面试的过程中 也是非常常见的 所以很有必要掌握 通过一系列的问题 了解
  • 题5:字符串的压缩

    题目 利用字符重复出现的次数 编写一个方法 实现基本的字符串压缩功能 比如 字符串 aabcccccaaa 经压缩会变成 a2b1c5a3 若压缩后的字符串没有变短 则返回原先的字符串 给定一个string iniString为待压缩的串
  • Pymol入门教程--基础

    Pymol入门教程 基础 软件界面介绍 内置demo介绍 打开PyMOL 点击1 1菜单窗口的Wizard菜单 然后点击Demo gt Representations然后在2 3对象窗口和2 4模式窗口之间会出现各种示例 Represent
  • Docker-Compose的安装

    一 什么是Docker Compose Compose项目来源于之前的fig项目 使用python语言编写 与docker swarm配合度很高 Compose 是 Docker 容器进行编排的工具 定义和运行多容器的应用 可以一条命令启动
  • IDEA插件安装以及一些不错的插件的推荐

    IDEA有自己庞大的插件支持 来丰富生态 现在一个好用点的工具如果没有点插件都不好意思 当然了 微信除外 因为人家会告你 一 插件的安装 IDEA的插件安装和别的IDE工具 比如eclipse或者vscode的位置都差不多 还是具体说一下
  • TensorFlow二元-多类-多标签分类示例

    探索不同类型的分类模型 使用 TensorFlow 构建二元 多类和多标签分类器 二元分类 简述 逻辑回归 二元交叉熵 二元分类架构 案例 逻辑回归预测获胜团队 多类分类 简述 Softmax 函数 分类交叉熵 多类分类架构 案例 预测航天
  • Jenkins CI、CD入门操作

    基于Jenkins拉取GitLab指定发行版本的SpringBoot代码进行构建发布到生产环境实现CD实现持续部署 准备测试项目 准备一个简单的Spring boot 项目 Jenkins新建任务 Jenkins关联Gitlab自动拉取最新
  • 如果一个人真的懂你

    一辈子 遇见一个真正读懂你的人 真的很难 人的一生中会遇到几十甚至上百万个人 其中能和你打招呼 称得上是朋友的人就更少 而在这么多人当中 却很有可能连一个真正懂你的人都没有 有些人 就算相识再久 也无法成为知己 有些人 即使你说了千句 他都
  • 基于错误信息的SQL盲注

    何谓盲注 在SQL注入基础一文中介绍了SQL注入的基本原理 可以轻易注入的原因是知道SQL拼接代码是怎么写的 很多情况下 很难甚至无法知道对方的SQL拼接语句是怎么写的 这里情况下需要做尝试 分析代码是采用何种拼接结构 然后再写个万能注入公
  • python docx 表格样式的设置修改表格列宽

    我的需求是设置表格的列宽和高度 之前的代码使用网上找的方法 table cell y x width Cm 4 无论怎么修改都是无效的 最后正确的代码是 col table columns 1 col width Inches 5
  • 修改mt4服务器地址,修改mt4服务器地址

    修改mt4服务器地址 内容精选 换一换 云平台支持修改主网卡的私有IP地址 具体操作请参见本节内容 如需修改扩展网卡的私有IP地址 请删除网卡 并挂载新网卡 云服务器已关机 如果网卡绑定了虚拟IP或者DNAT规则 需要先解绑 如果网卡上有I
  • [译] APT分析报告:03.OpBlueRaven揭露APT组织Fin7/Carbanak(上)Tirion恶意软件

    这是作者新开的一个专栏 主要翻译国外知名的安全厂商APT报告文章 了解它们的安全技术 学习它们溯源APT组织的方法 希望对您有所帮助 前文分享了钓鱼邮件网址混淆URL逃避检测 这篇文章将介绍APT组织Fin7 Carbanak的Tirion
  • 什么浏览器好用稳定速度快?

    什么浏览器好用稳定速度快 说到浏览器 不知道你们是否有这样的困惑和烦恼 浏览器换了一款又一款 内存大就不说了 体验总是不尽人意 经常弹出一些莫名其妙的资讯 还会出现卡住 奔溃 网页打开不完全 打开速度慢等情况 就拿我最近用的两款360来说吧
  • Nginx+lua实现秒杀系统架构

    能今天做好的事就不要等到明天 以梦为马 学习趁年华 文章目录 前言 一 秒杀业务特点 1 瞬时高并发 2 热点数据 3 读多写少 二 技术难点 1 数据一致性 2 库存超卖 三 秒杀注意事项 1 数据预热 2 请求承载 3 请求拦截 四 微
  • 重新理解Linux交叉编译及编译流程

    参考书籍 1 编译原理 2 嵌入式Linux应用开发 文章目录 一 交叉编译背景 二 gcc和arm linux gcc的常用选项 1 查询gcc帮助 2 常用gcc选项介绍 3 生成一个可执行文件的三种方法 二 交叉编译的四个流程及实例说
  • iOS编程基础-OC(六)-专家级技巧:使用ARC

    该系列文章系个人读书笔记及总结性内容 任何组织和个人不得转载进行商业活动 第6章 专家级技巧 使用ARC 本章是第一部分的最后一章 本章介绍ARC内存管理中的细微之处 如直接桥接对象使用ARC的方法 6 1 ARC和对象所有权 我们已经知道