iOS强制使用系统键盘

1
//强制使用系统键盘
2
- (BOOL)application:(UIApplication *)application shouldAllowExtensionPointIdentifier:(NSString *)extensionPointIdentifier {
3
        if ([extensionPointIdentifier isEqualToString:@"com.apple.keyboard-service"]) {
4
                return NO;
5
          }
6
      return YES;
7
}

移动端开源项目-iOS


项目 公司 项目简介 项目地址
DoraemonKit 滴滴出行 滴滴开发的一款功能齐全的客户端(iOS、Android)研发助手 https://gitee.com/didiopensource/DoraemonKit
DynamicCocoa 滴滴出行 滴滴 App 架构组自研的 iOS 动态化方案,可以让现有的 Objective-C 代码转换生成中间代码(JS),下发后动态执行 https://github.com/DynamicCocoa/DynamicCocoa
NMessenger eBay 是一个快速,轻量级的信息组件,在 AsyncDisplaykit 上构建并用 Swift 编写。开发人员可以固定地实现 60FPS 滚动和具有丰富内容组件的平滑过渡。 https://github.com/eBay/NMessenger
SparkChamber eBay 是一个用于 iOS 的轻量级异步触发动作框架,旨在用于自动化分析、跟踪和日志记录。 https://github.com/eBay/SparkChamber
SVNetworking eBay 一个 iOS 上用于加载远程资源的开发包,使用 key-value 观察方式进行设计。 https://github.com/eBay/SVNetworking
EBNObservable eBay 实现了一个可观察的 Key-Value 集合,基于 Block 方式实现。 https://github.com/eBay/EBNObservable
BugHunt-iOS Esty 是一个嵌入式模块,允许你简单的制作 Bug 报告,发送测试用例给你的用户,并且跟踪每个用户的 bug 报告 https://github.com/etsy/BugHunt-iOS
Sonar(flipper) Facebook Sonar 是一个用于调试 iOS 和 Android 移动应用的平台,通过一个简单的界面,开发者可以可视化地审查和控制其 APP,除了可以直接使用,Sonar 还支持使用插件 API 进行扩展。 https://github.com/facebook/flipper
FBMemoryProfiler Facebook FBMemoryProfiler是Facebook开源的一款用于分析iOS内存使用和检测循环引用的工具库。 https://github.com/facebook/FBMemoryProfiler
fishhook Facebook fishhook 是一个非常简单的库,它允许支持在 iOS 上的模拟器和设备运行Mach-O,并提供动态绑定服务。此功能类似在OS X 系统上使用的 DYLD_INTERPOSE 功能。你可以通过使用 fishhook 实现呼叫/跟踪功能(如:auditing for double-close issues with file descriptors)。 https://github.com/facebook/fishhook
clang-as-ios-dylib Facebook 是一个从 Xcode 中建立 iOS 动态库 的方法。它可以直接在 Xcode 中建立 iOS 动态库(iOS dylibs),而不需要在安装 Xcode 时候进行修改。使用起来很方便 https://github.com/facebookarchive/clang-as-ios-dylib
FBFetchedResultsController Facebook FBFetchedResultsController 是 NSFetchedResultsController 的嵌入式替代品,它能在 NSFetchedResultsController 无法工作的父/子目录下工作 https://github.com/facebookarchive/FBFetchedResultsController
Chisel Facebook Chisel 是一个 LLDB 指令集合,用户辅助 iOS 应用查错 https://github.com/facebook/chisel
ComponentKit Facebook 一个受 React 启发的 iOS 视图框架,它带来一个构建 UI 声明的方法 https://componentkit.org
React Native Facebook ReactNative 可以基于目前大热的开源JavaScript库React.js来开发iOS和Android原生App。而且React Native已经用于生产环境——Facebook Groups iOS 应用就是基于它开发的。 http://www.reactnative.com
Pop Facebook Facebook 推出的一个可扩展的 iOS 和 OS X 动画框架 https://github.com/facebook/pop
Tweaks Facebook Facebook 发布的一款 iOS 应用测试工具。这款应用框架允许iOS开发者在该应用上进行测试并做实时更改,让微调更加便捷,开发者无需改变代码即可尝试多种选项。 https://github.com/facebook/Tweaks
KVOController Facebook Key-value 的监控是一个 MVC 应用中非常有用的技术。KVOController (来自 facebook)构建了一个基于 Cocoa 的 time-tested key-value 监控实现,提供简单方便、线程安全的 API。 https://github.com/facebook/KVOController
GeoFire for iOS Firebase GeoFire 是一个开源的用来存储和查询定位信息的库,简化了使用字符串键来存储位置信息。这些查询是实时的。 https://github.com/firebase/geofire-objc
FLAnimatedImage Flipboard FLAnimatedImage 是 iOS 的一个渲染 Gif 动画的引擎 https://github.com/Flipboard/FLAnimatedImage
FLEX Flipboard FLEX (Flipboard Explorer) 是 iOS 开发的应用内调试和探测工具集。运行的时候,FLEX 提供一个浮动在应用之上的工具栏,用户可以查看和修改应用的每一个地方。 https://github.com/Flipboard/FLEX
Archimedes github 是Cocoa和 Cocoa Touch 的几何函数 https://github.com/github/Archimedes
GTXiLib Google GTXiLib 是 Google 开源的 iOS 专用自动化测试框架,用于帮助开发者打造无障碍 App 。 https://github.com/google/GTXiLib
EarlGrey Google iOS UI 测试自动化框架 https://github.com/google/EarlGrey
Flutter Google Flutter 是一种新型的方式,用于创建高性能、跨平台的移动应用。由 Google 的工程师团队打造。Flutter 针对当下以及未来的移动设备进行优化,专注于 Android and iOS 低延迟的输入和高帧率。 https://flutter.dev
LayoutKit Linkedin LayoutKit 是一个高性能的iOS应用视图布局库。 https://github.com/linkedin/LayoutKit
Selene Linkedin Selene 是一个 iOS 库,用于在后台调度任务的执行。 https://github.com/linkedin/Selene
LIExposeController Linkedin LIExposeController是一个新的iOS应用程序的导航模式 https://github.com/linkedin/LIExposeController
WinObjC Microsoft WinObjC 是 Windows 开源的 Winodws 到 iOS 的“桥梁”。Windows Bridge for iOS (WinObjC) 为 Visual Studio/Windows 提供一个 Objective-C 开发环境。此外,WinObjC 提供对 iOS API 兼容的支持。 https://github.com/Microsoft/WinObjC
voice-web Mozilla 开源语音识别采集库.这是一个 Web,Android 和 iOS 应用程序 https://voice.mozilla.org/zh-CN
PINRemoteImage Pinterest PINRemoteImage 是一个快速无死锁的 iOS 并行图像下载和缓存库。 https://github.com/pinterest/PINRemoteImage
PivotalCoreKit Pivotal PivotalCoreKit 是 iOS 项目的常见开发包。它能够让你的应用程序看起来更加的漂亮,且不需要你在项目中重新编写相同的代码。它有几个不同的功能。但最主要的功能是能够帮助开发者们在 iOS 应用程序中测试驱动。 https://github.com/pivotal-legacy/PivotalCoreKit
Cedar Pivotal Cedar 是 Objective-C 上 BDD 风格的单元测试框架 https://github.com/cedarbdd/cedar
MMKV 腾讯 MMKV 是基于 mmap 内存映射的 key-value 组件,底层序列化/反序列化使用 protobuf 实现,性能高,稳定性强。 https://github.com/Tencent/MMKV
GT 腾讯 GT(随身调)是 APP 的随身调试平台,它是直接运行在手机上的“集成调试环境”(IDTE, Integrated Debug Environment)。 https://github.com/Tencent/GT
LKImageKit 腾讯 LKImageKit 是腾讯开源的一个高性能的图片框架,包括了图片控件,图片下载、内存缓存、磁盘缓存、图片解码、图片处理等一系列能力。合理的架构和线程模型,并特别针对不同场景进行优化,能充分发挥硬件的性能。 https://github.com/Tencent/LKImageKit
OOMDetector 腾讯 OOMDetector 是腾讯开源的一个 iOS 内存监控组件,应用此组件可以帮助你轻松实现 OOM 监控、大内存分配监控、内存泄漏检测等功能。 https://github.com/Tencent/OOMDetector
MLeaksFinder 腾讯 MLeaksFinder 是腾讯开源的 iOS 平台的自动内存泄漏检测工具,引进 MLeaksFinder 后,就可以在日常的开发,调试业务逻辑的过程中自动地发现并警告内存泄漏。 https://github.com/Tencent/MLeaksFinder
Appecker 腾讯 Appecker 是一款专门为 iOS 系统系统定制的的自动化测试框架。 https://github.com/TencentOpen/Appecker
WCDB 腾讯 WCDB 是腾讯开源的一个高效、完整、易用的移动数据库框架,基于SQLCipher,支持 iOS、macOS 和 Android。 https://github.com/Tencent/wcdb
Mars 腾讯 Mars 是微信官方的终端基础组件,是一个使用 C++ 编写的业务性无关、平台性无关的基础组件。目前已接入微信 Android、iOS、Mac、Windows、WP 等客户端。 https://github.com/Tencent/mars
QT4i 腾讯 iOS 开发自动化测试工具 https://github.com/Tencent/QT4i
CocoaSPDY Twitter CocoaSPDY 是 Twitter 推出的为 iOS 和 OS X 开发的 SPDY 开发包。 https://github.com/twitter/CocoaSPDY
TwUI Twitter TwUI 是一个支持硬件加速的 Mac 的 UI 框架 https://github.com/github/twui
RIBs Uber RIBs 是 Router、Interactor 和 Builder 的简称,是 Uber 许多移动端应用背后的跨平台架构。 https://github.com/uber/RIBs
YMCache Yahoo YMCache 是 iOS 和 Mac OS X 的轻量级对象缓存解决方案, 设计用于高度并行访问场景。 https://github.com/yahoo/YMCache

