IOS 日常随笔

自己的demo

自定义Alertview -- LSAlertView
图片浏览器 -- LSShowImgs
倒计时 -- LSDailyNotes
自定义导航交互管理器 -- LSPercentDrivenInteractiveTransition
星级评分view -- LSRatingStar

1. 调用系统相册、相机发现是英文的系统相簿界面后标题显示“photos”,但是手机语言已经设置显示中文,纠结半天,最终在

info.plist设置解决问题。在info.plist里面添加

  • Localized sources can be mixed 值为YES
  • Localization native development region 值为China
    表示是否允许应用程序获取框架库内语言。
2. App中如何打开百度或者高德地图

百度地图URI API地址
高德地图URI API地址
腾讯地图URI API地址

[[UIApplication sharedApplication]canOpenURL:[NSURL URLWithString:@"baidumap://map/"]]

[[UIApplication sharedApplication]canOpenURL:[NSURL URLWithString:@"iosamap://"]]
可以判读是否安装的百度地图与高德地图。而后通过

//打开百度地图导航

- (void)openBaiDuMap{
NSString *urlString =@"";
///打开百度地图app
urlString = [[NSString stringWithFormat:@"baidumap://map/direction?origin=latlng:%f,%f|name:%@&destination=latlng:%f,%f|name:%@&mode=driving®ion=%@&output=html",34.264642646862,108.95108518068,@"我的位置",39.98871,116.43234,@"天安门",@"吉林"] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding] ;

/////打开webapp(网页版)
//urlString = [[NSString stringWithFormat:@"https://api.map.baidu.com/direction?origin=latlng:%f,%f|name:%@&destination=latlng:%f,%f|name:%@&mode=driving®ion=%@&output=html",34.264642646862,108.95108518068,@"我的位置",39.98871,116.43234,@"天安门",@"吉林"] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding] ;


[[UIApplication sharedApplication]openURL:[NSURL URLWithString:urlString]];

}
//打开高德地图导航

- (void)openGaoDeMap{

NSString *urlString = [[NSString stringWithFormat:@"iosamap://navi?sourceApplication=%@&backScheme=%@&poiname=%@&lat=%f&lon=%f&dev=1&style=2",@"app name", @"YGche", @"终点", _shopLat, _shopLon] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];

//urlString = [[NSString stringWithFormat:@"iosamap://path?sourceApplication=%@&sid=BGVIS1&slat=%f&slon=%f&sname=我的位置&did=BGVIS2&dlat=%f&dlon=%f&dname=%@&dev=0&m=0&t=0",@"点点吉林",39.92848272,116.39560823,39.98848272,116.47560823,@"终点"] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
//    urlString = [[NSString stringWithFormat:@"http://m.amap.com/?from=%f,%f(我的位置)&to=%f,%f(终点)&type=0&opt=1",39.997361,116.478346,39.966577,116.3246] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];


[[UIApplication sharedApplication]openURL:[NSURL URLWithString:urlString]];

}

//打开腾讯地图导航(暂不支持打开打开)

- (void)openBaiDuMap{
NSString *urlString =@"";
/////打开webapp(网页版)
NSString *urlString=@"";
                        urlString = [[NSString stringWithFormat:@"https://apis.map.qq.com/uri/v1/routeplan?type=drive&from=我的位置&fromcoord=39.980683,116.302&to=%@&tocoord=%f,%f&policy=1&referer=点点吉林",@"终点",latitude,longitude] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];


[[UIApplication sharedApplication]openURL:[NSURL URLWithString:urlString]];

}

//打开苹果自带地图导航

- (void)openAppleMap{

//起点

CLLocationCoordinate2D coords1 = CLLocationCoordinate2DMake(currentLatitude,currentLongitude);

MKMapItem *currentLocation = [[MKMapItem alloc] initWithPlacemark:[[MKPlacemark alloc] initWithCoordinate:coords1 addressDictionary:nil]];

//目的地的位置

CLLocationCoordinate2D coords2 = CLLocationCoordinate2DMake(_shopLat,_shopLon);

MKMapItem *toLocation = [[MKMapItem alloc] initWithPlacemark:[[MKPlacemark alloc] initWithCoordinate:coords2 addressDictionary:nil]];

toLocation.name =address;

NSArray *items = [NSArray arrayWithObjects:currentLocation, toLocation, nil];

NSDictionary *options = @{ MKLaunchOptionsDirectionsModeKey:MKLaunchOptionsDirectionsModeDriving, MKLaunchOptionsMapTypeKey: [NSNumber numberWithInteger:MKMapTypeStandard], MKLaunchOptionsShowsTrafficKey:@YES };

//打开苹果自身地图应用,并呈现特定的item

[MKMapItem openMapsWithItems:items launchOptions:options];

}

