zoukankan      html  css  js  c++  java
  • 第十八篇、keychain保存UUID(保持唯一性,应用卸载,下载安装也不变)和获取IP地址

    .h

    #import <Foundation/Foundation.h>
    #import <Security/Security.h>
    
    /**使用**/
    //-(void) setKeyChainValue
    //{
    //    KeychainItemWrapper *keyChainItem=[[KeychainItemWrapper alloc]initWithIdentifier:@"TestUUID" accessGroup:@"XXXXXX.h.HelloWorld"];
    //    NSString *strUUID = [keyChainItem objectForKey:(id)kSecValueData];
    //    if (strUUID==nil||[strUUID isEqualToString:@""])
    //    {
    //        [keyChainItem setObject:[self gen_uuid] forKey:(id)kSecValueData];
    //    }
    //    [keyChainItem release];
    //    
    //}
    //
    //-(NSString *) gen_uuid
    //{
    //    CFUUIDRef uuid_ref=CFUUIDCreate(nil);
    //    CFStringRef uuid_string_ref=CFUUIDCreateString(nil, uuid_ref);
    //    CFRelease(uuid_ref);
    //    NSString *uuid=[NSString stringWithString:uuid_string_ref];
    //    CFRelease(uuid_string_ref);
    //    return uuid;
    //}
    
    //Define an Objective-C wrapper class to hold Keychain Services code.
    @interface KeychainWrapper : NSObject
    
    {
        NSMutableDictionary        *keychainData;
        NSMutableDictionary        *genericPasswordQuery;
    }
    @property (nonatomic, strong) NSMutableDictionary *keychainData;
    @property (nonatomic, strong) NSMutableDictionary *genericPasswordQuery;
    
    - (void)mySetObject:(id)inObject forKey:(id)key;
    - (id)myObjectForKey:(id)key;
    - (void)resetKeychainItem;
    
    +(instancetype) shareManager;
    /**获取唯一的UUID**/
    -(NSString *) KeyChainValue;
    @end

    .m

    #import "KeychainWrapper.h"
    
    /* ********************************************************************** */
    //Unique string used to identify the keychain item:
    static const UInt8 kKeychainItemIdentifier[]    = "com.apple.dts.KeychainUI";
    
    @interface KeychainWrapper (PrivateMethods)
    
    
    //The following two methods translate dictionaries between the format used by
    // the view controller (NSString *) and the Keychain Services API:
    - (NSMutableDictionary *)secItemFormatToDictionary:(NSDictionary *)dictionaryToConvert;
    - (NSMutableDictionary *)dictionaryToSecItemFormat:(NSDictionary *)dictionaryToConvert;
    // Method used to write data to the keychain:
    - (void)writeToKeychain;
    
    @end
    
    @implementation KeychainWrapper
    
    //Synthesize the getter and setter:
    @synthesize keychainData, genericPasswordQuery;
    
    
    static KeychainWrapper *manager = nil;
    +(instancetype) shareManager
    {
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            manager = [[KeychainWrapper alloc]init];
        });
        return manager;
    
    }
    
    /**获取唯一的UUID**/
    -(NSString *) KeyChainValue
    {
        NSString *strUUID = [self myObjectForKey:(id)kSecValueData];
        if (strUUID==nil||[strUUID isEqualToString:@""])
        {
            [self mySetObject:[self uuid] forKey:(id)kSecValueData];
            strUUID = [self uuid]; // 首次获取为空,需要赋值
        }
        return strUUID;
    }
    
    -(NSString*) uuid {
        CFUUIDRef puuid = CFUUIDCreate( nil );
        CFStringRef uuidString = CFUUIDCreateString( nil, puuid );
        NSString * result = (NSString *)CFBridgingRelease(CFStringCreateCopy( NULL, uuidString));
        CFRelease(puuid);
        CFRelease(uuidString);
        return result;
    }
    
    
    - (id)init
    {
        if ((self = [super init])) {
            
            OSStatus keychainErr = noErr;
            // Set up the keychain search dictionary:
            genericPasswordQuery = [[NSMutableDictionary alloc] init];
            // This keychain item is a generic password.
            [genericPasswordQuery setObject:(__bridge id)kSecClassGenericPassword
                                     forKey:(__bridge id)kSecClass];
            // The kSecAttrGeneric attribute is used to store a unique string that is used
            // to easily identify and find this keychain item. The string is first
            // converted to an NSData object:
            NSData *keychainItemID = [NSData dataWithBytes:kKeychainItemIdentifier
                                                    length:strlen((const char *)kKeychainItemIdentifier)];
            [genericPasswordQuery setObject:keychainItemID forKey:(__bridge id)kSecAttrGeneric];
            // Return the attributes of the first match only:
            [genericPasswordQuery setObject:(__bridge id)kSecMatchLimitOne forKey:(__bridge id)kSecMatchLimit];
            // Return the attributes of the keychain item (the password is
            //  acquired in the secItemFormatToDictionary: method):
            [genericPasswordQuery setObject:(__bridge id)kCFBooleanTrue
                                     forKey:(__bridge id)kSecReturnAttributes];
            
            //Initialize the dictionary used to hold return data from the keychain:
            CFMutableDictionaryRef outDictionary = nil;
            // If the keychain item exists, return the attributes of the item:
            keychainErr = SecItemCopyMatching((__bridge CFDictionaryRef)genericPasswordQuery,
                                              (CFTypeRef *)&outDictionary);
            if (keychainErr == noErr) {
                // Convert the data dictionary into the format used by the view controller:
                self.keychainData = [self secItemFormatToDictionary:(__bridge_transfer NSMutableDictionary *)outDictionary];
            } else if (keychainErr == errSecItemNotFound) {
                // Put default values into the keychain if no matching
                // keychain item is found:
                [self resetKeychainItem];
                if (outDictionary) CFRelease(outDictionary);
            } else {
                // Any other error is unexpected.
                NSAssert(NO, @"Serious error.
    ");
                if (outDictionary) CFRelease(outDictionary);
            }
        }
        return self;
    }
    
    // Implement the mySetObject:forKey method, which writes attributes to the keychain:
    - (void)mySetObject:(id)inObject forKey:(id)key
    {
        if (inObject == nil) return;
        id currentObject = [keychainData objectForKey:key];
        if (![currentObject isEqual:inObject])
        {
            [keychainData setObject:inObject forKey:key];
            [self writeToKeychain];
        }
    }
    
    // Implement the myObjectForKey: method, which reads an attribute value from a dictionary:
    - (id)myObjectForKey:(id)key
    {
        return [keychainData objectForKey:key];
    }
    
    // Reset the values in the keychain item, or create a new item if it
    // doesn't already exist:
    
    - (void)resetKeychainItem
    {
        if (!keychainData) //Allocate the keychainData dictionary if it doesn't exist yet.
        {
            self.keychainData = [[NSMutableDictionary alloc] init];
        }
        else if (keychainData)
        {
            // Format the data in the keychainData dictionary into the format needed for a query
            //  and put it into tmpDictionary:
            NSMutableDictionary *tmpDictionary =
            [self dictionaryToSecItemFormat:keychainData];
            // Delete the keychain item in preparation for resetting the values:
            OSStatus errorcode = SecItemDelete((__bridge CFDictionaryRef)tmpDictionary);
            NSAssert(errorcode == noErr, @"Problem deleting current keychain item." );
        }
        
        // Default generic data for Keychain Item:
    //    [keychainData setObject:@"Item label" forKey:(__bridge id)kSecAttrLabel];
    //    [keychainData setObject:@"Item description" forKey:(__bridge id)kSecAttrDescription];
    //    [keychainData setObject:@"Account" forKey:(__bridge id)kSecAttrAccount];
    //    [keychainData setObject:@"Service" forKey:(__bridge id)kSecAttrService];
    //    [keychainData setObject:@"Your comment here." forKey:(__bridge id)kSecAttrComment];
    //    [keychainData setObject:@"password" forKey:(__bridge id)kSecValueData];
    }
    
    // Implement the dictionaryToSecItemFormat: method, which takes the attributes that
    // you want to add to the keychain item and sets up a dictionary in the format
    // needed by Keychain Services:
    - (NSMutableDictionary *)dictionaryToSecItemFormat:(NSDictionary *)dictionaryToConvert
    {
        // This method must be called with a properly populated dictionary
        // containing all the right key/value pairs for a keychain item search.
        
        // Create the return dictionary:
        NSMutableDictionary *returnDictionary =
        [NSMutableDictionary dictionaryWithDictionary:dictionaryToConvert];
        
        // Add the keychain item class and the generic attribute:
        NSData *keychainItemID = [NSData dataWithBytes:kKeychainItemIdentifier
                                                length:strlen((const char *)kKeychainItemIdentifier)];
        [returnDictionary setObject:keychainItemID forKey:(__bridge id)kSecAttrGeneric];
        [returnDictionary setObject:(__bridge id)kSecClassGenericPassword forKey:(__bridge id)kSecClass];
        
        // Convert the password NSString to NSData to fit the API paradigm:
        NSString *passwordString = [dictionaryToConvert objectForKey:(__bridge id)kSecValueData];
        [returnDictionary setObject:[passwordString dataUsingEncoding:NSUTF8StringEncoding]
                             forKey:(__bridge id)kSecValueData];
        return returnDictionary;
    }
    
    // Implement the secItemFormatToDictionary: method, which takes the attribute dictionary
    //  obtained from the keychain item, acquires the password from the keychain, and
    //  adds it to the attribute dictionary:
    - (NSMutableDictionary *)secItemFormatToDictionary:(NSDictionary *)dictionaryToConvert
    {
        // This method must be called with a properly populated dictionary
        // containing all the right key/value pairs for the keychain item.
        
        // Create a return dictionary populated with the attributes:
        NSMutableDictionary *returnDictionary = [NSMutableDictionary
                                                 dictionaryWithDictionary:dictionaryToConvert];
        
        // To acquire the password data from the keychain item,
        // first add the search key and class attribute required to obtain the password:
        [returnDictionary setObject:(__bridge id)kCFBooleanTrue forKey:(__bridge id)kSecReturnData];
        [returnDictionary setObject:(__bridge id)kSecClassGenericPassword forKey:(__bridge id)kSecClass];
        // Then call Keychain Services to get the password:
        CFDataRef passwordData = NULL;
        OSStatus keychainError = noErr; //
        keychainError = SecItemCopyMatching((__bridge CFDictionaryRef)returnDictionary,
                                            (CFTypeRef *)&passwordData);
        if (keychainError == noErr)
        {
            // Remove the kSecReturnData key; we don't need it anymore:
            [returnDictionary removeObjectForKey:(__bridge id)kSecReturnData];
            
            // Convert the password to an NSString and add it to the return dictionary:
            NSString *password = [[NSString alloc] initWithBytes:[(__bridge_transfer NSData *)passwordData bytes]
                                                          length:[(__bridge NSData *)passwordData length] encoding:NSUTF8StringEncoding];
            [returnDictionary setObject:password forKey:(__bridge id)kSecValueData];
        }
        // Don't do anything if nothing is found.
        else if (keychainError == errSecItemNotFound) {
            NSAssert(NO, @"Nothing was found in the keychain.
    ");
            if (passwordData) CFRelease(passwordData);
        }
        // Any other error is unexpected.
        else
        {
            NSAssert(NO, @"Serious error.
    ");
            if (passwordData) CFRelease(passwordData);
        }
        
        return returnDictionary;
    }
    
    // Implement the writeToKeychain method, which is called by the mySetObject routine,
    //   which in turn is called by the UI when there is new data for the keychain. This
    //   method modifies an existing keychain item, or--if the item does not already
    //   exist--creates a new keychain item with the new attribute value plus
    //  default values for the other attributes.
    - (void)writeToKeychain
    {
        CFDictionaryRef attributes = nil;
        NSMutableDictionary *updateItem = nil;
        
        // If the keychain item already exists, modify it:
        if (SecItemCopyMatching((__bridge CFDictionaryRef)genericPasswordQuery,
                                (CFTypeRef *)&attributes) == noErr)
        {
            // First, get the attributes returned from the keychain and add them to the
            // dictionary that controls the update:
            updateItem = [NSMutableDictionary dictionaryWithDictionary:(__bridge_transfer NSDictionary *)attributes];
            
            // Second, get the class value from the generic password query dictionary and
            // add it to the updateItem dictionary:
            [updateItem setObject:[genericPasswordQuery objectForKey:(__bridge id)kSecClass]
                           forKey:(__bridge id)kSecClass];
            
            // Finally, set up the dictionary that contains new values for the attributes:
            NSMutableDictionary *tempCheck = [self dictionaryToSecItemFormat:keychainData];
            //Remove the class--it's not a keychain attribute:
            [tempCheck removeObjectForKey:(__bridge id)kSecClass];
            
            // You can update only a single keychain item at a time.
            OSStatus errorcode = SecItemUpdate(
                                               (__bridge CFDictionaryRef)updateItem,
                                               (__bridge CFDictionaryRef)tempCheck);
            NSAssert(errorcode == noErr, @"Couldn't update the Keychain Item." );
        }
        else
        {
            // No previous item found; add the new item.
            // The new value was added to the keychainData dictionary in the mySetObject routine,
            // and the other values were added to the keychainData dictionary previously.
            // No pointer to the newly-added items is needed, so pass NULL for the second parameter:
            OSStatus errorcode = SecItemAdd(
                                            (__bridge CFDictionaryRef)[self dictionaryToSecItemFormat:keychainData],
                                            NULL);
            NSAssert(errorcode == noErr, @"Couldn't add the Keychain Item." );
            if (attributes) CFRelease(attributes);
        }
    }
    
    
    @end


    获取设备的IP地址

    #import "getIPhoneIP.h"
    #import <ifaddrs.h>
    #import <arpa/inet.h>
    
    @implementation getIPhoneIP
    //create by huangys
    +(NSString *)getIPAddress {
        NSString *address = @"error";
        struct ifaddrs *interfaces = NULL;
        struct ifaddrs *temp_addr = NULL;
        int success = 0;
        // retrieve the current interfaces - returns 0 on success
        success = getifaddrs(&interfaces);
        if (success == 0) {
            // Loop through linked list of interfaces
            temp_addr = interfaces;
            while(temp_addr != NULL) {
                if(temp_addr->ifa_addr->sa_family == AF_INET) {
                    // Check if interface is en0 which is the wifi connection on the iPhone
                    if([[NSString stringWithUTF8String:temp_addr->ifa_name] isEqualToString:@"en0"]) {
                        // Get NSString from C String
                        address = [NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_addr)->sin_addr)];
                    }
                }
                temp_addr = temp_addr->ifa_next;
            }
        }
        // Free memory
        freeifaddrs(interfaces);
        return address;
    }
    @end
  • 相关阅读:
    [转载] IE8+兼容小结
    vue添加,删除内容
    vue跳转的两种方法
    checked 完整版全选,单选,反选
    网页特殊符号HTML代码大全
    利用css 实现 视觉差效果
    css 自定义滚动条样式
    js 模拟键盘
    css 动画 transition和animation
    浅谈浏览器垃圾回收机制
  • 原文地址:https://www.cnblogs.com/HJQ2016/p/5818204.html
Copyright © 2011-2022 走看看