iPhone x searchBar编辑状态黑线处理


我在适配iPhone x的时候,我修改了searchBar的背景颜色后,在编辑状态总是出现一条黑线
image.png

未处理背景色的时候代码:

1
//设置搜索框
2
 UISearchBar *searchBar = _searchController.searchBar;
3
 // 设置搜索框外部的颜色
4
 searchBar.backgroundImage = [UIImage imageWithColor:AB_White_Color size:searchBar.frame.size];
5
 // 处理搜索框编辑状态时的背景色
6
 CGSize size = CGSizeMake(searchBar.frame.size.width, searchBar.frame.size.height + 20);
7
  [searchBar setBackgroundImage:[UIImage imageWithColor:AB_White_Color size:size] forBarPosition:UIBarPositionTopAttached barMetrics:UIBarMetricsDefault];
8
9
 searchBar.showsCancelButton = NO;
10
 [searchBar sizeToFit];
11
 searchBar.placeholder = NSLocalizedString(@"public.search", nil);
12
 searchBar.delegate = self;
13
 searchBar.barTintColor = [UIColor whiteColor]; //调整iPhone x上背景颜色的改变

经测试后,将UIBarMetricsDefault修改为UIBarMetricsDefaultPrompt即可

其他机型上还是使用UIBarMetricsDefault

