The keychain is about the only place that an iPhone application can safely store data that will be preserved across a re-installation of the application. Each iPhone application gets its own set of keychain items which are backed up whenev
The keychain is about the only place that an iPhone application can safely store data that will be preserved across a re-installation of the application. Each iPhone application gets its own set of keychain items which are backed up whenever the user backs up the device via iTunes. The backup data is encrypted as part of the backup so that it remains secure even if somebody gets access to the backup data. This makes it very attractive to store sensitive data such as passwords, license keys, etc.
The only problem is that accessing the keychain services is complicated and even the GenericKeychain example code is hard to follow. I hate to include cut and pasted code into my application, especially when I do not understand it. Instead I have gone back to basics to build up a simple iPhone keychain access example that does just what I want and not much more.
In fact all I really want to be able to do is securely store a password string for my application and be able to retrieve it a later date.
Getting Started
A couple of housekeeping items to get started:
- Add the “Security.framework” framework to your iPhone application
- Include the header file
Note that the security framework is a good old fashioned C framework so no Objective-C style methods calls. Also it will only work on the device not in in the iPhone Simulator.
The Basic Search Dictionary
All of the calls to the keychain services make use of a dictionary to define the attributes of the keychain item you want to find, create, update or delete. So the first thing we will do is define a function to allocate and construct this dictionary for us:
<code>static NSString *serviceName = @"com.mycompany.myAppServiceName"; - (NSMutableDictionary *)newSearchDictionary:(NSString *)identifier { NSMutableDictionary *searchDictionary = [[NSMutableDictionary alloc] init]; [searchDictionary setObject:(id)kSecClassGenericPassword forKey:(id)kSecClass]; NSData *encodedIdentifier = [identifier dataUsingEncoding:NSUTF8StringEncoding]; [searchDictionary setObject:encodedIdentifier forKey:(id)kSecAttrGeneric]; [searchDictionary setObject:encodedIdentifier forKey:(id)kSecAttrAccount]; [searchDictionary setObject:serviceName forKey:(id)kSecAttrService]; return searchDictionary; } </code>
The dictionary contains three items. The first with key kSecClass defines the class of the keychain item we will be dealing with. I want to store a password in the keychain so I use the value kSecClassGenericPassword for the value.
The second item in the dictionary with key kSecAttrGeneric is what we will use to identify the keychain item. It can be any value we choose such as “Password” or “LicenseKey”, etc. To be clear this is not the actual value of the password just a label we will attach to this keychain item so we can find it later. In theory our application could store a number of passwords in the keychain so we need to have a way to identify this particular one from the others. The identifier has to be encoded before being added to the dictionary
The combination of the final two attributes kSecAttrAccount and kSecAttrService should be set to something unique for this keychain. In this example I set the service name to a static string and reuse the identifier as the account name.
You can use multiple attributes for a given class of item. Some of the other attributes that we could also use for the kSecClassGenericPassword item include an account name, description, etc. However by using just a single attribute we can simplify the rest of the code.
Searching the keychain
To find out if our password already exists in the keychain (and what the value of the password is) we use the SecItemCopyMatching function. But first we add a couple of extra items to our basic search dictionary:
<code>- (NSData *)searchKeychainCopyMatching:(NSString *)identifier { NSMutableDictionary *searchDictionary = [self newSearchDictionary:identifier]; // Add search attributes [searchDictionary setObject:(id)kSecMatchLimitOne forKey:(id)kSecMatchLimit]; // Add search return types [searchDictionary setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnData]; NSData *result = nil; OSStatus status = SecItemCopyMatching((CFDictionaryRef)searchDictionary, (CFTypeRef *)&result); [searchDictionary release]; return result; } </code>
The first attribute we add to the dictionary is to limit the number of search results that get returned. We are looking for a single entry so we set the attribute kSecMatchLimit to kSecMatchLimitOne.
The next attribute determines how the result is returned. Since in our simple case we are expecting only a single attribute to be returned (the password) we can set the attribute kSecReturnData to kCFBooleanTrue. This means we will get an NSData reference back that we can access directly.
If we were storing and searching for a keychain item with multiple attributes (for example if we were storing an account name and password in the same keychain item) we would need to add the attribute kSecReturnAttributes and the result would be a dictionary of attributes.
Now with the search dictionary set up we call the SecItemCopyMatching function and if our item exists in the keychain the value of the password is returned to in the NSData block. To get the actual decoded string you could do something like:
<code> NSData *passwordData = [self searchKeychainCopyMatching:@"Password"]; if (passwordData) { NSString *password = [[NSString alloc] initWithData:passwordData encoding:NSUTF8StringEncoding]; [passwordData release]; } </code>
Creating an item in the keychain
Adding an item is almost the same as the previous examples except that we need to set the value of the password we want to store.
<code>- (BOOL)createKeychainValue:(NSString *)password forIdentifier:(NSString *)identifier { NSMutableDictionary *dictionary = [self newSearchDictionary:identifier]; NSData *passwordData = [password dataUsingEncoding:NSUTF8StringEncoding]; [dictionary setObject:passwordData forKey:(id)kSecValueData]; OSStatus status = SecItemAdd((CFDictionaryRef)dictionary, NULL); [dictionary release]; if (status == errSecSuccess) { return YES; } return NO; } </code>
To set the value of the password we add the attribute kSecValueData to our search dictionary making sure we encode the string and then call SecItemAdd passing the dictionary as the first argument. If the item already exists in the keychain this will fail.
Updating a keychain item
Updating a keychain is similar to adding an item except that a separate dictionary is used to contain the attributes to be updated. Since in our case we are only updating a single attribute (the password) this is easy:
<code>- (BOOL)updateKeychainValue:(NSString *)password forIdentifier:(NSString *)identifier { NSMutableDictionary *searchDictionary = [self newSearchDictionary:identifier]; NSMutableDictionary *updateDictionary = [[NSMutableDictionary alloc] init]; NSData *passwordData = [password dataUsingEncoding:NSUTF8StringEncoding]; [updateDictionary setObject:passwordData forKey:(id)kSecValueData]; OSStatus status = SecItemUpdate((CFDictionaryRef)searchDictionary, (CFDictionaryRef)updateDictionary); [searchDictionary release]; [updateDictionary release]; if (status == errSecSuccess) { return YES; } return NO; } </code>
Deleting an item from the keychain
The final (and easiest) operation is to delete an item from the keychain using the SecItemDelete function and our usual search dictionary:
<code>- (void)deleteKeychainValue:(NSString *)identifier { NSMutableDictionary *searchDictionary = [self newSearchDictionary:identifier]; SecItemDelete((CFDictionaryRef)searchDictionary); [searchDictionary release]; } </code>

苹果xs max是苹果第十二代。“X”是罗马数字中的10,“X”代表苹果向iPhone问世十周年的致敬;2017年9月13日,iPhone X正式发布,该产品为苹果第十一代产品;iPhone XS Max是2018年9月13日发布的,为第十二代苹果手机。

iphone13 mini是单卡。iphone13 mini是苹果公司于2021年9月15日发布的一款智能手机,其SIM卡片类型为nano-SIM卡,并不兼容现有的micro-SIM卡,因此不支持双卡模式;该机为5G(sub-6 GHz)全网通手机(支持中国联通、中国移动和中国电信),支持GSM/EDGE、UMTS/HSPA+、DC-HSDPA网络。

iphone13 pro可以插2张卡。iPhone13 Pro是苹果公司于北京时间2021年9月15日发布的智能手机,支持双卡双待,支持双卡nano-SIM卡,但不兼容现有的micro-SIM卡;应用双卡要求运用两项移动通信服务,不支持同一时刻使用两项CDMA移动通信服务,且仅部分运营商支持双VoLTE。

iphone13摄像头旁边的小孔是麦克风,采用双唛降噪设计,是辅助副送话器收音用的,可以用来降低环境噪音和提升通话语音的清晰度的。由于在拍摄视频的时候会由于环境噪音导致被摄主体的收音效果不佳,目前大部分的智能手机都会在机身上设置有多个降噪麦克风,用来录制周围环境的噪音,结合降噪算法,实现降噪效果。

iphone13是双卡双待,iphone13系列中只有“iPhone 13 mini”不是双卡双待;苹果iPhone13支持双卡双待,双卡类型为“nano-SIM”,不支持现有的“micro-SIM”卡,需要正反两面安装SIM卡,一共可以安装两张“12mm*9mm nano-SIM”卡。

iphone数据漫游是指iPhone蜂窝网络下的“数据漫游”功能,而数据漫游就是跨运营商的漫游;在国内,该功能无论是打开或者关闭,都是没有任何作用的,因为它只是针对国际上不同的移动运营商起作用。

区别:1、教育优惠比官网标价(普通版)要便宜。2、教育优惠官网下单速度会比普通版慢,普通版有货的状态一般是1-3个工作日就发货了,教育优惠版比较快的也是几天时间,如果是遇到了开学前大量学生购买的高峰期,可能要排队几个星期。3、教育优惠适用人群为准大学生、大学生、教职工(包括大中小学以及特殊教育学校的教职工群体);而普通版的适用人群比较广。

区别:1、苹果11采用A13仿生处理芯片,具有4核图形处理器和8核神经网络引擎;而13采用采用A15仿生处理芯片,具有4核图形处理器和16核神经网络引擎。2、苹果11屏幕尺寸为6.1英寸Liquid 视网膜高清显示屏;而苹果13屏幕尺寸为6.1英寸超视网膜XDR显示屏。3、苹果11的屏幕对比度为1400:1对比度,而苹果13的屏幕对比度为2000000:1对比度。


Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

AI Hentai Generator
Generate AI Hentai for free.

Hot Article

Hot Tools

Zend Studio 13.0.1
Powerful PHP integrated development environment

Notepad++7.3.1
Easy-to-use and free code editor

SecLists
SecLists is the ultimate security tester's companion. It is a collection of various types of lists that are frequently used during security assessments, all in one place. SecLists helps make security testing more efficient and productive by conveniently providing all the lists a security tester might need. List types include usernames, passwords, URLs, fuzzing payloads, sensitive data patterns, web shells, and more. The tester can simply pull this repository onto a new test machine and he will have access to every type of list he needs.

ZendStudio 13.5.1 Mac
Powerful PHP integrated development environment

EditPlus Chinese cracked version
Small size, syntax highlighting, does not support code prompt function