在更新iOS9后原来的方法不起做用了。解决办法:
在info.plist添加白名单
LSApplicationQueriesSchemes

baidumap
iosamap

3.avplayer 播放器demo

https://github.com/renzifeng/ZFPlayer
https://github.com/xhzengAIB/PlayerKit
https://github.com/36Kr-Mobile/KRVideoPlayer
https://github.com/douban/DOUAudioStreamer
https://github.com/Bilibili/ijkplayer

4.常用的swift第三方

Network:
Alamofire:著名的AFNetworking网络基础库Swift版 - Alamofire/Alamofire · GitHub**
SwiftyJSON:最为开发者认可的JSON解析类 - SwiftyJSON/SwiftyJSON · GitHub**
Storage:
SQLite.swift:简单、轻量,使用上最SQL的SQLite封装库 - stephencelis/SQLite.swift · GitHub**
SugarRecord:基于CoreData与REALM的好用封装 - SugarRecord/SugarRecord · GitHub**UI:
SweetAlert:带动画效果弹窗封装类 - codestergit/SweetAlert-iOS · GitHub**
RAMAnimatedTabBarController:灵动的动画标签栏类库 - Ramotion/animated-tab-bar · GitHub**
PNChart-Swift:带动画效果的图表控件库 - kevinzhow/PNChart-Swift · GitHub**
LTMorphingLabel:各种文字动画效果 - lexrus/LTMorphingLabel · GitHub**
Cartography:用代码解决麻烦的AutoLayout - robb/Cartography · GitHub**
Kingfisher : swift 中的SDWebImage 类似库
onevcat/Kingfisher Github**
SnapKit : swift 中的约束 类似库
SnapKit/SnapKit Github**

下拉刷新

BreakOutToRefresh 一个下拉刷新打砖块的swift库
SDRefreshView 简单易用的上拉和下拉刷新
ZLSwiftRefresh - 下拉刷新/上拉加载更多,支持自定义动画,集成简单
GearRefreshControl - 一个非常精细的下拉刷新 做的很细心
refresher - 简洁清爽的下拉刷新
PullToBounce - 弹性动画 非常炫酷的下拉刷新
RCTRefreshControl qq的橡皮糖下拉刷新
PullToRefresh 刷新动画可定制的下拉数据请求更新组件
MLSwiftBasic 集合自定义导航栏、下拉刷新/上拉加载更多、视觉效果、好用分类等等一系列,却耦合性很低的Swift库!

图片选择、浏览 (这部分swift库真少呀 欢迎知道的补充)

PhotoBrowser-swift 图片浏览
PhotoPicker swift图片选择
BSImagePicker 这个图片选择 不错,oc和swift都有 真贴心呀
KYElegantPhotoGallery - 一个优雅的图片浏览库(可惜OC写的呀。。。。)
CocoaPicker() - 仿 QQ 图片选择器(非swift-_-)。

5、跳转AppStore的两种方法,应用内和直接跳转
#import "ViewController.h"
#import 
@interface ViewController ()
 
@end
 
@implementation ViewController
 