解决黑线问题

1
UIBarMetrics barMetrics = UIBarMetricsDefault;
2
if (IPHONE_X) {
3
    barMetrics = UIBarMetricsDefaultPrompt;
4
}
5
[searchBar setBackgroundImage:[UIImage imageWithColor:AB_White_Color size:size] forBarPosition:UIBarPositionTopAttached barMetrics:barMetrics];

效果图:
image.png

textView中字符串处理


1.获取textView中每行的字符串
相关代码如下:

1
- (NSArray *)getLinesArrayOfStringInLabel:(UITextView *)textView {
2
    NSString *text = [textView text];
3
    UIFont *font = [textView font];
4
    CGRect rect = [textView bounds];
5
6
    CTFontRef myFont = CTFontCreateWithName((__bridge CFStringRef)([font fontName]), [font pointSize], NULL);
7
    NSMutableAttributedString *attStr = [[NSMutableAttributedString alloc] initWithString:text];
8
    [attStr addAttribute:(NSString *)kCTFontAttributeName value:(__bridge id)myFont range:NSMakeRange(0, attStr.length)];
9
    CTFramesetterRef frameSetter = CTFramesetterCreateWithAttributedString((__bridge CFAttributedStringRef)attStr);
10
    CGMutablePathRef path = CGPathCreateMutable();
11
    CGPathAddRect(path, NULL, CGRectMake(0,0,rect.size.width,100000));
12
    CTFrameRef frame = CTFramesetterCreateFrame(frameSetter, CFRangeMake(0, 0), path, NULL);
13
    NSArray *lines = (__bridge NSArray *)CTFrameGetLines(frame);
14
    NSMutableArray *linesArray = [[NSMutableArray alloc]init];
15
    for (id line in lines) {
16
        CTLineRef lineRef = (__bridge CTLineRef )line;
17
        CFRange lineRange = CTLineGetStringRange(lineRef);
18
        NSRange range = NSMakeRange(lineRange.location, lineRange.length);
19
        NSString *lineString = [text substringWithRange:range];
20
        [linesArray addObject:lineString];
21
    }
22
    return (NSArray *)linesArray;
23
}

