2017.6.20-至今 项目开题,编写基本代码
7.19
- 编写数据库,用于存储用户信息
为数据库设置缓存,提高查询效率
[db setShouldCacheStatements:YES];
事务操作,提高效率 FMDB官方使用文档-GCD的使用-提高性能
[queue inTransaction:^(FMDatabase *db, BOOL *rollback) {
}];
- 禁止UITextField 复制粘贴,选择
创建UITextField的分类,在.m文件中重写以下方法
-(BOOL)canPerformAction:(SEL)action withSender:(id)sender
-(BOOL)canPerformAction:(SEL)action withSender:(id)sender{
if (action == @selector(paste:)) {
return NO; //禁止粘贴
}
if (action == @selector(select:)) {
return NO; //禁止选择
}
if (action == @selector(selectAll:)) {
return NO; //禁止全选
}
return [super canPerformAction:action withSender:sender];
}
7.24
完成头像的裁剪 上传工作
//avatar 特定标识符 后台协定
[formData appendPartWithFileData:data name:@"avatar" fileName:fielName mimeType:@"image/jpeg"];
- 包含内容
扫码登录 签名 证书管理
//老政府机关 么有自己APP 包含注册登录,
7.25
- 扫码登陆的问题
数处对象设置扫描类型的时候,必须先让会话添加输出对象
if ([_session canAddInput:self.input])
{
[_session addInput:self.input];
}
if ([_session canAddOutput:self.output])
{
[_session addOutput:self.output];
}
//扫描类型设置为二维码 _session添加了_output之后,才可以对其进行设置
[_output setMetadataObjectTypes:[NSArray arrayWithObjects:AVMetadataObjectTypeQRCode, nil]];
2.post 发送确认二维码登录的时候,后台一直接收不到参数
几经尝试,发现改为get 问题得到解决
第一种可能,安卓说 有可能是post 是把各种参数直接拼接成一个json字符串发过去了 后台不能看到请求的body 而get 是分出来body的
参考: AJAX POST请求中参数以form data和request payload形式在servlet中的获取方式
第二种情况,由于使用了AFN网络框架,所以post的时候,是以form表单的形式上传,但却不是标准的formdata.所以一般的后台框架或者getpramter方法可能获取不到,必须一层层解析
受教了
7.26
- 报错
Error Domain=NSCocoaErrorDomain Code=3840 "The operation couldn’t be completed. (Cocoa error 3840.)" (JSON text did not start with array or object and option to allow fragments not set.) UserInfo=0x9ba1b30 {NSDebugDescription=JSON text did not start with array or object and option to allow fragments not set.}
解决:
后台返回的不是一个有效的JSON string 所以库里面转化的时候一个error就抛出了
8.1
- 对某两个字符串或者字符串之间的值进行替换
/**
对某两个字符串或者字符串之间的值进行替换
@param originalStr 原始字符串
@param str1 开始的位置字符串
@param str2 结束的位置字符串
@param valueStr 替换的值
@return 新的字符串
*/
+ (NSString *)originalStr:(NSString *)originalStr
exchangeValue:(NSString *)str1
str2:(NSString *)str2
withString:(NSString *)valueStr{
NSRange startRange = [originalStr rangeOfString:str1];
NSRange endRange = [originalStr rangeOfString:str2];
NSRange range = NSMakeRange(startRange.location + startRange.length, endRange.location - startRange.location - startRange.length);
originalStr = [originalStr stringByReplacingCharactersInRange:range withString:valueStr];
return [NSString stringWithString:originalStr];
}
- 研究webservice
- Web Service技术, 能使得运行在不同机器上的不同应用无须借助附加的、专门的第三方软件或硬件, 就可相互交换数据或集成。依据Web Service规范实施的应用之间, 无论它们所使用的语言、 平台或内部协议是什么, 都可以相互交换数据。Web Service是自描述、 自包含的可用网络模块, 可以执行具体的业务功能。Web Service也很容易部署, 因为它们基于一些常规的产业标准以及已有的一些技术,诸如标准通用标记语言下的子集XML、HTTP。Web Service减少了应用接口的花费。Web Service为整个企业甚至多个组织之间的业务流程的集成提供了一个通用机制。
简单来说 webservice 请求就是是往服务器POST XML数据;
然后服务器响应得到的也是XML数据;
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
//假如在这开始请求
NSString *webServiceBodyStr = [NSString stringWithFormat:
@"<Jsjy_yjy xmlns=\"http://murpcn.com/murpwebservice/\">"
"<xxx>34192</xxx>"
"<pagenow>1</pagenow>"
"<pagesize>20</pagesize>"
"</Jsjy_yjy>"];//这里是参数
NSString *webServiceStr = [NSString stringWithFormat:
@"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
"<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">\n"
"<soap:Body>\n"
"%@\n"
"</soap:Body>\n"
"</soap:Envelope>",
webServiceBodyStr];//webService头
NSString *SOAPActionStr = [NSString stringWithFormat:@"http://xxx.com/murpwebservice/%@", @"Jsjy_yjy"];//SOAPAction
NSURL *url = [NSURL URLWithString:@"http://xxxx/key/MurpjsjyService.asmx"];
NSMutableURLRequest *theRequest = [NSMutableURLRequest requestWithURL:url];
NSString *msgLength = [NSString stringWithFormat:@"%ld", webServiceStr.length];
[theRequest addValue:@"text/xml; charset=utf-8" forHTTPHeaderField:@"Content-type"];
[theRequest addValue:SOAPActionStr forHTTPHeaderField:@"SOAPAction"];
[theRequest addValue:msgLength forHTTPHeaderField:@"Content-Length"];
[theRequest setHTTPMethod:@"POST"];
[theRequest setHTTPBody:[webServiceStr dataUsingEncoding:NSUTF8StringEncoding]];
NSURLConnection *theConn = [[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
if (theConn) {
NSLog(@"8888哈哈哈笑");
}else {
NSLog(@"5555你给我哭");
}
}
//接收到数据的代理
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
NSString *str = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(@"%@", str);//得到想要的XML字符串然后解析
//系统自带的
NSXMLParser *par = [[NSXMLParser alloc] initWithData:[str dataUsingEncoding:NSUTF8StringEncoding]];
[par setDelegate:self];//设置NSXMLParser对象的解析方法代理
[par parse];//调用代理解析NSXMLParser对象,看解析是否成功
}
//解析XML
#pragma mark xmlparser
//step 1 :准备解析
- (void)parserDidStartDocument:(NSXMLParser *)parser{
}
//step 2:准备解析节点
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict{
NSLog(@"%@", NSStringFromSelector(_cmd) );
}
//step 3:获取首尾节点间内容
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{
NSLog(@"%@", string);
}
//step 4 :解析完当前节点
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{
NSLog(@"%@",NSStringFromSelector(_cmd) );
}
//step 5;解析结束
- (void)parserDidEndDocument:(NSXMLParser *)parser{
}
//获取cdata块数据
- (void)parser:(NSXMLParser *)parser foundCDATA:(NSData *)CDATABlock{
}
8.3
1.字典转化为字符串
//字典转字符串
+ (NSString *)dictionaryToJson:(NSDictionary *)dic
{
NSError *parseError = nil;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dic options:NSJSONWritingPrettyPrinted error:&parseError];
return [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
}
- 字典转化为键值对(用于拼接get请求的参数)
+ (NSString *)keyValueStrFromJson:(NSDictionary *)dic
{
NSMutableString *string = [[NSMutableString alloc] init];
[dic enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) {
[string appendFormat:@"%@=%@&",key,obj];
if ([key isEqualToString:[dic allKeys].lastObject]) {
[string deleteCharactersInRange:NSMakeRange(string.length-1, 1)];
}
}];
return [string copy];
}
- 系统原生http请求
/*方法的作用:GET 请求
*@param urlStr : 数据请求接口地址
*@param dic : 接口请求数据参数
*@param finish : 数据请求失败的回调
*@param conError : 数据请求失败的回调
*/
+ (void)requestGETWithURLString:(NSString *)urlStr
parDic:(NSDictionary *)dic
finish:(void(^)(id responseObject))finish
conError:(void(^)(NSError *error))conError{
NSURL *url;
if (dic) {
url = [NSURL URLWithString:[NSString stringWithFormat:@"%@?%@",urlStr,[LCXMLPrase keyValueStrFromJson:dic]]];
}else{
url = [NSURL URLWithString:urlStr];
}
NSMutableURLRequest *request = [[NSMutableURLRequest alloc]initWithURL:url];
request.HTTPMethod = @"GET";
request.timeoutInterval = 7.f;
[request setValue:@"text/xml; charset=utf-8" forHTTPHeaderField:@"Content-Type"];
NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
if (finish) {
finish([NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil]);
}
if (error) {
if (conError) {
conError(error);
}
}
}];
[task resume];
}
/*方法的作用:POST 请求
*@param urlStr : 数据请求接口地址
*@param dic : 接口请求数据参数
*@param finish : 数据请求失败的回调
*@param conError : 数据请求失败的回调
*/
+ (void)requestPOSTWithURLString:(NSString *)urlStr
parDic:(NSDictionary *)dic
finish:(void(^)(id responseObject))finish
conError:(void(^)(NSError *error))conError{
NSURL *url = [NSURL URLWithString:urlStr];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc]initWithURL:url];
request.HTTPMethod = @"POST";
request.timeoutInterval = 7.f;
[request setValue:@"text/xml; charset=utf-8" forHTTPHeaderField:@"Content-Type"];
NSData *bodyData = [[LCXMLPrase keyValueStrFromJson:dic] dataUsingEncoding:NSUTF8StringEncoding];
request.HTTPBody = bodyData;
NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
if (finish) {
finish([NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil]);
}
if (error) {
if (conError) {
conError(error);
}
}
}];
[task resume];
}
- 证书申请流程
1. 填写信息,设置密码,保存证书,这个密码是该证书的密码,证书保存在本地,如果删除软件,则证书丢失
8.7 立秋 雨
- 是否是全数字
1.NSScanner类
+ (BOOL)isPureInt:(NSString*)string{
NSScanner * scan = [NSScanner scannerWithString:string];
int val;
return[scan scanInt:&val] && [scan isAtEnd];
}
2.正则判断
- (BOOL) deptNumInputShouldNumber:(NSString *)str
{
NSString *regex = @"[0-9]*";
NSPredicate *pred = [NSPredicate predicateWithFormat:@"SELF MATCHES %@",regex];
if ([pred evaluateWithObject:str]) {
return YES;
}
return NO;
}
- 密码验证,不能连续数字,不能连续相同
+(BOOL) validatePwd:(NSString *)str
{
for (NSInteger i = 1; i < 6;i++) {
int asciiCode1 = [str characterAtIndex:i];
int asciiCode2 = [str characterAtIndex:i - 1];
if (asciiCode1 - asciiCode2 != 1 && asciiCode2 - asciiCode1 != 1 && asciiCode1 - asciiCode2 != 0) {
return YES;
}
}
return NO;
}
8.8 晴天
- 随机数算法 (用于制作随机数键盘)
//产生任意范围内任意数量的随机数(使用此方法)
-(NSArray*)randomDataFromLower:(NSInteger)lower
toHigher:(NSInteger)higher
withQuantity:(NSInteger)quantity{
NSMutableArray *myRandomNumbers=[NSMutableArray array];
if (!quantity||quantity>(higher-lower)+1) {
quantity=(higher-lower)+1;
}
while (myRandomNumbers.count!=quantity) {
NSInteger myNumber=arc4random_uniform((uint32_t)(higher+1-lower))+(uint32_t)lower;
if (![myRandomNumbers containsObject: @(myNumber)]) {
[myRandomNumbers addObject:@(myNumber)];
}
}
return [myRandomNumbers copy];//可变数组变成不可变
}
//直接产生0-9随机数
-(NSArray*)randomData{
NSMutableArray *numberArr=[NSMutableArray arrayWithArray:@[@1,@2,@3,@4,@5,@6,@7,@8,@9,@0]];
NSInteger numberCount=numberArr.count;
NSMutableArray *tmpArr=[NSMutableArray array];
for (NSInteger i=0; i<numberCount; i++) {
NSNumber *number=numberArr[arc4random() % numberArr.count];
[tmpArr addObject:number];
[numberArr removeObject:number];
}
return tmpArr;
}
- 业务流程
手机盾整体业务流程
1. 申请证书,必要条件 appkey(开发平台生成),appid用户标识符,容器名字(拼接而成,保证唯一即可),设置证书密码
2. 申请证书完毕的后续操作,初始化 唤醒容器 ,证书密码需要输入
8.9
- 活体检测
- 方法1 发起app跳转 方法2 接受跳转到的app回调回来,如何把方法2得到的结果 搞到方法1的block中
定义一个block属性(或者全局的block) 把方法1的block 赋值给 这个全局block 方法2回调的时候,得到的结果,传给这个全局的block 即可完成
8.10 秋高气爽 晴天一个
VC还没有显示到windows上面,就去调用,会导致操作失效,比如VC 模态
解决:
[self.window makeKeyAndVisible]; 使其可见
8.14
- sdk自己使用的时候,也需要注册,完善相关的信息
近期在测试项目,测试接口,但是没有进行及时的记录,检讨
8.24 项目问题
- 获取Hash值,初始化成功,hash的时候,报
未知错误
2.本方申请证书,
1. 错误指针不允许被释放
2. 打印到链接SKF,然后崩溃
8.25
- label 设置
numberOfLines = 0
失效,查找原因,发现时没有手动设置字体大小导致的
8.31
新需求
1.对文件进行签名等操作,具体实施:
以二进制流形式读入文件,过大的话分段加密,然后拼接保存
9.4 邮箱开发
待补充
9.5
- PIN码拼接时间戳,传入,保证唯一性
9.18--9.25 临时制证
9.26
适配ios11
if (@available(iOS 11.0, *)) {
_tableView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
//不自动计算内边距
} else {
self.automaticallyAdjustsScrollViewInsets = NO;
}
11.24
可变参数列表
- (void)functionName:(NSString *)string, ...
{
if (string)
{
va_list args;
va_start(args, string);
//第一个元素
NSLog(@"%@",string);
NSString *otherString;
while ((otherString = va_arg(args, NSString *)))
{
//依次取得所有参数(2,3,4)
NSLog(@"%@",otherString);
}
va_end(args);
}
}
2017年总结
2018
4.2
wkwebview 高度自适应
// 页面加载完成之后调用
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation{//这里修改导航栏的标题,动态改变
//self.navigationItem.title = webView.title;
[QMUITips hideAllToastInView:self.view animated:YES];
//
[webView evaluateJavaScript:@"document.body.offsetHeight" completionHandler:^(id _Nullable result, NSError * _Nullable error) {
NSLog(@"%@",result);
CGFloat webViewHeight = ((NSNumber *)result).floatValue;
CGRect newFrame = webView.frame;
newFrame.size.height= webViewHeight;
webView.frame= newFrame;
self.webview.frame = newFrame;
[self.menuView.collectionView reloadData];
}];
}
5.14
tableview 防遮挡
if (@available(iOS 11.0, *)) {
_tableView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
_tableView.estimatedRowHeight = 0;
_tableView.estimatedSectionHeaderHeight = 0;
_tableView.estimatedSectionFooterHeight = 0;
//self.additionalSafeAreaInsets
} else {
// Fallback on earlier versions
self.automaticallyAdjustsScrollViewInsets = NO;
}
此前 self.edgesForExtendedLayout = UIRectEdgeNone;
放在tableview初始化里面是没有问题的,但是最近发现,放在这里,tableview加载完成后,页面tableview会跳动进行调整,如果卡一下的话,直接不跳。 后来试了一下,卸载viewdidload里面,问题解决了
5.31
unsigned char 字符串,转化为NSString类型字符串的方式
unsigned char encD[1024] = "ddjhldjd";
//先转化为data
NSData *adata = [[NSData alloc] initWithBytes:encD length:encL];
//再转化为字符串
NSString *encstrr = [[NSString alloc] initWithData:adata encoding:NSUTF8StringEncoding];
6.20
NSString 和NSData转化base64
NSString *decodeString = @"Raja";
NSData *encodeData = [decodeString dataUsingEncoding:NSUTF8StringEncoding];
NSString *base64String = [encodeData base64EncodedStringWithOptions:0];DLog(@"Encode String Value: %@", base64String);
NSData *decodedData = [[NSData alloc] initWithBase64EncodedString:base64String options:0];
NSString *decodedString = [[NSString alloc] initWithData:decodedData encoding:NSUTF8StringEncoding];
NSLog(@"Decode String Value: %@", decodedString);
7.10
数据类型之间的转换
控制台报错 error can't allocate region
error can't allocate region 程序运行报错,在xcode中则会发出“SIGABRT”信号来终止程序。
原因是程序运行内存不足,欲申请空间得不到分配。
此时可以查找程序是否出现程序一直申请内存,出现死循环.
SIGABRT 程序自己发现错误并调用abort来终止程序.
可能是程序没有内存可分配导致,运行终止.
7.18
删除子view
self.view.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];
8.10
断点调试 po
输出报错:
error: errored out in DoExecute, couldn't PrepareToExecuteJITExpression
这是因为开启了release模式,run 调整为debug模式即可
8.18
char 数组可以转为NSString
char cStrArr[4] = {'1','2','3','4'};
NSString *StrArr = [[NSString alloc]initWithCString:cStrArr encoding:NSASCIIStringEncoding];
8.20
base64字符串
Base64编码说明
Base64编码要求把3个8位字节(3*8=24)转化为4个6位的字节(4*6=24),之后在6位的前面补两个0,形成8位一个字节的形式。 如果剩下的字符不足3个字节,则用0填充,输出字符使用'=',因此编码后输出的文本末尾可能会出现1或2个'='。
为了保证所输出的编码为可读字符,Base64制定了一个编码表,以便进行统一转换。编码表的大小为2^6=64,这也是Base64名称的由来。
Base64编码表
9.20
hash值转化为二进制数据
NSString * input = @"N0YzMTQxMUE2RUMwODVGMDJFMzI2NThBNDc5M0E4Rjc2OEE5OEIyMQ==";
NSData *decdata = [[NSData alloc] initWithBase64EncodedString:input options:0];
将二进制数据转化为byte字节
unsigned char inputData[SignData_LEN] = {0};
//从指针位置截取length,写进byte数组
[data getBytes:inputData length:data.length];
将byte字节转化为二进制数据
unsigned char signData[SignData_LEN] = {0};
unsigned int datL = 0;
...省略中间写进数据的代码
//根据指针位置开始取值,长度为datL,写进data
NSData *data = [[NSData alloc] initWithBytes:signData length:datL];
11.19
最近封装AFN的时候发现在.h文件中总是出现这种警告:
这个东西虽然不影响编译和运行,但看起来总让人不舒服。
为什么会出现这种警告?
我们都知道在swift中,可以使用!和?来表示一个对象是optional的还是non-optional,如view?和view!。而在Objective-C中则没有这一区分,view既可表示这个对象是optional,也可表示是non-optioanl。这样就会造成一个问题:在Swift与Objective-C混编时,Swift编译器并不知道一个Objective-C对象到底是optional还是non-optional,因此这种情况下编译器会隐式地将Objective-C的对象当成是non-optional。
为了解决这个问题,苹果在Xcode 6.3引入了一个Objective-C的新特性:nullability annotations。这一新特性的核心是两个新的类型注释:__nullable和__nonnull。从字面上我们可以猜到,__nullable表示对象可以是NULL或nil,而__nonnull表示对象不应该为空。当我们不遵循这一规则时,编译器就会给出警告。
——摘自会报编译器警告的Xcode 6.3新特性:Nullability Annotations
如何解决这些警告?
根据Xcode的提示一个一个fix?可以但未免太繁琐。苹果为开发者提供了两个宏:
NS_ASSUME_NONNULL_BEGIN
NS_ASSUME_NONNULL_END
在这两个宏里的参数默认不可空,如果想改成可空,可以添加nullable
,如:
- (nullable NSURLSessionDataTask *)GET:(NSString *)URLString
parameters:(nullable id)parameters
progress:(nullable void (^)(NSProgress *downloadProgress))downloadProgress
success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success
failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure;
其中URLString
不可空(默认nonnull
),parameters
和downloadProgress
等用nullable
修饰的可空。
如果给URLString
赋值nil,Xcode会警告: