紧急求助,非大神不能解决,APNS 苹果关闭魅族自带应用通知通知问题

OpenAPI发出推送请求后,请求到达移动推送系统,将该推送请求发到苹果APNs,由苹果的APNs最终推送到终端设备。虚线部分为推送系统模块,APNs&终端设备链路,由苹果自行维护。若收到通知有延迟,可以按下面步骤排查:...
iOS App迁移到另一开发者账号,操作流程和注意事项,参考苹果官方文档-Transferring and Deleting Apps。App迁移后,BundleId保持不变,推送证书...(推送证书用于服务端和苹果APNs建连鉴权,不影响APNs到终端的链路)
iOS通知推送,走苹果APNs通道,本身区分开发环境和生产环境。参考:OpenAPI的推送高级接口,设置iOSApnsEnv参数选择推送模式。
通知通过苹果APNs长连通道发送(非自建长连通道);iOS设备启动后,自动建立该APNs长连通道;在iOS设备设置中可选择关闭对应App的通知,可将该长连通道关闭,使通知无法送达;【注意】iOS消息通道的在线/离线状态和...
如果您在iOS关机后进行推送,苹果APNS只会保留最后一条推送信息。即当您重新开机后您只会收到最后一条推送信息。
iOS的通知是通过APNs中心来发送的,需要填写对应的环境信息。'DEV':表示开发环境 'PRODUCT':表示生产环境 pushRequest.setIOSRemind(true);消息推送时设备不在线(既与移动推送的服务端的长连接通道不通),则这条推...
移动推送的“通知”走的是APNs,需要您配置正确的苹果相关推送证书才行,而“消息”走的是移动推送提供的应用内通道,所以不需要苹果一整套的证书。遇到这种情况,请检查您的证书相关配置。
推送包括消息和通知,区别参考:移动推送 iOS...iOS通知,通过苹果APNs通道下发,理论上国内外用户都可以正常使用。iOS消息,通过应用内自建通道下发,服务器布点在国内,国外用户使用时有可能受网络限制,依情况而定。
向APNs注册,获取deviceToken [application registerForRemoteNotifications];} else { not granted NSLog(@"User denied notification.");} }];应修改为: [_notificationCenter requestAuthorizationWithOptions: ...
deviceToken为iOS设备向APNs注册推送通知服务时,返回的设备标识符,请不要同deviceId混淆。获取到deviceToken后,可调用registerDevice 接口上报deviceToken到推送服务器,在上报成功回调中可获取到转换后的...
取得APNS通知内容 NSDictionary*aps=[userInfo valueForKey:@"aps"];内容 NSString*content=[aps valueForKey:@"alert"];badge数量 NSInteger badge=[[aps valueForKey:@"badge"]integerValue];播放声音 NSString*...
未解决问题?到论坛提问试试吧!
你可能感兴趣苹果推送通知服务(APNs)编程 - CSDN博客
苹果推送通知服务(APNs)编程
iPhone 对于应用程序在后台运行有诸多限制(除非你越狱)。因此,当用户切换到其他程序后,原先的程序无法保持运行状态。对于那些需要保持持续连接状态的应用程序(比如社区网络应用),将不能收到实时的信息。
为解决这一限制,苹果推出了APNs(苹果推送通知服务)。APNs 允许设备与苹果的推送通知服务器保持常连接状态。当你想发送一个推送通知给某个用户的iPhone上的应用程序时,你可以使用 APNs 发送一个推送消息给目标设备上已安装的某个应用程序。
本文中,你将学到创建使用 APNs 的iOS 应用的详细步骤。
创建证书请求
使用APNs 的第一步是生成一个证书请求,使用该证书请求来申请一个用于开发的 SSL 证书。
1. 打开“钥匙串访问”应用程序。
2. 选择“KeychainAccess -& Certificate Assistant -& Request a Certificate From CertificateAuthority”(如图1 所示):
3. 输入所需的信息,勾选“Saved to disk”选项,点击 Continue(如图2 所示):
4. 使用默认文件名把证书请求进行保存(图3):在弹出窗口中,点击Done。
创建 App ID
每个使用 APNs 的 iOS 应用必须有一个唯一的 App ID。在本步骤中,你将学到如何创建推送通知中要用到的App ID。
1. 登录iPhoneDeveloper Program:。点击页面右边的“ iPhone Developer Program Portal ”(图4):
2. 首先看到的是欢迎页面(图5):
3. 点击左边的“App ID”,然后点击右边的“New App ID”按钮(图6):
4. 在 Description 栏输入“PushAppID”,在“Bundle Seed ID”栏中选择“Generate New”。在“Bundle Identifier”栏,输入“net.learn2develop.MyPushApp”,然后点击“Submit”(图7):
5. 现在你应该能看到所创建的 App ID 了(图8):
一旦创建了 App ID,你还要为推送通知对 App ID 进行一些配置。
1. 点击App ID 右边的 Configure 链接,会看到如下选项(图9):
勾选“Enable for Apple Push Notificationservice”,点击“Development Push SSL Certificate”右边的“Configure”按钮。
2. 接下来你会看到“Apple Push Notification service SSL Certificate Assistant”页面。点击Continue(图10):
3. 点击Choose File 按钮,选择前面保存的证书请求文件存放地址。点击 Generate(图11):
4. 你的SSL 证书会被生成。点击 Continue(图12):
5. 点击Download Now 按钮,下载 SSL 证书。点击 Done(图13):
6. 下载的 SSL 证书文件名为 aps.developer.identity.cer。双击,将证书安装到钥匙串中(图14)。这个证书会在你的程序中用到,它允许程序接收 APNs 发送来的推送通知。
创建 Provisioning Profile
接下来,需要创建 provisioning profile 以便允许应用程序安装到真实设备上。
1. 回到iPhone Development Program Portal,点击 Provisioning 栏,点击 New Profile 按钮(图15):
2. Profile Name 栏输入 MyDevicesProfile,在 App ID 栏选择 PushAppID。在Devices 栏,勾选所有你想激活的设备(在 iPhone Developer Program Portal 的 Devices 页中注册的所有设备)。点击 Submit(图16)。
3. provisioning& profile 会等待审核。几秒钟后,它会显示在页面上。点击Download 按钮下载该 provisioning profile(图17):
4. 下载下来的provisioning profile 名为 MydevicesProfile.mobileprovision。
创建 provision profile 后,你可以将它安装到真实设备中。
1. 将iPhone 或 iPod 连接到 Mac。
2. 把下载下来的 MyDevicesProfile.mobileprovision 文件拖到Dock 栏的 Xcode 图标上。
3. Xcode 的 Organizer 程序将启动,选择当前连机的设备。可以看到MyDevicesProfile 已自动安装到设备上了(图18)。
创建 iPhone 应用程序
1. 打开Xcode,创建 View-Based Application 项目,命名为 ApplePushNotification。
2. 把一个 WAV 文件(本例是 beep.wav)拖到Xcode 的 Resouces 文件夹(图19)。
3. 展开Xcode 中的 Targets 项目,选择ApplePushNotification,按下 ?+i,在 info 出口,点击Properties 标签栏(图20):
在 Identifier 文本框,输入net.learn2develop.MyPushApp.
4. 点击 Build 标签栏,在 search 输入框中键入Code Signing。在 Any iPhone OS Device 选项,选择正确的 profile(图21):
5. 在 ApplePushNotificationAppDelegate.m 文件中,输入以下代码(加粗部分):
#import &ApplePushNotificationAppDelegate.h&
#import &ApplePushNotificationViewController.h&
@implementation ApplePushNotificationAppDelegate
@synthesize viewC
- (void)applicationDidFinishLaunching:(UIApplication*)application {&&&
&&&[window addSubview:viewController.view];
&&&[window makeKeyAndVisible];
&&& NSLog(@&Registeringfor push notifications...&);&&&
&&& [[UIApplication sharedApplication]
&&&&&&&registerForRemoteNotificationTypes:
&&&&&&& (UIRemoteNotificationTypeAlert |
&&&&&&&&UIRemoteNotificationTypeBadge |
&&&&&&&&UIRemoteNotificationTypeSound)];
- (void)application:(UIApplication*)appdidRegisterForRemoteNotificationsWithDeviceToken:(
*)deviceToken {
&&&&&&&stringWithFormat:@&Device Token=%@&,deviceToken];
&&& NSLog(str);
- (void)application:(UIApplication*)appdidFailToRegisterForRemoteNotificationsWithError:(
*str = [stringWithFormat:
@&Error: %@&, err];
&&& NSLog(str);&&&
- (void)application:(UIApplication*)application didReceiveRemoteNotification:(
*)userInfo {
&&& for (id key in userInfo) {
&&&&&&&NSLog(@&key: %@, value: %@&, key, [userInfo objectForKey:key]);
- (void)dealloc {
&&&[viewController release];
&&&[window release];
&&&[super dealloc];
6. 按下 ?+R 运行程序(在真实设备)。按下 shift+?+R 显示Debugger Console 窗口。查看设备输出到控制台的 device token(图22)。在下图,device token 是 38c866dd bb323b39 ffaee5 a85e0b7c e90d56e9fe145bcc 6c2c594b。记下device token(复制、粘贴到一个文本文件里)
7. 如果查看 iPhone/iPod 上的“Settings”程序,你会发现一个 Notifications 的项(图23):
创建 Push Notification Provider
Push Notification Provider 是一个应用程序,用于通过 APNs 发送推送通知给 iPhone 应用。
通过 APNs 发送推送通知有几个步骤:
1. 使用前面创建的 SSL 证书与 APNs 通讯;
2. 构造所要发送的消息载体;
3. 发送载体到APNs;
APNs 是一个基于流的 TCP socket,你的 provider 以 SSL 协议与其通讯。推送通知(包括载体)是以二进制流的方式发送的。和APNs 建立连接后,你可以维持该连接并在连接中断之前发送多个通知。
技巧: 应避免每发送一次推送通知就建立、关闭一次连接。频繁的建立、关闭连接可能会被 APNs 认为是 DOS 攻击,从而拒绝发送 provider 的推送通知发送请求。
一个推送通知消息的格式如图24 所示:
更多细节,请参考 。
载体(payload)是 JSON 字符串(最长 256 字节),封装了你发送给 iOS 应用的信息。这是一个 payload 的例子:
&&&&aps&: {
&&&&&&& &alert& : &Yougot a new message!& ,
&&&&&&& &badge& : 5,
&&&&&&& &sound& : &beep.wav&},
&&&&&acme1& : &bar&,
&&&&&acme2& : 42
写provider之前,我们需要生成php Push Notification sender需要的证书文件:
& 1)在Keychain Access.app里选定这个新证书(Apple Development Push Services*),导出到桌面,保存为Certificates.p12.
& 2)然后运行如下命令:
&& 1.&&&& openssl pkcs12 -clcerts -nokeys -out cert.pem -in Certificates.p12
&& 2.&&&& openssl pkcs12 -nocerts -out key.pem -in Certificates.p12
&& 3.&&&& openssl rsa -in key.pem -out key.unencrypted.pem
& &4.&&&& cat cert.pem key.unencrypted.pem & ck.pem
下面是一个简单的push notification proivder写法:
$deviceToken = '38c866dd bb323b39 ffaee5 a85e0b7ce90d56e9 fe145bcc 6c2c594b'; // masked for security reason
// Passphrase for the private key (ck.pem file)
// $pass = '';
// Get the parameters from http get or from command line
$message = $_GET['message'] or $message = $argv[1] or $message = 'Message received from javacom';
$badge = (int)$_GET['badge'] or $badge = (int)$argv[2];
$sound = $_GET['sound'] or $sound = $argv[3];
// Construct the notification payload
$body = array();
$body['aps'] = array('alert' =& $message);
if ($badge)
$body['aps']['badge'] = $
if ($sound)
$body['aps']['sound'] = $
/* End of Configurable Items */
$ctx = stream_context_create();
stream_context_set_option($ctx, 'ssl', 'local_cert', 'ck.pem');
// assume the private key passphase was removed.
// stream_context_set_option($ctx, 'ssl', 'passphrase', $pass);
$fp = stream_socket_client('ssl://gateway.sandbox.:2195', $err, $errstr, 60, STREAM_CLIENT_CONNECT, $ctx);
if (!$fp) {
print &Failed to connect $err $errstrn&;
print &Connection OKn&;
$payload = json_encode($body);
$msg = chr(0) . pack(&n&,32) . pack('H*', str_replace(' ', '', $deviceToken)) . pack(&n&,strlen($payload)) . $
print &sending message :& . $payload . &n&;
fwrite($fp, $msg);
fclose($fp);
运行结果:Connection OKnsending message :{&aps&:{&alert&:&Message received from javacom&}}n
效果图在下面。
为了省去自己编写 push notification provider 的麻烦,你也可以使用 Stefan Hafeneger 写的一个 Mac OS X 应用程序:PushMeBaby,
1. 在Xcode 中打开 PushMeBaby。
2. 右击 Resouces 文件夹,选择 Add Existing Files…,选择前面所下载到的aps.developer.identity.cer 文件(图25)。
3. 在 ApplicationDelegate.m 文件中,修改如下代码(加粗部分):
- (id)init {
&&&self = [super init];
&&&if(self != nil) {
&&&&&&&self.deviceToken = @&38c866dd bb323b39 ffaee5 a85e0b7ce90d56e9 fe145bcc 6c2c594b&;
&&&&&&& self.payload = @&{\&aps\&:{\&alert\&:\&Yougot a new message!\&,\&badge\&:5,\&sound\&:\&beep.wav\&},\&acme1\&:\&bar\&,\&acme2\&:42}&;
&&&&&&&self.certificate = [[
mainBundle]
&&&&&&&&&&&pathForResource:@&aps_developer_identity& ofType:@&cer&];
4. 按下 ?+R,运行程序。将会问你是否允许使用证书,点击Always Allow(总是允许)(图26):
在 iPhone/iPod,确认 ApplePushNotification 程序未运行。点击 Push 按钮,会向设备发送一条推送通知。服务器实际上发送了下列消息给APN 服务器:
&&&&aps&: {
&&&&&&& &alert& : &Yougot a new message!& ,
&&&&&&& &badge& : 5,
&&&&&&& &sound& : &beep.wav&},
&&&&&acme1& : &bar&,
&&&&&acme2& : 42
5. 如果消息推送成功,将会在 iPhone/iPod 上出现下图(图27):
6. 如果现在按下 ?+R 调试 ApplePushNotification 程序,然后从 PushMeBaby 中发送一条消息,控制台会显示如下输出:
21:11:49.182 ApplePushNotification[]key: acme1, value: bar
21:11:49.187 ApplePushNotification[]key: aps, value: {
&&&alert = &You got a new message!&;
&&&badge = 5;
&&&sound = &beep.wav&;
21:11:49.191 ApplePushNotification[]key: acme2, value: 42
几个注意的问题:
1.如果申请ssl 证书时不是用的新的apple id,而是原来已经存在的,那么设置好之后要把对应的provisioning profile
也更新一下, 然后去下载新的profile替换掉老的,不然运行会有错。
2.如果你用的是企业版的开发者证书,别人可能没有权限去申请这个ssl 证书,当你替他申请好证书后,应该把证书和证书对
的私钥一起发给他,这样他在本地安装私钥时才会有对应的密钥。
3.当push notification到达时,程序状态不同,效果也是不一样的,一般来说程序可以分为下面三种状态:
1)程序不在运行(后台和前台都不在运行)
这时候如果push notification到了,会弹出一个alertview,当你点击action按钮时,会启动程序,并执行程序delegate.m文件里的
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
方法,所以你可以在这里做一些处理:
//看是否有push notification到达,并做相应处理,这个方法和local notification相同,但注意key要对应就行
UILocalNotification * remoteNotification = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
if (remoteNotification) {
//弹出一个alertview,显示相应信息
UIAlertView * al = [[UIAlertView alloc]initWithTitle:@&receive remote notification!& message:@&hello& delegate:self cancelButtonTitle:@&Ok& otherButtonTitles:nil, nil];
[al show];
[al release];
2)程序在运行(不论是在前台还是后台)
当push notification到达时,如果程序在前台运行并不会弹出alertview,而是直接执行下面方法:
* Remote Notification Received while application was open.
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
UIAlertView * al = [[UIAlertView alloc]initWithTitle:@&receive remote notification!& message:@&hey& delegate:self cancelButtonTitle:@&ok& otherButtonTitles:nil, nil];
[al show];
[al release];
在这个方法里你可以获取到userInfo字典来进行相应处理。
如果程序是在后台运行,则会弹出一个alertview,当你点击action按钮,也会执行上面一样的方法。
所以如果你想要程序在push notification到达时,针对前台和后台运行做区分处理,你可以在上面方法里先做一个状态的
判断: //可以根据application状态来判断,程序当前是在前台还是后台
UIApplicationState state = [application applicationState];
if (state == UIApplicationStateInactive) {
// Application was in the background when notification
// was delivered.
原文链接:
本文已收录于以下专栏:
相关文章推荐
来自http://blog.csdn.net/lifengzhong/article/details/7737028#
苹果信息推送服务(Apple Push Notification ...
Shell基础之控制流结构
一、控制结构
几乎所有的脚本里都有某种流控制结构,很少有例外。流控制是什么?假定有一个脚本,包含下列几个命令:
# make a di...
转载请标明出处:
http://blog.csdn.net/forezp/article/details/
本文出自方志朋的博客
在上一篇文章,讲了服务的注册和发现。在服...
1.查找当前目录中所有大于500M的文件,把这些文件名写到一个文本文件中,并统计其个数。
find ./ -size +500M -type f | tee file_list | wc -l还可使...
NSPredicate 用于指定过滤条件,主要用于从集合中分拣出符合条件的对象,也可以用于字符串的正则匹配。
NSPredicate常用方法介绍
1.创建NSPredicate(相当于创建一个过滤条件...
在前一篇文章中我们介绍了OC中一个重要技术通知:http://blog.csdn.net/jiangwei/article/details/,今天我们在来看一下OC...
简述:Cocoa框架中的NSPredicate用于查询,原理和用法都类似于SQL中的where,作用相当于数据库的过滤取。
定义(最常用到的方法):
[cpp] vie...
可以实现可通过汉字,拼音,拼音首字母,拼音中间字母进行搜索的搜索栏。
+ (NSString *)getPinyinWithString:(NSString *)string{
...
他的最新文章
讲师:宋宝华
讲师:何宇健
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)君,已阅读到文档的结尾了呢~~
苹果推送通知服务开发。
扫扫二维码,随身浏览文档
手机或平板扫扫即可继续访问
APNS苹果推送通知服务开发文档 Apple Push Notification Service
举报该文档为侵权文档。
举报该文档含有违规或不良信息。
反馈该文档无法正常浏览。
举报该文档为重复文档。
推荐理由:
将文档分享至:
分享完整地址
文档地址:
粘贴到BBS或博客
flash地址:
支持嵌入FLASH地址的网站使用
html代码:
&embed src='/DocinViewer-4.swf' width='100%' height='600' type=application/x-shockwave-flash ALLOWFULLSCREEN='true' ALLOWSCRIPTACCESS='always'&&/embed&
450px*300px480px*400px650px*490px
支持嵌入HTML代码的网站使用
您的内容已经提交成功
您所提交的内容需要审核后才能发布,请您等待!
3秒自动关闭窗口关于iOS一些常见知识点解析 - 简书
关于iOS一些常见知识点解析
常见问题收集
孙源前百度现在滴滴打车, 唐巧, 叶孤城, YYKit郭曜源
MVC的目的是为了把数据(Model)和视图(View)分离开来,然后用控制器(Controller)负责调节两者之间的关系。也就是让专业的对象做专业的事情,View就只负责视图相关的东西,Model就只负责描述数据模型,Controller负责调节两者之间的关系。
MVC在核心通讯上基于推送/订阅模型,当一个model变化时它对应用其它模块发出更新通知(“publishes” ),订阅者 (subscriber)——通常是一个Controller,然后更新对应的view。观察者——这种自然的观察关系促进了多个view关联到同一个 model。
就是在其中一个view中包含了view和model,
其目的就是给vc减负
id和instancetype的区别
相同点: 都可以作为方法的返回类型
区别: 1.id只能返回未知类型,
而instancetype返回所在类对象类型;
2. instancetype不能作为参数类型, 而id可以
ios是一门可以把确定数据类型的时机从编译推迟到运行时的语言, 属于纯C语言的API
1.在程序运行过程中, 动态创建一个类(比如KVO的底层实现)
2. 在程序运行过程中, 动态地为某个类添加属性\方法, 修改属性值\方法
runloop是事件接收和分发机制的一个实现,当启动一个子线程,如果只是处理单一的线程,在事件处理完后就会退出,但是当我们需要让该线程随即监听某项事物,就得让线程一直存在,runloop就是优化后的死循环,每一个线程都有一个runloop,主线程中的runloop是默认开启的,子线程需要手动调用开启,当事件源没有传入的时候当前线程就会进入休眠状态,当事件源传入的时候runloop才会循环一次。runloop循环一次会使引用对象的计数-1,当计数变为0的时候对象就会释放掉。
NSDefaultRunLoopMode触碰就停止, 主线程默认此模式
UITrackingRunLoopMode 触碰屏幕才开始循环, 界面跟踪模式,
NSRunLoopCommonModes 一直在循环, 占位模式,
不是一个真正的模式
对于NSString *obj = [NSData alloc]
init]; 编译和运行时是什么状态
编译时是前者,运行时时是后者
______block和___weak修饰符的区别
____block对象在block中是可以被修改的,重新赋值的, ______block对象不会在block中被强引用一次,从而不会出现循环引用的问题
使用了____weak的对象作用等同于定义为weak的property对象,是不会导致循环引用的问题,苹果官方文档已经说明了当原对象没有任何强引用的时候,弱引用指针也会被置为nil.
1.__block不管是ARC还是MRC模式下都可以使用,可以修饰对象,还可以修饰基本数据类型。
2.__weak只能在ARC模式下使用,也只能修饰对象(NSString),不能修饰基本数据类型(int)。
3.______block对象可以在block中被重新赋值,___weak不可以。
如何解决tableview的cell卡顿问题
1使用不透明视图,
2.不要重复创建不必要的cell,
3减少视图的数目,
4.不要做多余的绘制工作
5.不可以阻塞主线程,所有刷新UI操作都是要到主线程中去的。
tableview优化,
1.不用xib铺界面,
2.在model缓存高度,
3.预估高度,
4.不在协议方法赋值,
用setter方法进行赋值,
不要给控件设置圆角, draw rect或者铺两个图
6.使用cell factory
core data是对sqlite进行的封装,
但是执行效率sqlite比较高
常用设计模式
单例模式:整个项目只有只需要创建一次的类,而且自行实例化并向整个系统提供这个实例,单例也被称为懒汉模式或恶汉模式, 数据库, 当然有数据库也就有coredata,
音频, 视频,
应用场景:当做数据缓存时 创建的datamanage就是单例,反向传值--优势:使用简单,易于跨模块
+(instancetype)shareManage{
static databaseManage *manage =
static dispatch_once_t onceT
dispatch_once(&oncetoken,^{
manage = [[databaseManage alloc]init];
好处: 节省资源, 一个应用就一个对象
注意: 一旦不小心销毁了单例,
再调用生成方法是不会被创建的, 而且单例一旦被创建, 整个app都不会释放, 这会占用内存, 因此不可滥用单例
观察者模式
是定义对象间的一种一对多的依赖关系,并且当一个对象的状态发生改变的时候,所有依赖于它的对象都会得到通知且自动更新。
缺点: 代码可读性很差,
而且搜索通知时系统是全局逐行搜索, 运行效率低
a)先在苹果推送服务器APNs上注册devicetoken ,返回给后台服务器
b)后台服务器将devicetoken和要发送的消息打包给APNs(需要在开发者中心注册推送证书)
c)APNs将消息发送给devicetoken上保存的指定的设备的app上。
APP发布到APPStore上的流程
a)首先到苹果官网购买开发者账号,分为企业和个人版本
b)在开发者中心注册开发者证书和发布证书,如需推送,同时也要注册推送证书,将p12装到电脑上
c)注册APP IDs和真机调试
接着注册调试 ——创建发布的配置文件
d)在itunces connectent 中心创建好应用并填写相关信息
e)在xcode中将项目打包并上传(boundle id 要一致,先在building setting 里填写创建好的配置文件,发布证书)
f)回到content 中选择填好的项目上传点击提交审核(无法构建版本的情况下需要重新打包上传)
GET和POST的区别
Http定义了与服务器交互的不同方法,最基本的方法有4种,分别是GET,POST,PUT,DELETE 对应着对这个资源查, 改, 增, 删
所以GET一般用于获取/查询 资源信息,而POST一般用于更新 资源信息
再进一步了解下他们两个的区别:
1. GET使用URL或Cookie传参。而POST将数据放在BODY中
2. GET的URL会有长度上的限制,则POST的数据则可以非常大。
3. POST比GET安全,因为数据在地址栏上不可见。
简述SDWebImageView的实现原理
1.首先显示placeholderImage,然后sdWebImageManager根据URL开始处理图片
2.根据你提供的URL,去本地查找是否用对应这个URL的文件,如果有,就直接读取本地数据,如果没有,就发送网络请求(用MD5生成32位的固定)
3.开启一个子线程,在子线程当中使用异步请求的方式向服务器索取数据
4.下载完图片后进行解码处理,在主线程中宣告解码完成,回调给sdWebImageManager告知图片下载完成,在需要的地方展示图片,图片加载到UI之上,并且根据URL的字符串名字按一定的方式生成一个文件命名,保存到本地
SDWebImageView 是否有清除缓存的功能,如果没有,你如何实现?
有sdImageCache在内存警告或者退到后台的时候清理内存图片缓存,应用结束清理过期图片。遍历缓存文件夹,删除所有缓存文件
[[SDImageCache sharedImageCache] clearDisk];
AFNetworking 原理
AFNetworking的第一个重大突破就是将NSURLConnection 、NSOperation结合。可以从头到尾监视请求的状态,并储存请求、响应、响应数据等中间状态。
AFN 的基础部分是 AFURLConnectionOperation,一个 NSOperation subclass,实现了 基于NSURLConnection 相关的delegate+blocks,网络部分是由 NSURLConnection 完成,然后利用 NSOperation 的 state (isReady→isExecuting→isFinished) 变化来进行网络控制。网络请求是在一个指定的线程(networkRequestThread)完成。
AFURLConnectionOperation是一个很纯粹的网络请求 operation,可以对他进行 start/cancel/pause/resume 操作,可以获取对应的 NSURLRequest 和 NSURLResponse 数据。支持 NSInputStream/NSOutputStream,提供了 uploadPress 和downloadProgress 以方便其他使用。
AFHTTPRequestOperation是 AFURLConnectionOperation 的子类,针对 HTTP+HTTPS 协议做了一层封装,比如statusCode、Content-Type 等,添加了请求成功和失败的回调 block,提供了addAcceptableContentTypes: 以方便上层使用。
contentOffset, contentInset, contentSize
contentSize是scrollview可以滚动的区域,比如frame = (0 ,0 ,320 ,480) contentSize = (320 ,960),代表你的scrollview可以上下滚动,滚动区域为frame大小的两倍。
contentOffset是scrollview当前显示区域顶点相对于frame顶点的偏移量,比如上个例子你拉到最下面,contentoffset就是(0 ,480),也就是y偏移了480
contentInset是scrollview的contentview的顶点相对于scrollview的位置,例如你的contentInset = (0 ,100),那么你的contentview就是从scrollview的(0 ,100)开始显示
进程和线程区别
进程就是一个应用程序在处理机上的一次执行过程,它是一个动态的概念,而线程是进程中的一部分,进程包含多个线程在运行。
多线程框架
单线程—针对线程直接控制的,手动开启, 是三种方法里面相对轻量级的,但需要管理线程的生命周期、同步、加锁问题,这会导致一定的性能开销
NSOperation(NSOperation是抽象父类,不能直接使用子类NSblockinvation和nsinvocationoperation)
需手动创建线程,还需创建队列,无回调(断点续传用到)
主要是操作队列
主队列(主线程) 子队列(子线程)
NSOperation 是对GCD 一个封装
要解决GCD的一些遗留问题
自动创建线程,不需手动管理周期,有回调,方便,但不能取消。
大的调度中心
主要是操作队列
主队列 子队列
GCD一旦开启一个子线程,就无法停止
任务队列做线程管理,把创建好的任务直接放到线程中,以任务为中心,GCD是nsoperation的底层实现
什么是串行队列 — 队列里的任务是按先后顺序依次有序的执行
什么是并发队列 — 队列里的任务是同时执行的
多线程如何优化执行效率
如何保证线程安全
[NSLock lock]
信号量self(标志位),如果信号量已经存在,则该线程锁正在使用当中,其他线程无法进入锁内代码
@synchronized(self){ }
static dispatch_once_
dispatch_once(&one, ^{
dispatch_async(dispatch_queue_t queue, dispatch_block_t block);
除了async,还有sync,delay,
async表明异步运行,block代表的是你要做的事情,queue则是你把任务交给谁来处理了
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSURL * url = [NSURL URLWithString:@"http://avatar.csdn.net/2/C/D/1_totogo2010.jpg"];
NSData * data = [[NSData alloc]initWithContentsOfURL:url];
UIImage *image = [[UIImage alloc]initWithData:data];
if (data != nil) {
//回归主线程
dispatch_async(dispatch_get_main_queue(), ^{
self.imageView.image =
------------我是分割线----------------------------------
系统默认就有一个串行队列main_queue和全局队列global_queue(也是并行队列)
举个例子, globalQ和mainQ这俩名字随便起
1.dispatch_queue_t globalQ = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
2.dispatch_queue_t mainQ = dispatch_get_main_queue();
通常,我们可以在global_queue中做一些long-running的任务,完成后在main_queue中更新UI,避免UI阻塞,无法响应用户操作:
Serial queue有FIFO特性, 即first in first out
验证Serial queue的FIFO特性
NSDate *da = [NSDate date];
NSString *daStr = [da description];
const char *queueName = [daStr UTF8String];
dispatch_queue_t myQueue = dispatch_queue_create(queueName, DISPATCH_QUEUE_SERIAL);
dispatch_async(myQueue, ^{
[NSThread sleepForTimeInterval:6];
NSLog(@"[NSThread sleepForTimeInterval:6];");
dispatch_async(myQueue, ^{
[NSThread sleepForTimeInterval:3];
NSLog(@"[NSThread sleepForTimeInterval:3];");
dispatch_async(myQueue, ^{
[NSThread sleepForTimeInterval:1];
NSLog(@"[NSThread sleepForTimeInterval:1];");
//在MRC需要释放
dispatch_release(myQueue);
16:37:14.397
NSThreadAndBlockDemo[] [NSThread sleepForTimeInterval:6];
16:37:17.399
NSThreadAndBlockDemo[] [NSThread sleepForTimeInterval:3];
16:37:18.401
NSThreadAndBlockDemo[] [NSThread sleepForTimeInterval:1];
验证Concurrent queue(global dispatch queue)
dispatch_queue_t myQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(myQueue, ^{
[NSThread sleepForTimeInterval:6];
NSLog(@"[NSThread sleepForTimeInterval:6];");
dispatch_async(myQueue, ^{
[NSThread sleepForTimeInterval:3];
NSLog(@"[NSThread sleepForTimeInterval:3];");
dispatch_async(myQueue, ^{
[NSThread sleepForTimeInterval:1];
NSLog(@"[NSThread sleepForTimeInterval:1];");
dispatch_release(myQueue);
16:38:41.660
NSThreadAndBlockDemo[] [NSThread sleepForTimeInterval:1];
16:38:43.660
NSThreadAndBlockDemo[] [NSThread sleepForTimeInterval:3];
16:38:46.660
NSThreadAndBlockDemo[] [NSThread sleepForTimeInterval:6];
dispatch_group_async的使用
dispatch_group_async可以实现监听一组任务是否完成,完成后得到通知执行其他的操作。这个方法很有用,比如你执行三个下载任务,当三个任务都下载完成后你才通知界面说完成的了
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, queue, ^{
[NSThread sleepForTimeInterval:6];
NSLog(@"group1 [NSThread sleepForTimeInterval:6];");
dispatch_group_async(group, queue, ^{
[NSThread sleepForTimeInterval:3];
NSLog(@"group2 [NSThread sleepForTimeInterval:3];");
dispatch_group_async(group, queue, ^{
[NSThread sleepForTimeInterval:1];
NSLog(@"group3 [NSThread sleepForTimeInterval:1];");
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(@"main thread.");
dispatch_release(group);
16:48:23.063
NSThreadAndBlockDemo[] group3 [NSThread sleepForTimeInterval:1];
16:48:25.063
NSThreadAndBlockDemo[] group2 [NSThread sleepForTimeInterval:3];
16:48:28.063
NSThreadAndBlockDemo[] group1 [NSThread sleepForTimeInterval:6];
16:48:28.065
NSThreadAndBlockDemo[] main thread.
dispatch_barrier_async的使用
dispatch_barrier_async是在前面的任务执行结束后它才执行,而且它后面的任务等它执行完成之后才会执行
dispatch_queue_t queue = dispatch_queue_create("gcdtest.rongfzh.yc", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
[NSThread sleepForTimeInterval:3];
NSLog(@"dispatch_async1");
dispatch_async(queue, ^{
[NSThread sleepForTimeInterval:1];
NSLog(@"dispatch_async2");
dispatch_barrier_async(queue, ^{
NSLog(@"dispatch_barrier_async");
[NSThread sleepForTimeInterval:0.5];
dispatch_async(queue, ^{
[NSThread sleepForTimeInterval:1];
NSLog(@"dispatch_async3");
17:01:54.580 NSThreadAndBlockDemo[]
dispatch_async2
17:01:56.580 NSThreadAndBlockDemo[]
dispatch_async1
17:01:56.580 NSThreadAndBlockDemo[]
dispatch_barrier_async
17:01:58.083 NSThreadAndBlockDemo[]
dispatch_async3
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
会发现运行结果为:
17:07:17.577 NSThreadAndBlockDemo[]
dispatch_barrier_async
17:07:18.579 NSThreadAndBlockDemo[]
dispatch_async3
17:07:19.578 NSThreadAndBlockDemo[]
dispatch_async2
17:07:20.577 NSThreadAndBlockDemo[]
dispatch_async1
dispatch_apply
执行某个代码片段N次。
dispatch_apply(5, globalQ, ^(size_t index) {
// 执行5次
dispatch_once
dispatch_once这个函数,它可以保证整个应用程序生命周期中某段代码只被执行一次!单例!
static dispatch_once_t onceT
dispatch_once(&onceToken, ^{
// code to be executed once
+ (instancetype)sharedViewController{
static ViewController *vc =
//输入dispatch
//只运行一次
static dispatch_once_t onceT
dispatch_once(&onceToken, ^{
vc = [[ViewController alloc] init];
dispatch_after
有时候我们需要等个几秒钟然后做个动画或者给个提示,这时候可以用dispatch_after这个函数:
double delayInSeconds = 2.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
// code to be executed on the main queue after delay
dispatch_set_target_queue
通过dispatch_set_target_queue函数可以设置一个dispatch queue的优先级,或者指定一个dispatch source相应的事件处理提交到哪个queue上。
dispatch_set_target_queue(serialQ, globalQ);
---------------------至此GCD的部分结束------------------
互斥锁使用格式
@synchronized(锁对象) { // 需要锁定的代码
注意:锁定1份代码只用1把锁,用多把锁是无效的
OC在定义属性时有nonatomic和atomic两种选择
atomic:原子属性,为setter方法加锁(默认就是atomic), 但是需要消耗大量CPU资源
nonatomic:非原子属性,不会为setter方法加锁, 适合内存小的移动设备(常用)
atomic加锁原理:
@property (assign, atomic)
- (void)setAge:(int)age
@synchronized(self) {
我写了个模拟售票的demo叫"试着总结线程锁"
可以这么理解,
异步是为了在复杂操作过程中还可以干别的事情,
别如加载图片过程中用户可以继续滑动看别的东西
而加同步锁是为了避免一些必要的逻辑顺序错误,
比如点击图片,
如果在加载过程中能够双击,
那么就会返回错误,
这时就需要加同步锁.
然而. 滥用@synchronized()会降低代码效率,因为共用同一个锁的同步块,都必须按顺序执行。若是在对象上频繁加锁,那么程序可能要等另一段与此无关的代码执行完毕,才能继续执行当前代码,这样做会造成没有必要的损耗。
另一种方法是NSLock
- (void)synchronizedMethod{
[_lock lock];
[_lock unlock];
也可以使用NSRecursiveLock这种“递归锁”,线程能够多次持有该锁,而不会出现死锁现象。
这两种方法都不错,但是依然有缺陷,在极端情况下,同步块会导致死锁,还有效率也不高,
(这个网站写的不错,
用五个案例分析GCD死锁)
dispatch_async(queue,block)
async 异步队列,dispatch_async 函数会立即返回, block会在后台异步执行。
dispatch_sync(queue,block)
sync 同步队列,dispatch_sync 函数不会立即返回,及阻塞当前线程,等待 block同步执行完成。所以dispatch_sync 在主线程调用就会造成死锁
线程间的通讯
ios性能优化:
1. 不用xib铺界面, 不要给控件设置圆角, 用draw rect或者两张图用中间透明 四周白色的图片覆盖
2.在model缓存高度,
3.预估高度,
4.不在协议方法赋值,
用setter方法进行赋值,
5.在线程中使用 autoreleasepool
imageNamed与imageWithContentsOfFile
imageNamed默认加载图片成功后会内存中缓存图片,这个方法用一个指定的名字在系统缓存中查找并返回一个图片对象.如果缓存中没有找到相应的图片对象,则从指定地方加载图片然后缓存对象,并返回这个图片对象.
而imageWithContentsOfFile则仅只加载图片,不缓存.
大量使用imageNamed方式会在不需要缓存的地方额外增加开销CPU的时间来做这件事.当应用程序需要加载一张比较大的图片并且使用一次性,那么其实是没有必要去缓存这个图片的,用imageWithContentsOfFile是最为经济的方式,这样不会因为UIImage元素较多情况下,CPU会被逐个分散在不必要缓存上浪费过多时间.
deep copy和shallow copy
深拷贝和浅拷贝
浅拷贝:简单的指针复制,新指针和旧指针指向同一内存地址
深拷贝:新指针和旧指针指向不同的内存区域,新指针是一个新的对象,新对象改变了对旧对象没有任何影响.
1.如果对一个不可变对象复制,copy是指针复制,即浅拷贝,返回不可变对象;而mutableCopy则是对象复制,即深拷贝,返回的为可变对象。
2.如果对一个可变对象复制,始终是深拷贝。
协议代理模式
1)出现的原因 :
因为OC是不支持多继承的,所以很多时候都是用Protocol(协议)来代替。Protocol(协议)只能定义公用的一套接口,但不能提供具体的实现方法
2)必须使用weak修饰, 否则在双向代理中,会造成双向强引用.
OC的三大特性
封装: 将文件中具有相同方法的代码抽离出来,提供一个api接口供程序使用
继承: 子类可以继承父类的成员变量和方法,主要体现在代码重用,节省开发时间
多态:同一个操作作用域不同的对象,可以有不同的解释,产生不同的效果,在运行时可以指向基类的指针,产生派生类的方法。
MRC下检测内存泄露的工具
Instruments工具
协议, block, 通知, 和单例(不推荐经常使用)
协议: 一对一
通知: 一对多
耦合性高低排布
协议代理-&block-&通知中心
运行效率高低排布
block-&协议代理-&通知中心
通知可读性差,
且系统运行时需要从头到尾搜索每一行代码, 不要滥用通知
UIView和CALayer之间的关系
UIView是CALayer的一个载体,UIView显示的部分,都是由CALayer来负责的,其实UIView最重要的功能不是用于显示内容,它主要作用是用于管理它所渲染区域的内部的各种事件.
UIView是继承自UIResponder,所以它可以响应事件.
如果AFNetworking不能使用了,使用MKNetWork第三方库框架替代它
视图控制器的生命周期
alloc init(执行一次)——loadView(只执行一次)——viewDidLoad—viewWillAppear—viewDidAppear—viewWillDisAppear—viewDidDisAppear——viewUnload —dealloc
程序生命周期
lifeCycle[] willFinishLaunchingWithOptions
lifeCycle[] didFinishLaunchingWithOptions
lifeCycle[] applicationDidBecomeActive
按下home键
lifeCycle[] applicationWillResignActive
lifeCycle[] applicationDidEnterBackground
双击home键,再打开程序
lifeCycle[] applicationWillEnterForeground
lifeCycle[] applicationDidBecomeActive
#include和#import的区别@class
include是c/c++导入头文件的关键字,#import 是oc导入头文件的关键字, #import 可以防止头文件重复导入,#import需要导入foundation框架,@class 告诉编译器有某一个类的存在,当执行时才会去查看类的实现文件,可以解决头文件的相互包含
写一个标准宏计算A和B较大的值
define MAX(A,B)((A)&(B)?(A):(B))

我要回帖

更多关于 苹果微信通知声音更改 的文章

 

随机推荐