2.按照2个英文字符作为一个字,一个中文汉字作为一个字的方式,计算字符串的实际长度
实现NSString的分类,在分类中添加方法代码:

1
//得到中英文字符串长度
2
- (NSInteger)convertToNumbers {
3
        NSInteger strlength = 0;
4
        char  *p = (char*)[self cStringUsingEncoding:NSUnicodeStringEncoding];
5
        for (NSInteger i = 0; i < [self lengthOfBytesUsingEncoding:NSUnicodeStringEncoding]; i++) {
6
            if (*p) {
7
                p++;
8
                strlength++;
9
            }
10
            else {
11
                p++;
12
            }
13
        }
14
        return strlength;
15
}

字体的基本知识


字体的基本知识:
字体(Font):是一系列字号、样式和磅值相同的字符(例如:10磅黑体Palatino)。现多被视为字样的同义词
字面(Face):是所有字号的磅值和格式的综合
字体集(Font family):是一组相关字体(例如:Franklin family包括Franklin Gothic、Fran-klinHeavy和Franklin Compressed)
磅值(Weight):用于描述字体粗度。典型的磅值,从最粗到最细,有极细、细、book、中等、半粗、粗、较粗、极粗
样式(Style):字形有三种形式:Roman type是直体;oblique type是斜体;utakuc type是斜体兼曲线(比Roman type更像书法体)。
x高度(X height):指小写字母的平均高度(以x为基准)。磅值相同的两字母,x高度越大的字母看起来比x高度小的字母要大
Cap高度(Cap height):与x高度相似。指大写字母的平均高度(以C为基准)
下行字母(Descender):例如在字母q中,基线以下的字母部分叫下伸部分
上行字母(Ascender):x高度以上的部分(比如字母b)叫做上伸部分
基线(Baseline):通常在x、v、b、m下的那条线
描边(Stroke):组成字符的线或曲线。可以加粗或改变字符形状
衬线(Serif):用来使字符更可视的一条水平线。如字母左上角和下部的水平线。
无衬线(Sans Serif):可以让排字员不使用衬线装饰。
方形字(Block):这种字体的笔画使字符看起来比无衬线字更显眼,但还不到常见的衬线字的程度。例如Lubalin Graph就是方形字,这种字看起来好像是木头块刻的一样
手写体脚本(Calligraphic script):是一种仿效手写体的字体。例如Murray Hill或者Fraktur字体
艺术字(Decorative):像绘画般的字体
Pi符号(Pisymbol):非标准的字母数字字符的特殊符号。例如Wingdings和Mathematical Pi
连写(Ligature):是一系列连写字母如fi、fl、ffi或ffl。由于字些字母形状的原因经常被连写,故排字员已习惯将它们连写。