- (void)viewDidLoad {
    [super viewDidLoad];
    //第一种方法  直接跳转
    UIButton *btn = [[UIButton alloc]initWithFrame:CGRectMake(100, 100, 100, 50)];
    btn.backgroundColor = [UIColor redColor];
    [btn setTitle:@"直接跳转" forState:UIControlStateNormal];
    btn.tag = 1;
    [btn addTarget:self action:@selector(btn:) forControlEvents:UIControlEventTouchUpInside];
    //第二中方法  应用内跳转
    UIButton *btnT = [[UIButton alloc]initWithFrame:CGRectMake(100, 300, 100, 50)];
    btnT.backgroundColor = [UIColor purpleColor];
    btnT.tag = 2;
    [btnT setTitle:@"应用内跳转" forState:UIControlStateNormal];
    [btnT addTarget:self action:@selector(btn:) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:btn];
    [self.view addSubview:btnT];
}
- (void)btn:(UIButton *)btn{
    if (btn.tag == 1) {
        //第一种方法  直接跳转
        [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"itms-apps://itunes.apple.com/app/id1018221712"]];
    }else{
        //第二中方法  应用内跳转
        //1:导入StoreKit.framework,控制器里面添加框架#import 
        //2:实现代理SKStoreProductViewControllerDelegate
        SKStoreProductViewController *storeProductViewContorller = [[SKStoreProductViewController alloc] init];
        storeProductViewContorller.delegate = self;
//        ViewController *viewc = [[ViewController alloc]init];
//        __weak typeof(viewc) weakViewController = viewc;
         
        //加载一个新的视图展示
        [storeProductViewContorller loadProductWithParameters:
         //appId
         @{SKStoreProductParameterITunesItemIdentifier : @"1018221712"} completionBlock:^(BOOL result, NSError *error) {
             //回调
             if(error){
                 NSLog(@"错误%@",error);
             }else{
                 //AS应用界面
                 [self presentViewController:storeProductViewContorller animated:YES completion:nil];
             }
         }];
    }
     
}
#pragma mark - 评分取消按钮监听
//取消按钮监听
- (void)productViewControllerDidFinish:(SKStoreProductViewController *)viewController{
    [self dismissViewControllerAnimated:YES completion:nil];
}
5、mac 设置文件夹权限
sudo chmod -R 777 xxx(文件夹)
6、单元测试常用的断言
XCTFail(format…) 生成一个失败的测试;

XCTAssertNil(a1, format...)为空判断,a1为空时通过,反之不通过;

XCTAssertNotNil(a1, format…)不为空判断,a1不为空时通过,反之不通过;

XCTAssert(expression, format...)当expression求值为TRUE时通过;

XCTAssertTrue(expression, format...)当expression求值为TRUE时通过;

XCTAssertFalse(expression, format...)当expression求值为False时通过;

XCTAssertEqualObjects(a1, a2, format...)判断相等,[a1 isEqual:a2]值为TRUE时通过,其中一个不为空时,不通过;

XCTAssertNotEqualObjects(a1, a2, format...)判断不等,[a1 isEqual:a2]值为False时通过;

XCTAssertEqual(a1, a2, format...)判断相等(当a1和a2是 C语言标量、结构体或联合体时使用, 判断的是变量的地址,如果地址相同则返回TRUE,否则返回NO);

XCTAssertNotEqual(a1, a2, format...)判断不等(当a1和a2是 C语言标量、结构体或联合体时使用);

XCTAssertEqualWithAccuracy(a1, a2, accuracy, format...)判断相等,(double或float类型)提供一个误差范围,当在误差范围(+/-accuracy)以内相等时通过测试;

XCTAssertNotEqualWithAccuracy(a1, a2, accuracy, format...) 判断不等,(double或float类型)提供一个误差范围,当在误差范围以内不等时通过测试;

XCTAssertThrows(expression, format...)异常测试,当expression发生异常时通过;反之不通过;(很变态) XCTAssertThrowsSpecific(expression, specificException, format...) 异常测试,当expression发生specificException异常时通过;反之发生其他异常或不发生异常均不通过;

XCTAssertThrowsSpecificNamed(expression, specificException, exception_name, format...)异常测试,当expression发生具体异常、具体异常名称的异常时通过测试,反之不通过;

XCTAssertNoThrow(expression, format…)异常测试,当expression没有发生异常时通过测试;

XCTAssertNoThrowSpecific(expression, specificException, format...)异常测试,当expression没有发生具体异常、具体异常名称的异常时通过测试,反之不通过;

XCTAssertNoThrowSpecificNamed(expression, specificException, exception_name, format...)异常测试,当expression没有发生具体异常、具体异常名称的异常时通过测试,反之不通过

7、IOS 3D touch帖子

1、iOS9新特性 3DTouch 开发教程全解(含源码)

2、iOS9:预览特定的 UITableViewCell 视图

8、检测键盘

