自己的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是一样的:
配置好之后运行项目,可拿到请求结果。
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
图片预览
图片预览
)