image

image

字符属性名称:

1
const CFStringRef kCTCharacterShapeAttributeName;              
2
//字体形状属性  必须是CFNumberRef对象默认为0,非0则对应相应的字符形状定义,如1表示传统字符形状
3
const CFStringRef kCTFontAttributeName;                        
4
//字体属性   必须是CTFont对象
5
const CFStringRef kCTKernAttributeName;                        
6
//字符间隔属性 必须是CFNumberRef对象
7
const CFStringRef kCTLigatureAttributeName;                 
8
//设置是否使用连字属性,设置为0,表示不使用连字属性。标准的英文连字有FI,FL.默认值为1,既是使用标准连字。也就是当搜索到f时候,会把fl当成一个文字。必须是CFNumberRef 默认为1,可取0,1,2
9
const CFStringRef kCTForegroundColorAttributeName;             
10
//字体颜色属性  必须是CGColor对象,默认为black
11
const CFStringRef kCTForegroundColorFromContextAttributeName;
12
 //上下文的字体颜色属性 必须为CFBooleanRef 默认为False,
13
const CFStringRef kCTParagraphStyleAttributeName;              
14
//段落样式属性 必须是CTParagraphStyle对象 默认为NIL
15
const CFStringRef kCTStrokeWidthAttributeName;              
16
//笔画线条宽度 必须是CFNumberRef对象,默为0.0f,标准为3.0f
17
const CFStringRef kCTStrokeColorAttributeName;              
18
//笔画的颜色属性 必须是CGColorRef 对象,默认为前景色
19
const CFStringRef kCTSuperscriptAttributeName;              
20
//设置字体的上下标属性 必须是CFNumberRef对象 默认为0,可为-1为下标,1为上标,需要字体支持才行。如排列组合的样式Cn1
21
const CFStringRef kCTUnderlineColorAttributeName;           
22
//字体下划线颜色属性 必须是CGColorRef对象,默认为前景色
23
const CFStringRef kCTUnderlineStyleAttributeName;           
24
//字体下划线样式属性 必须是CFNumberRef对象,默为kCTUnderlineStyleNone 可以通过CTUnderlineStypleModifiers 进行修改下划线风格
25
const CFStringRef kCTVerticalFormsAttributeName;
26
//文字的字形方向属性 必须是CFBooleanRef 默认为false,false表示水平方向,true表示竖直方向
27
const CFStringRef kCTGlyphInfoAttributeName;
28
//字体信息属性 必须是CTGlyphInfo对象
29
const CFStringRef kCTRunDelegateAttributeName
30
//CTRun 委托属性 必须是CTRunDelegate对象

钥匙串访问权限


ios 钥匙串的开发使用,这里使用的是SAMKeychain第三方库,详细使用参照SAMKeychain

####这里主要说的是钥匙串间的共享问题

1.首先新建一个项目SAMKeychainOne,并在项目中保存钥匙串信息

1
[SAMKeychain setPassword:@"zyn.geekzyn" forService:@"com.geekzyn" account:@"password"];
2
3
NSString *password = [SAMKeychain passwordForService:@"com.geekzyn" account:@"password" ];
4
5
self.label.text = password;

进行如下图的设置

截图.jpeg

然后新建项目2 SAMKeychainTwo,获取项目1中的保存的信息

1
NSString *password = [SAMKeychain passwordForService:@"com.geekzyn" account:@"password" ];
2
3
self.label.text = password;

并进行截图相同的配置 即可取到消息了,

必须要保证开发者账号是同一个账号下的应用可以进行共享

gzip数据压缩解析


1.需要服务器进行配置Content-Type 为gzip
2.AFN框架客户端使用下列代码即可
``OBJC
// 1.创建请求管理对象
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];

[manager.requestSerializer setValue:@"gzip" forHTTPHeaderField:@"Accept-Content"];
[manager.requestSerializer setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
manager.requestSerializer.timeoutInterval = timeoutInterval;

manager.responseSerializer = [AFHTTPResponseSerializer serializer];
manager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json",@"application/json;charset=utf-8", @"text/json", @"text/javascript", @"text/plain",@"text/html", nil];

[manager POST:url parameters:params success:^(NSURLSessionDataTask *task, id responseObject) {

// NSStringEncoding enc = CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingISOLatin1);

    NSString* strdata = [[NSString alloc]initWithData:responseObject encoding:NSUTF8StringEncoding];
    NSData *data = [strdata dataUsingEncoding:NSUTF8StringEncoding];


    NSMutableString *strM = [[NSMutableString alloc] initWithBytes:[data bytes] length:[data length] encoding:NSUTF8StringEncoding];

    NSData* jsonData = [strM dataUsingEncoding:NSUTF8StringEncoding];
    NSDictionary* dict = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:nil];
 //   NSDictionary *dict = [NSDictionary initWithJsonString:strM.copy];

    if (success) {
        success(dict);
    }
} failure:^(NSURLSessionDataTask *task, NSError *error) {
    if (failure) {
        failure(error);
    }
}];
1
2

时间格式转换问题


NSDateFormatter 格式说明:

G: 公元时代,例如AD公元
yy:年的后2位
yyyy:完整年
MM:月,显示为1-12
MMM:月,显示为英文月份简写,如 Jan
MMMM:月,显示为英文月份全称,如 Janualy
dd:日,2位数表示,如02
d:日,1-2位显示,如2
EEE:简写星期几,如Sun
EEEE:全写星期几,如Sunday
aa:上下午,AM/PM
H:时,24小时制,0-23
K:时,12小时制,0-11
m:分,1-2位
mm:分,2位
s:秒,1-2位
ss:秒,2位
S:毫秒

hh:mm:ss

按照12小时制的格式进行字符串格式化

如果时间处于00:00:00——12:59:59,则返回的字符串正常

如果时间处于13:00:00——23:59:59,则返回的字符串是实际时间-12小时后的值,也就是说比真实的时间少了12个小时。

例如:14:00:00进行格式化后的字符串为“2:00:00”

HH:mm:ss

按照24小时制的格式进行字符串格式化

当时间为任意一个区间,则返回的字符串都是正常的。

获取iOS设备唯一标识


获取iOS设备唯一标识

在开发过程中,我们经常会被要求获取每个设备的唯一标示,以便后台做相应的处理。我们来看看有哪些方法来获取设备的唯一标示,然后再分析下这些方法的利弊。
具体可以分为如下几种:

  1. UUID
  2. IDFA
  3. IDFV
  4. MAC
  5. UUID

下面我们来具体分析下每种获取方法的利弊

1. UDID

什么是UDID?
UDID 「Unique Device Identifier Description」是由子母和数字组成的40个字符串的序号,用来区别每一个唯一的iOS设备,包括 iPhones, iPads, 以及 iPod touches,这些编码看起来是随机的,实际上是跟硬件设备特点相联系的。

UDID是用来干什么的?
UDID可以关联其它各种数据到相关设备上。例如,连接到开发者账号,可以允许在发布前让设备安装或测试应用;也可以让开发者获得iOS测试版进行体验。苹果用UDID连接到苹果的ID,这些设备可以自动下载和安装从App Store购买的应用、保存从iTunes购买的音乐、帮助苹果发送推送通知、即时消息。 在iOS 应用早期,UDID被第三方应用开发者和网络广告商用来收集用户数据,可以用来关联地址、记录应用使用习惯……以便推送精准广告。

为什么苹果反对开发人员使用UDID?
iOS 2.0版本以后UIDevice提供一个获取设备唯一标识符的方法uniqueIdentifier,通过该方法我们可以获取设备的序列号,这个也是目前为止唯一可以确认唯一的标示符。 许多开发者把UDID跟用户的真实姓名、密码、住址、其它数据关联起来;网络窥探者会从多个应用收集这些数据,然后顺藤摸瓜得到这个人的许多隐私数据。同时大部分应用确实在频繁传输UDID和私人信息。 为了避免集体诉讼,苹果最终决定在iOS 5 的时候,将这一惯例废除,开发者被引导生成一个唯一的标识符,只能检测应用程序,其他的信息不提供。现在应用试图获取UDID已被禁止且不允许上架。