检测键盘

 ///监听键盘
        NotificationCenter.default.addObserver(self, selector: #selector(keyBoardWillShow(_:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(keyBoardWillHide(_:)), name: NSNotification.Name.UIKeyboardWillHide, object: nil)

移除监听

deinit {
        //移除通知
        NotificationCenter.default.removeObserver(self)
    }

监听的方法

//键盘的出现
    func keyBoardWillShow(_ notification: Notification){
        //获取userInfo
        let kbInfo = notification.userInfo
        //获取键盘的size
        let kbRect = (kbInfo?[UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue
        //键盘的y偏移量
        let changeY = kbRect.origin.y - screenHeight
        //键盘弹出的时间
        let duration = kbInfo?[UIKeyboardAnimationDurationUserInfoKey] as! Double
        
        //界面偏移动画
        UIView.animate(withDuration: duration) {
            
            self.sc.transform = CGAffineTransform(translationX: 0, y: changeY)
        }
    }
    
    //键盘的隐藏
    func keyBoardWillHide(_ notification: Notification){
        
        let kbInfo = notification.userInfo
//        let kbRect = (kbInfo?[UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue
//        let changeY = kbRect.origin.y
        let duration = kbInfo?[UIKeyboardAnimationDurationUserInfoKey] as! Double
        
        UIView.animate(withDuration: duration) {
            self.sc.transform = CGAffineTransform(translationX: 0, y: 0)
        }
    }
9、 iOS开发 - swift通过Alamofire实现https通信

转载iOS开发 - swift通过Alamofire实现https通信
本文信息来源于 不错的一个网址

实现了OC的https,那么swift的https怎么来写呢,实际上,两者实现没有什么差别,只是对应代码转化成swift的模式,偶然想到这个问题,但是又懒得自己去写,所以在网上找了下,于是发现了上面的网址,swift通过Alamofire实现https,由于之前遇到太多垃圾代码,为了保证这里的代码切实可行,遂通过实战来进行检验:
https双向验证:

import UIKit
import Alamofire
class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        //认证相关设置
        let manager = SessionManager.default
        manager.delegate.sessionDidReceiveChallenge = { session, challenge in
            //认证服务器证书
            if challenge.protectionSpace.authenticationMethod
                == NSURLAuthenticationMethodServerTrust {
                print("服务端证书认证!")
                let serverTrust:SecTrust = challenge.protectionSpace.serverTrust!
                let certificate = SecTrustGetCertificateAtIndex(serverTrust, 0)!
                let remoteCertificateData
                    = CFBridgingRetain(SecCertificateCopyData(certificate))!
                let cerPath = Bundle.main.path(forResource: "server", ofType: "cer")!
                let cerUrl = URL(fileURLWithPath:cerPath)
                let localCertificateData = try! Data(contentsOf: cerUrl)

                if (remoteCertificateData.isEqual(localCertificateData) == true) {

                    let credential = URLCredential(trust: serverTrust)
                    challenge.sender?.use(credential, for: challenge)
                    return (URLSession.AuthChallengeDisposition.useCredential,
                            URLCredential(trust: challenge.protectionSpace.serverTrust!))

                } else {
                    return (.cancelAuthenticationChallenge, nil)
                }
            }
                //认证客户端证书
            else if challenge.protectionSpace.authenticationMethod
                == NSURLAuthenticationMethodClientCertificate {
                print("客户端证书认证!")
                //获取客户端证书相关信息
                let identityAndTrust:IdentityAndTrust = self.extractIdentity();

                let urlCredential:URLCredential = URLCredential(
                    identity: identityAndTrust.identityRef,
                    certificates: identityAndTrust.certArray as? [AnyObject],
                    persistence: URLCredential.Persistence.forSession);

                return (.useCredential, urlCredential);
            }
                // 其它情况(不接受认证)
            else {
                print("其它情况(不接受认证)")
                return (.cancelAuthenticationChallenge, nil)
            }
        }

        //数据请求
        Alamofire.request("请求地址")
            .responseString { response in
                print(response)
        }
    }

    //获取客户端证书相关信息
    func extractIdentity() -> IdentityAndTrust {
        var identityAndTrust:IdentityAndTrust!
        var securityError:OSStatus = errSecSuccess

        let path: String = Bundle.main.path(forResource: "client", ofType: "p12")!
        let PKCS12Data = NSData(contentsOfFile:path)!
        let key : NSString = kSecImportExportPassphrase as NSString
        let options : NSDictionary = [key : "xxxxxxxxxxx"] //客户端证书密码
        //create variable for holding security information
        //var privateKeyRef: SecKeyRef? = nil

        var items : CFArray?

        securityError = SecPKCS12Import(PKCS12Data, options, &items)

        if securityError == errSecSuccess {
            let certItems:CFArray = items as CFArray!;
            let certItemsArray:Array = certItems as Array
            let dict:AnyObject? = certItemsArray.first;
            if let certEntry:Dictionary = dict as? Dictionary {
                // grab the identity
                let identityPointer:AnyObject? = certEntry["identity"];
                let secIdentityRef:SecIdentity = identityPointer as! SecIdentity!
                print("\(identityPointer)  :::: \(secIdentityRef)")
                // grab the trust
                let trustPointer:AnyObject? = certEntry["trust"]
                let trustRef:SecTrust = trustPointer as! SecTrust
                print("\(trustPointer)  :::: \(trustRef)")
                // grab the cert
                let chainPointer:AnyObject? = certEntry["chain"]
                identityAndTrust = IdentityAndTrust(identityRef: secIdentityRef,
                                                    trust: trustRef, certArray:  chainPointer!)
            }
        }
        return identityAndTrust;
    }


//定义一个结构体,存储认证相关信息
struct IdentityAndTrust {
    var identityRef:SecIdentity
    var trust:SecTrust
    var certArray:AnyObject
}

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


}

接着需要配置plist,这里的配置和OC是一样的:

20170112112625149.jpeg

配置好之后运行项目,可拿到请求结果。

https单向验证,验证服务器通过服务器的域名和IP地址来验证,服务器验证客户端证书和密码:

import UIKit

import Alamofire

class ViewController: UIViewController {

    //自签名网站地址
    let selfSignedHosts = ["域名","IP地址"]

    override func viewDidLoad() {
        super.viewDidLoad()

        //认证相关设置
        let manager = SessionManager.default
        manager.delegate.sessionDidReceiveChallenge = { session, challenge in
            //认证服务器(这里不使用服务器证书认证,只需地址是我们定义的几个地址即可信任)
            if challenge.protectionSpace.authenticationMethod
                == NSURLAuthenticationMethodServerTrust
                && self.selfSignedHosts.contains(challenge.protectionSpace.host) {
                print("服务器认证!")
                let credential = URLCredential(trust: challenge.protectionSpace.serverTrust!)
                return (.useCredential, credential)
            }
                //认证客户端证书
            else if challenge.protectionSpace.authenticationMethod
                == NSURLAuthenticationMethodClientCertificate {
                print("客户端证书认证!")
                //获取客户端证书相关信息
                let identityAndTrust:IdentityAndTrust = self.extractIdentity();

                let urlCredential:URLCredential = URLCredential(
                    identity: identityAndTrust.identityRef,
                    certificates: identityAndTrust.certArray as? [AnyObject],
                    persistence: URLCredential.Persistence.forSession);

                return (.useCredential, urlCredential);
            }
                // 其它情况(不接受认证)
            else {
                print("其它情况(不接受认证)")
                return (.cancelAuthenticationChallenge, nil)
            }
        }

        //数据请求
        Alamofire.request("https://xxxxxxxxx")
            .responseString { response in
                print(response)
        }
    }

    //获取客户端证书相关信息
    func extractIdentity() -> IdentityAndTrust {
        var identityAndTrust:IdentityAndTrust!
        var securityError:OSStatus = errSecSuccess

        let path: String = Bundle.main.path(forResource: "client", ofType: "p12")!
        let PKCS12Data = NSData(contentsOfFile:path)!
        let key : NSString = kSecImportExportPassphrase as NSString
        let options : NSDictionary = [key : "xxxxxxxxxxx"] //客户端证书密码
        //create variable for holding security information
        //var privateKeyRef: SecKeyRef? = nil

        var items : CFArray?

        securityError = SecPKCS12Import(PKCS12Data, options, &items)

        if securityError == errSecSuccess {
            let certItems:CFArray = items as CFArray!;
            let certItemsArray:Array = certItems as Array
            let dict:AnyObject? = certItemsArray.first;
            if let certEntry:Dictionary = dict as? Dictionary {
                // grab the identity
                let identityPointer:AnyObject? = certEntry["identity"];
                let secIdentityRef:SecIdentity = identityPointer as! SecIdentity!
                print("\(identityPointer)  :::: \(secIdentityRef)")
                // grab the trust
                let trustPointer:AnyObject? = certEntry["trust"]
                let trustRef:SecTrust = trustPointer as! SecTrust
                print("\(trustPointer)  :::: \(trustRef)")
                // grab the cert
                let chainPointer:AnyObject? = certEntry["chain"]
                identityAndTrust = IdentityAndTrust(identityRef: secIdentityRef,
                                                    trust: trustRef, certArray:  chainPointer!)
            }
        }
        return identityAndTrust;
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
}

//定义一个结构体,存储认证相关信息
struct IdentityAndTrust {
    var identityRef:SecIdentity
    var trust:SecTrust
    var certArray:AnyObject
}

同样,这里也需要配置plist,和上面双向验证是一样的。而下面这样也是可以的。

NSAppTransportSecurity

    NSAllowsArbitraryLoads
    

10、字符串和字典互转

// MARK: - 字典拓展
extension Dictionary {
    /// 转成字json符串
    ///
    /// - Returns: json字符串
    func ls_toJSONString() -> String? {
        if let data = try? JSONSerialization.data(withJSONObject: self, options: JSONSerialization.WritingOptions(rawValue: 0)) {
            if let json = String(data: data, encoding: String.Encoding.utf8) {
                return json
            }
        }
        return nil
    }
    /// 转成base64字符串
    ///
    /// - Returns: base64字符串
    func ls_toBase64String() -> String? {
        let dataStr : String = self.ls_toJSONString()!
        print(dataStr)
        let dataStrstr = dataStr as NSString
        let base64Str = dataStrstr.base64Encoded()  //需要base64类
        return base64Str
    }
}
extension String{
    /// 将字符串转成字典
    var ls_toDic : Dictionary? {
        var returnData : Dictionary? = nil
        let dataWeb: Data = self.data(using: String.Encoding.utf8 , allowLossyConversion: false)!
        if let json : AnyObject = try? JSONSerialization.jsonObject(with: dataWeb, options: JSONSerialization.ReadingOptions.allowFragments) as AnyObject {
            if((json as AnyObject).count != 0 && (json as AnyObject).count != nil ){
                returnData = json as? Dictionary
            }
        }
        return returnData!
    }
}

11、HmacSHA256加密算法

//  
//  HmacUtils.m  
//  Inspector  
//  
//  Created by yaoliangjun on 16/5/20.  
//  Copyright © 2016年 yaoliangjun. All rights reserved.  
//  
  
#import "HmacUtils.h"  
#import   
#import   
  
@implementation HmacUtils  
  
/** 
 *  加密方式,MAC算法: HmacSHA256 
 * 
 *  @param plaintext 要加密的文本 
 *  @param key       秘钥 
 * 
 *  @return 加密后的字符串 
 */  
+ (NSString *)hmac:(NSString *)plaintext withKey:(NSString *)key  
{  
    const charchar *cKey  = [key cStringUsingEncoding:NSASCIIStringEncoding];  
    const charchar *cData = [plaintext cStringUsingEncoding:NSASCIIStringEncoding];  
    unsigned char cHMAC[CC_SHA256_DIGEST_LENGTH];  
    CCHmac(kCCHmacAlgSHA256, cKey, strlen(cKey), cData, strlen(cData), cHMAC);  
    NSData *HMACData = [NSData dataWithBytes:cHMAC length:sizeof(cHMAC)];  
    const unsigned charchar *buffer = (const unsigned charchar *)[HMACData bytes];  
    NSMutableString *HMAC = [NSMutableString stringWithCapacity:HMACData.length * 2];  
    for (int i = 0; i < HMACData.length; ++i){  
        [HMAC appendFormat:@"%02x", buffer[i]];  
    }  
      
    return HMAC;  
}  
  
@end  

图片预览

图片预览
)

你可能感兴趣的:(IOS 日常随笔)