一.一个项目的开始搭建
1.工具类的文件可以直接用之前项目的。
二.Cocopod导入需要的库。
cd 项目位置
然后添加podfile文件:vim podfile (注:在写该文件的时候要注意格式 ' ' );
进入后按i进入插入模式,进行编辑,安装官方最新的文档格式:
platform :ios, '8.0'
target '你的项目名称' do
pod 'AFNetworking', '~> 3.0'
end
编辑完成后,按ESC退出编辑模式,最后输入:wq保存并退出文件,此时可以发现在项目目录下多了一个Podfile的文件,请注意这个文件必须与.xcodeproj在同一目录下,
最后:pod install进行安装即可
三.基础页面的搭建。
1.基类的viewcontroller,基类的WKWebViewController.
四.与后台对接接口。
/**
*发送get请求
*
*@param url url
*@param params发送的参数
*@param success成功回调
*@param failure失败回调
*/
+ (void)get:(NSString*)url params:(nullableNSDictionary*)params showHud:(BOOL)showHudsuccess:(void(^)(id__nullablejson))success failure:(void(^)(NSError*error))failure{
// 1.创建请求管理者}
AFHTTPSessionManager*mgr = [AFHTTPSessionManagermanager];
//mgr.responseSerializer = [AFHTTPResponseSerializer serializer];
mgr.requestSerializer= [AFHTTPRequestSerializerserializer];
//添加证书
[mgrsetSecurityPolicy:[QWAFSecurityPolicycustomSecurityPolicy]];
mgr.requestSerializer.timeoutInterval=30;
mgr.responseSerializer.acceptableContentTypes= [NSSetsetWithObjects:@"application/json",@"text/json",@"text/xml",@"text/plain",@"text/html",@"image/png",nil];
[mgrGET:urlparameters:paramsprogress:^(NSProgress*_NonnulldownloadProgress) {
}success:^(NSURLSessionDataTask*_Nonnulltask,id_NullableresponseObject) {
if(showHud) {
[hudhideAnimated:YES];
}
if(success) {
//NSString *online = [NSString stringWithFormat:@"%@",responseObject[@"online"]];
//[QWAccountModel sharedModel].isOnline = [online boolValue];
success(responseObject);
}
}failure:^(NSURLSessionDataTask*_Nullabletask,NSError*_Nonnullerror) {
if(showHud) {
[hudhideAnimated:YES];
}
//[MBProgressHUD hideHUD];
//[TJShowMessage showMessage:@"网络异常,请重新加载"];
//[[NSNotificationCenter defaultCenter] postNotificationName:TJReloadDataFailedNotification object:nil];
if(failure) {
failure(error);
}
}];
+ (void)postmanager:(NSString*)url params:(NSDictionary*)params success:(void(^)(idmanager,idjson))success failure:(void(^)(
NSError*error))failure{
AFHTTPSessionManager*mgr = [AFHTTPSessionManagermanager];
mgr.requestSerializer= [AFHTTPRequestSerializerserializer];
//添加证书
[mgrsetSecurityPolicy:[QWAFSecurityPolicycustomSecurityPolicy]];
mgr.requestSerializer.timeoutInterval=30;
mgr.responseSerializer.acceptableContentTypes= [NSSetsetWithObjects:@"application/json",@"text/json",@"text/xml",@"text/plain",@"text/html",nil];
[mgrPOST:urlparameters:paramsprogress:nilsuccess:^(NSURLSessionDataTask*_Nonnulltask,id_NullableresponseObject) {
if(success) {success(task, responseObject);
}
}failure:^(NSURLSessionDataTask*_Nullabletask,NSError*_Nonnullerror) {
if(failure) {failure(error);
}
加密验签。
//生成sign
+ (NSString*)getSignAndSignDict:(NSMutableDictionary*)dict
{
NSMutableDictionary*dic = [NSMutableDictionarydictionaryWithDictionary:dict];
[dicsetValue:VersionforKey:@"version"];
[dicsetValue:[CommonFunctime]forKey:@"timeStamp"];
[dicsetValue:PtforKey:@"pt"];
[dicsetValue:ImeiforKey:@"imei"];
NSString*singstr = [selfsortDicToString:dic];
returnsingstr;
}
//排序验签
+ (NSString*) sortDicToString:(NSMutableDictionary*)dic{
//排序
NSMutableArray*stringArray = [NSMutableArrayarrayWithArray:dic.allKeys];
[stringArraysortUsingComparator: ^NSComparisonResult(NSString*str1,NSString*str2) {
return[str1compare:str2];
}];
//验签
NSString*md5StrPre =@"";
for(inti =0; i < [stringArraycount]; i++) {
NSString*key = [stringArrayobjectAtIndex:i];
md5StrPre = [md5StrPrestringByAppendingString:[dicobjectForKey:key]];
}
NSString*getKey =QWKey;
md5StrPre = [md5StrPrestringByAppendingString:getKey];
NSString*md5Str = [QWCommonFuncmd5:md5StrPre];
returnmd5Str;
}
五.MVC模式搭界面。
六.登录分享。
1.很多公司都是用H5页面直接调取登录注册。这里主要说一下第三方登录。
Cocopod导入shareSDK或者直接在官网拖入导入(但是要手动添加一些依赖库)。
- (instancetype)init
{
if(self= [superinit])
{
self.users= [NSMutableArrayarray];
//将已授权用户加入列表
[[SSEThirdPartyLoginHelperusers]enumerateKeysAndObjectsUsingBlock:^(idkey,SSEBaseUser*obj,BOOL*stop) {
[self.usersaddObject:obj];
}];
}
returnself;
}
[ShareSDKregisterApp:QWShareKey
activePlatforms:@[
@(SSDKPlatformTypeSinaWeibo),
@(SSDKPlatformTypeWechat),
@(SSDKPlatformTypeQQ),]
onImport:^(SSDKPlatformTypeplatformType)
{
switch(platformType)
{
caseSSDKPlatformTypeWechat:
[ShareSDKConnectorconnectWeChat:[WXApiclass]delegate:self];
break;
//case SSDKPlatformSubTypeQZone:
caseSSDKPlatformTypeQQ:
[ShareSDKConnectorconnectQQ:[QQApiInterfaceclass]tencentOAuthClass:[TencentOAuthclass]];
break;
caseSSDKPlatformTypeSinaWeibo:
[ShareSDKConnectorconnectWeibo:[WeiboSDKclass]];
break;
default:
break;
}
}
onConfiguration:^(SSDKPlatformTypeplatformType,NSMutableDictionary*appInfo)
{
switch(platformType)
{
caseSSDKPlatformTypeSinaWeibo:
//设置新浪微博应用信息,其中authType设置为使用SSO+Web形式授权
[appInfoSSDKSetupSinaWeiboByAppKey:SinaAppid
appSecret:SinaAppsecret
redirectUri:@""
authType:SSDKAuthTypeBoth];
break;
caseSSDKPlatformTypeWechat:
[appInfoSSDKSetupWeChatByAppId:WXAppid
appSecret:WXAppsecret];
break;
caseSSDKPlatformTypeQQ:
[appInfoSSDKSetupQQByAppId:QQAppid
appKey:QQAppsecret
authType:SSDKAuthTypeBoth];
break;
default:
break;
}
以上是分享和登录的KEY注册。
[SSEThirdPartyLoginHelper loginByPlatform:SSDKPlatformTypeSinaWeibo
onUserSync:^(SSDKUser*user,SSEUserAssociateHandlerassociateHandler) {
onLoginResult:^(SSDKResponseStatestate,SSEBaseUser*user,NSError*error) {
}];
分享需要注意的是:
微博和微信朋友圈的分享需要特别分清。
NSMutableDictionary*shareParams = [NSMutableDictionarydictionary];
[shareParamsSSDKEnableUseClientShare];
//定制微博的分享内容
[shareParamsSSDKSetupSinaWeiboShareParamsByText:[NSStringstringWithFormat:@"%@%@",[QWStringUtilsconvertNullString:content],[NSURLURLWithString:url]]title:[QWStringUtilsconvertNullString:title]image:imageArrayurl:[NSURLURLWithString:url]latitude:0longitude:0objectID:niltype:SSDKContentTypeAuto];
//定制微信朋友圈的分享内容
[shareParamsSSDKSetupWeChatParamsByText:[NSStringstringWithFormat:@"%@",[QWStringUtilsconvertNullString:content]]title:[QWStringUtilsconvertNullString:title]url:[NSURLURLWithString:url]thumbImage:nilimage:imageArraymusicFileURL:nilextInfo:nilfileData:nilemoticonData:niltype:SSDKContentTypeAutoforPlatformSubType:SSDKPlatformSubTypeWechatTimeline];
[shareParamsSSDKSetupShareParamsByText:[NSStringstringWithFormat:@"%@%@",[QWStringUtilsconvertNullString:content],[NSURLURLWithString:url]]
images:imageArray
url:[NSURLURLWithString:url]
title:[QWStringUtilsconvertNullString:title]
type:SSDKContentTypeAuto];
系统的分享UI界面
[ShareSDKshowShareActionSheet:nil
items:typeArr
shareParams:shareParams
onShareStateChanged:^(SSDKResponseStatestate,SSDKPlatformTypeplatformType,NSDictionary*userData,SSDKContentEntity*contentEntity,NSError*error,BOOLend) {
switch(state) {
caseSSDKResponseStateSuccess:
{
[QWShowMessageshowToastmsg:@"分享成功"toView:controller.view];
break;
}
caseSSDKResponseStateFail:
{
[QWShowMessageshowToastmsg:@"分享失败"toView:controller.view];break;
}caseSSDKResponseStateCancel: {
[QWShowMessageshowToastmsg:@"分享取消"toView:controller.view];
break;
}
default:
break;
}
}
];
自定义分享界面
这个可以自己写一个View。(用tableview或者collection)(也可以写成button的点击)
__blocktypeof(self)weakSelf =self;
[ShareSDKshare:[dict[@"shareType"]intValue]parameters:shareParamsonStateChanged:^(SSDKResponseStatestate,NSDictionary*userData,SSDKContentEntity*contentEntity,NSError*error) {
switch(state) {
caseSSDKResponseStateSuccess:
{
[weakSelfshareSuccessMsg];
Log(@"分享成功!");
break;
}
caseSSDKResponseStateFail:
{
[TJShowMessageshowToast:self.superViewmsg:@"分享失败"];
TJLog(@"---%@",error.description);
break;
}
caseSSDKResponseStateCancel: {
break;
}
default:
break;
}];
如何判断是否登录成功了呢?
还有如何下次启动不在输入密码,自动登录呢?
那么我们需要AccountModel单例和LoginTool。
当然我们也需要归档和解档。来判断是否登录。记录是否有账号和密码。但是这种有一个缺点,如果我们卸载了该应用然后在安装,就不会有登录的记录。很多程序是记录的手机UDID,传给后台,一一对应。
实现归档中的 encodeWithCoder 和 initWithCoder方法
//www.greatytc.com/p/98ce827931c7
+ (void)saveAccount:(AccountModel*)model
{
[NSKeyedArchiverarchiveRootObject:modeltoFile:AccountPath];//归档
}
+ (AccountModel*)loadAccount
{
AccountModel*model = [NSKeyedUnarchiverunarchiveObjectWithFile:AccountPath];
returnmodel;
}
if(![QWLoginToolisLogin]) {
[selfpresentViewController:[QWLoginToollogin]animated:YEScompletion:nil];
return;
}
判断是否登录。
七.支付
1.支付宝支付。
2.微信支付。
3.银联支付。
4.京东支付。
5.苹果内购支付。
关于苹果内购支付的思路。
1.证书。
五个证书。两个p12证书(一个development开发者,一个distribution发布者),三个描述文件(一个development开发描述真机测试,一个distribution发布APP描述文件,一个distribution_adhoc打包测试证书)。
2.流程
1、Get Set of Product IDs内购商品信息最好存放到服务器,因为界面的展示都是根据模型显示(将数据放到一个集合里面:NSSet/Web Service)前提是需要将项目在苹果内购后台信息配置好
2、向苹果请求有效的内购商品信息Request Valid Product IDs (苹果可能限制某些商品)怎么请求:SKProductsRequest(创建这个请求)。
3、苹果返回有效的内购商品信息Valid DIs Returned
4、展示购买的选项(展示界面)Display Purchase Options
5、用户开始购买(User Initiates Purchase):选中某个商品,创建票据(SKPayment),将票据加入到交易队列里面(User Works Through Dialogs)
6、监听交易队列交易成功还是失败(添加观察者,遵守协议,实现方法进行回调)。
(代理一对一,观察者一对多)
八.常用的框架
1.Masonry(布局)
2.github.com/forkingdog(流畅的侧滑)
3.WMPageController(好框架)(自己写的话就有些小麻烦,浪费时间。)
4.SDCycleScrollView(广告轮播图)
5.iCarousel-(第一次启动新手引导)
九.封装。优化。
十.上架。
十一.与H5页面交互。
#pragma mark WKUIDelegate
//页面开始加载时调用
-(void)webView:(WKWebView*)webView didStartProvisionalNavigation:(WKNavigation*)navigation{
NSLog(@"开始加载");
}
//内容开始返回时调用
-(void)webView:(WKWebView*)webView didCommitNavigation:(WKNavigation*)navigation{
NSLog(@"开始返回");
}
//页面加载完成时调用
-(void)webView:(WKWebView*)webView didFinishNavigation:(WKNavigation*)navigation{
NSLog(@"加载完成");
}
//页面加载失败时调用
-(void)webView:(WKWebView*)webView didFailNavigation:(WKNavigation*)navigation withError:(NSError*)error{
NSLog(@"加载失败");
}
- (void)webView:(WKWebView*)webView decidePolicyForNavigationAction:(WKNavigationAction*)navigationAction decisionHandler:(void(^)(WKNavigationActionPolicy))decisionHandler
{
NSString*requestStr = navigationAction.request.URL.absoluteString;
QWLog(@"requestStr==%@",requestStr);
if([requestStrisEqualToString:@""]) {
QWLog(@"获取URL失败");
decisionHandler(WKNavigationActionPolicyCancel);
return;
}
if([requestStrrangeOfString:@"#"].location!=NSNotFound) {
NSArray*arr = [requestStrcomponentsSeparatedByString:@"#"];
requestStr = [arrobjectAtIndex:1];
Log(@"找到带#号的url");
decisionHandler(WKNavigationActionPolicyCancel);
requestStr = [requestStrstringByRemovingPercentEncoding];
NSData*data = [requestStrdataUsingEncoding:NSUTF8StringEncoding];
NSDictionary*dic = [NSJSONSerializationJSONObjectWithData:dataoptions:NSJSONReadingMutableLeaveserror:nil];
QWLog(@"dic = %@",dic);
if([requestStrrangeOfString:@""].location!=NSNotFound) {
}
decisionHandler(WKNavigationActionPolicyAllow);
if(![requestStrhasPrefix:@"http"])
{
decisionHandler(WKNavigationActionPolicyCancel);
return;
}
}