所以这个方法作废。

2. IDFA

全名:advertisingIdentifier
直译就是广告id, 在同一个设备上的所有App都会取到相同的值,是苹果专门给各广告提供商用来追踪用户而设的,用户可以在 设置|隐私|广告追踪 里重置此id的值,或限制此id的使用,故此id有可能会取不到值,但好在Apple默认是允许追踪的,而且一般用户都不知道有这么个设置,所以基本上用来监测推广效果,是戳戳有余了。
获取代码:

1
NSString *adId = [[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString];
注意:由于idfa会出现取不到的情况,故绝不可以作为业务分析的主id,来识别用户。

3. IDFV

全名:identifierForVendor
顾名思义,是给Vendor标识用户用的,每个设备在所属同一个Vender的应用里,都有相同的值。其中的Vender是指应用提供商,但准确点说,是通过BundleID的反转的前两部分进行匹配,如果相同就是同一个Vender,例如对于com.taobao.app1, com.taobao.app2 这两个BundleID来说,就属于同一个Vender,共享同一个idfv的值。和idfa不同的是,idfv的值是一定能取到的,所以非常适合于作为内部用户行为分析的主id,来标识用户,替代OpenUDID。
获取代码:

1
NSString *idfv = [[[UIDevice currentDevice] identifierForVendor] UUIDString];
注意:如果用户将属于此Vender的所有App卸载,则idfv的值会被重置,即再重装此Vender的App,
idfv的值和之前不同。

4. MAC地址

使用WiFi的mac地址来取代已经废弃了的uniqueIdentifier方法。具体可见:http://stackoverflow.com/questions/677530/how-can-i-programmatically-get-the-mac-address-of-an-iphone

然而在iOS 7中苹果再一次无情的封杀mac地址,使用之前的方法获取到的mac地址全部都变成了02:00:00:00:00:00。

5. UUID

我们可以获取到UUID,然后把UUID保存到KeyChain里面。

这样以后即使APP删了再装回来,也可以从KeyChain中读取回来。使用group还可以可以保证同一个开发商的所有程序针对同一台设备能够获取到相同的不变的UDID。
但是刷机或重装系统后uuid还是会改变。

使用Keychain,将UUID当做密码信息来存储.
流程如下:

  1. 通过AdSupport获取UUID

    1
    -(NSString *)appleIFA {
    2
      NSString *ifa = nil;
    3
        Class ASIdentifierManagerClass = NSClassFromString(@"ASIdentifierManager");
    4
        if (ASIdentifierManagerClass) { // a dynamic way of checking if AdSupport.framework is available
    5
            SEL sharedManagerSelector = NSSelectorFromString(@"sharedManager");
    6
            id sharedManager = ((id (*)(id, SEL))[ASIdentifierManagerClass methodForSelector:sharedManagerSelector])(ASIdentifierManagerClass, sharedManagerSelector);
    7
            SEL advertisingIdentifierSelector = NSSelectorFromString(@"advertisingIdentifier");
    8
            NSUUID *advertisingIdentifier = ((NSUUID* (*)(id, SEL))[sharedManager methodForSelector:advertisingIdentifierSelector])(sharedManager, advertisingIdentifierSelector);
    9
            ifa = [advertisingIdentifier UUIDString];
    10
        }
    11
        return ifa;
    12
    }
  2. 如果不支持AdSupport,那就使用IFV/IDFV (Identifier for Vendor)

    1
    + (NSString *)appleIFV {
    2
        if(NSClassFromString(@"UIDevice") && [UIDevice instancesRespondToSelector:@selector(identifierForVendor)]) {
    3
            // only available in iOS >= 6.0
    4
            return [[UIDevice currentDevice].identifierForVendor UUIDString];
    5
        }
    6
        return nil;
    7
    }
  3. 如果以上的都不支持,使用CFUUIDRef手动创建UUID

    1
    + (NSString *)randomUUID {
    2
        if(NSClassFromString(@"NSUUID")) { // only available in iOS >= 6.0
    3
            return [[NSUUID UUID] UUIDString];
    4
        }
    5
        CFUUIDRef uuidRef = CFUUIDCreate(kCFAllocatorDefault);
    6
        CFStringRef cfuuid = CFUUIDCreateString(kCFAllocatorDefault, uuidRef);
    7
        CFRelease(uuidRef);
    8
        NSString *uuid = [((__bridge NSString *) cfuuid) copy];
    9
        CFRelease(cfuuid);
    10
        return uuid;
    11
    }

NSDateFormatter格式


a: AM/PM (上午/下午)
A: 086399999 (一天的第A微秒)
c/cc: 1
7 (一周的第一天, 周天为1)
ccc: Sun/Mon/Tue/Wed/Thu/Fri/Sat (星期几简写)
cccc: Sunday/Monday/Tuesday/Wednesday/Thursday/Friday/Saturday (星期几全拼)
d: 131 (月份的第几天, 带0)
D: 1
366 (年份的第几天,带0)
e: 17 (一周的第几天, 带0)
E
EEE: Sun/Mon/Tue/Wed/Thu/Fri/Sat (星期几简写)
EEEE: Sunday/Monday/Tuesday/Wednesday/Thursday/Friday/Saturday (星期几全拼)
F: 15 (每月的第几周, 一周的第一天为周一)
g: Julian Day Number (number of days since 4713 BC January 1) 未知
G
GGG: BC/AD (Era Designator Abbreviated) 未知
GGGG: Before Christ/Anno Domini 未知
h: 112 (0 padded Hour (12hr)) 带0的时, 12小时制
H: 0
23 (0 padded Hour (24hr)) 带0的时, 24小时制
k: 124 (0 padded Hour (24hr) 带0的时, 24小时制
K: 0
11 (0 padded Hour (12hr)) 带0的时, 12小时制
L/LL: 112 (0 padded Month) 第几月
LLL: Jan/Feb/Mar/Apr/May/Jun/Jul/Aug/Sep/Oct/Nov/Dec 月份简写
LLLL: January/February/March/April/May/June/July/August/September/October/November/December 月份全称
m: 0
59 (0 padded Minute) 分钟
M/MM: 112 (0 padded Month) 第几月
MMM: Jan/Feb/Mar/Apr/May/Jun/Jul/Aug/Sep/Oct/Nov/Dec
MMMM: January/February/March/April/May/June/July/August/September/October/November/December
q/qq: 1
4 (0 padded Quarter) 第几季度
qqq: Q1/Q2/Q3/Q4 季度简写
qqqq: 1st quarter/2nd quarter/3rd quarter/4th quarter 季度全拼
Q/QQ: 14 (0 padded Quarter) 同小写
QQQ: Q1/Q2/Q3/Q4 同小写
QQQQ: 1st quarter/2nd quarter/3rd quarter/4th quarter 同小写
s: 0
59 (0 padded Second) 秒数
S: (rounded Sub-Second) 未知
u: (0 padded Year) 未知
vvvv: (General GMT Timezone Abbreviation) 常规GMT时区的编写
vvvv: (General GMT Timezone Name) 常规GMT时区的名称
w: 1
53 (0 padded Week of Year, 1st day of week = Sunday, NB: 1st week of year starts from the last Sunday of last year) 一年的第几周, 一周的开始为周日,第一周从去年的最后一个周日起算
W: 15 (0 padded Week of Month, 1st day of week = Sunday) 一个月的第几周
y/yyyy: (Full Year) 完整的年份
yy/yyy: (2 Digits Year) 2个数字的年份
Y/YYYY: (Full Year, starting from the Sunday of the 1st week of year) 这个年份未知干嘛用的
YY/YYY: (2 Digits Year, starting from the Sunday of the 1st week of year) 这个年份未知干嘛用的
z
zzz: (Specific GMT Timezone Abbreviation) 指定GMT时区的编写
zzzz: (Specific GMT Timezone Name) Z: +0000 (RFC 822 Timezone) 指定GMT时区的名称

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×