H:/1024/01_本地通知_AppDelegate.m
// AppDelegate.m
// 本地通知
// Created by apple on 13-10-24.
// Copyright (c) 2013年 itcast. All rights reserved.
#import "AppDelegate.h"
@implementation AppDelegate
/**
提示:通知和应用是分别处理的,应用程序调度了通知之后,即便被关掉,
仍然能够在指定的调度时间到来时,触发通知。
通常在使用本地通知时,是在应用程序退出到后台时才调度的。
应用程序退出到后台之后,会在内存中驻留10分钟的时间,过了10分钟之后,
系统会自动清理应用程序,
被完全清理之后,再次运行时,才会调用didFinishLaunchingWithOptions:方法。
且只会执行一次改方法
1. 通常本地通知是在退出应用程序时,被调度的,
在后台往往会做一些后台调度的服务,
譬如
1) 一个联网下棋的软件:
当对手落子后,需要进行检测,检测完成后,
通过本地通知的方式通知用户重新回到应用程序
2) 例如一个新闻客户端,在后台检测最新的数据,当发现数据后,
通知用户,用户进入应用时,直接显示通知的内容
3)未接来电
4)QQ聊天
如果要实现类似的上述功能,可以借助 userInfo 数据字典
要获取到通知的消息,可以在application:didFinishLaunchingWithOptions:
方法中实现
2. UILocalNotification常用属性
fireDate; 通知的触发时间
timeZone; 通知所在时区,如果指定时区,可以自行调整时间
alertBody; 通知的正文
soundName; 通知播放的声音,
如果用UILocalNotificationDefaultSoundName,使用系统默认声音
applicationIconBadgeNumber; 应用程序图标
userInfo; 数据字典,在生成PDF文件时候也用到userInfo
*/
// 下面方法,会在程序首次启动后仅调用一次,
// 当通过点击通知提示进入的程序,字典launchOptions里面才有通知
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// 截获本地通知,只有当用户通过点击通知的横幅进入app,字典中才有本地通知
UILocalNotification *notification =
launchOptions[UIApplicationLaunchOptionsLocalNotificationKey];
// 判断是否存在通知,即是否通过点击通知提示,进入的app
if (notification) {
NSLog(@"%@", notification.userInfo);
[notification.userInfo writeToFile:@"/users/apple/Desktop/123.plist"
atomically:YES];
}
// 下面是固定代码
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen]
bounds]];
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
return YES;
}
#pragma mark - WillEnterForeground即将进入前台,清除app图标右上角数字
- (void)applicationWillEnterForeground:(UIApplication *)application
{
[application setApplicationIconBadgeNumber:0];
}
#pragma mark - DidEnterBackground进入后台
- (void)applicationDidEnterBackground:(UIApplication *)application
{
// 调用自定义方法,创建通知
[self loadNotification];
}
#pragma mark - 创建本地通知
- (void)loadNotification
{
// 实例化一个UILocalNotification对象
UILocalNotification *notification = [[UILocalNotification alloc]init];
// 5秒钟之后触发
notification.fireDate = [NSDate dateWithTimeIntervalSinceNow:5];
notification.alertBody = @"出大事了";
notification.soundName = UILocalNotificationDefaultSoundName;
notification.applicationIconBadgeNumber = 100;
notification.userInfo = @{@"userName": @"马大哈", @"age": @(18)};
// app将通知塞给系统,由系统统一调度本地通知,scheduleLocalNotification
// 即使app被kill,也会如期执行通知事件
[[UIApplication sharedApplication]scheduleLocalNotification:notification];
}
@end
H:/1024/02_消息推送_AppDelegate.m
// AppDelegate.m
// 消息推送
// Created by apple on 13-10-24.
// Copyright (c) 2013年 itcast. All rights reserved.
/*
APNS: apple push notification service
1,registerForRemoteNotificationTypes
2,didRegisterForRemoteNotificationsWithDeviceToken
3,从NSUserDefaults standardUserDefaults取出旧的 deviceToken 与新的比较
如果不一样,就保存新的deviceToken,并且上传新的deviceToken到服务器
4,由服务器去和apple的APNS服务器打交道
5,app只要实现了registerForRemoteNotificationTypes,
手机就会通过SSL连接从apple的APNS服务器上取回deviceToken
*/
#import "AppDelegate.h"
@implementation AppDelegate
/*
要开发测试消息机制的程序,必须用真机测试
推送消息的类型
UIRemoteNotificationType None 不接收推送消息
UIRemoteNotificationType Badge 接收图标数字
UIRemoteNotificationType Sound 接收音频
UIRemoteNotificationType Alert 接收消息文字
UIRemoteNotificationType NewsstandContentAvailability 接收订阅消息
要想监听到注册的deviceToken需要在苹果的开发者中心,进行一些设置工作才可以。
*/
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// 设置应用程序能够接收APNS推送的消息
// app注册远程通知类型
[application registerForRemoteNotificationTypes:
UIRemoteNotificationTypeAlert |
UIRemoteNotificationTypeBadge |
UIRemoteNotificationTypeSound];
// 下面是固定代码
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen]bounds]];
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
return YES;
}
#pragma mark - 获取DeviceToken
- (void)application:(UIApplication *)application
didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
NSLog(@"%@", deviceToken);
// 1. 从系统偏好取之前旧的token
NSData *oldToken = [[NSUserDefaults standardUserDefaults]
objectForKey:@"deviceToken"];
// 2. 新旧token进行比较
if (![oldToken isEqualToData:deviceToken]) {
// 3. 如果不一致,保存新token到系统偏好
[[NSUserDefaults standardUserDefaults]setObject:deviceToken
forKey:@"deviceToken"];
// 4. 使用post请求传输新旧token至服务器
// 1) url
// 具体的URL地址以及POST请求中的参数和格式,是由公司的后端程序员提供的
// 2) request POST body(包含新旧token的数据)
// 3) connection 的异步
}
}
@end
H:/1024/03_新浪微博_AppDelegate.m
// AppDelegate.m
// 新浪微博
// Created by apple on 13-10-24.
// Copyright (c) 2013年 itcast. All rights reserved.
#import "AppDelegate.h"
#import "MainViewController.h"
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window.backgroundColor = [UIColor whiteColor];
// 实例化MainViewController
MainViewController *controller = [[MainViewController alloc]init];
// 将代理的window的根控制器设置为 MainViewController
[self.window setRootViewController:controller];
[self.window makeKeyAndVisible];
return YES;
}
@end
H:/1024/03_新浪微博_MainViewController.m
// MainViewController.m
// 新浪微博
// Created by apple on 13-10-24.
// Copyright (c) 2013年 itcast. All rights reserved.
/*
(前提要在设置中需要设置新浪微博的账号)
*/
#import "MainViewController.h"
// 需要导入第3方框架
#import <Social/Social.h>
@interface MainViewController ()
@end
@implementation MainViewController
- (void)viewDidLoad
{
[super viewDidLoad];
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[button setFrame:CGRectMake(110, 210, 100, 40)];
[button setTitle:@"新浪微博" forState:UIControlStateNormal];
[self.view addSubview:button];
// 为按钮添加监听点击事件
[button addTarget:self action:@selector(weibo)
forControlEvents:UIControlEventTouchUpInside];
}
#pragma mark 响应按钮点击,发布微博,发布的自动回到原界面
- (void)weibo
{
// 1. 判断新浪微博服务是否可用(前提要在设置中需要设置新浪微博的账号)
// 2. 如果要发twitter或者facebook直接改类型即可。
if ([SLComposeViewController
isAvailableForServiceType:SLServiceTypeSinaWeibo]) {
// 1)实例化视图控制器
SLComposeViewController *controller = [SLComposeViewController
composeViewControllerForServiceType:SLServiceTypeSinaWeibo];
// 2)展现视图控制器
[self presentViewController:controller animated:YES completion:nil];
} else {
NSLog(@"新浪微博服务不可用");
}
}
@end
H:/1024/04_ImagePicker_蓝牙传输_AppDelegate.m
// AppDelegate.m
// 蓝牙传输
// Created by apple on 13-10-24.
// Copyright (c) 2013年 itcast. All rights reserved.
#import "AppDelegate.h"
#import "MainViewController.h"
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window.backgroundColor = [UIColor whiteColor];
// 实例化控制器MainViewController
MainViewController *controller = [[MainViewController alloc]init];
// 将MainViewController设置为代理的window的根控制器
[self.window setRootViewController:controller];
[self.window makeKeyAndVisible];
return YES;
}
@end
H:/1024/04_ImagePicker_蓝牙传输_MainViewController.m
// MainViewController.m
// 蓝牙传输
// Created by apple on 13-10-24.
// Copyright (c) 2013年 itcast. All rights reserved.
#import "MainViewController.h"
#import <GameKit/GameKit.h>
@interface MainViewController () <UIImagePickerControllerDelegate,
UINavigationControllerDelegate, GKPeerPickerControllerDelegate>
{
UIButton *_imageButton;
// 对端连接回话
GKSession *_gkSession;
}
@end
@implementation MainViewController
/*
添加按钮,点击按钮选择照片
照片源类型
UIImagePickerControllerSourceTypeCamera 照相机
UIImagePickerControllerSourceTypePhotoLibrary 照片库(通过从电脑同步存放的,用户不能删除)
UIImagePickerControllerSourceTypeSavedPhotosAlbum 保存的照片(通过拍照或者截屏保存的,用户可以删除)
关于蓝牙的数据传输
1. 一次性传送,没有中间方法,所谓中间方法指的是,显示传输进度比例
对于用户而言,选择了传输,就必须等待传输完成,或者传输失败
实际开发中,最好不要用蓝牙传输太大的文件
在实际应用中,蓝牙通常用于传递游戏数据模型,用于联机对战,譬如点对点的棋牌类游戏。
*/
- (void)loadView
{
self.view = [[UIView alloc]initWithFrame:[UIScreen mainScreen].applicationFrame];
// 选择照片按钮
UIButton *imageButton = [UIButton buttonWithType:UIButtonTypeCustom];
[imageButton setFrame:CGRectMake(10, 10, 300, 300)];
[imageButton setTitle:@"选择照片" forState:UIControlStateNormal];
[self.view addSubview:imageButton];
[imageButton addTarget:self action:@selector(selectPhoto)
forControlEvents:UIControlEventTouchUpInside];
_imageButton = imageButton;
// 蓝牙连接按钮
UIButton *connectButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[connectButton setFrame:CGRectMake(30, 400, 100, 40)];
[connectButton setTitle:@"连接" forState:UIControlStateNormal];
[self.view addSubview:connectButton];
[connectButton addTarget:self action:@selector(connectPeer)
forControlEvents:UIControlEventTouchUpInside];
// 照片发送按钮
UIButton *sendButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[sendButton setFrame:CGRectMake(190, 400, 100, 40)];
[sendButton setTitle:@"发送照片" forState:UIControlStateNormal];
[self.view addSubview:sendButton];
[sendButton addTarget:self action:@selector(sendPhoto)
forControlEvents:UIControlEventTouchUpInside];
}
#pragma mark 响应选择照片按钮, 选择照片
- (void)selectPhoto
{
// 1. 首先判断照片源是否可用
if ([UIImagePickerController
isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]) {
// 0)实例化ImagePicker控制器
UIImagePickerController *picker = [[UIImagePickerController
alloc]init];
// 1)设置照片源
[picker setSourceType:UIImagePickerControllerSourceTypePhotoLibrary];
// 2) 设置允许修改
[picker setAllowsEditing:YES];
// 3) 设置代理,为当前控制器
[picker setDelegate:self];
// 4) 展现控制器
[self presentViewController:picker animated:YES completion:nil];
} else {
NSLog(@"照片源不可用");
}
}
#pragma mark - imagePicker代理方法,didFinishPickingMediaWithInfo
- (void)imagePickerController:(UIImagePickerController *)picker
didFinishPickingMediaWithInfo:(NSDictionary *)info
{
// 从info字典得到编辑后的照片
UIImage *image = info[@"UIImagePickerControllerEditedImage"];
// 设置照片
[_imageButton setImage:image forState:UIControlStateNormal];
// 必须手动,关闭照片选择器
[self dismissViewControllerAnimated:YES completion:nil];
// 需要将照片保存至应用程序沙箱,由于涉及到数据存储,同时与界面无关
// 可以使用多线程来保存图像
dispatch_async(dispatch_get_global_queue
(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// 保存图像
// 1. 取图像路径
NSArray *docs = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES);
// 拼接保存的文件路径
NSString *imagePath = [docs[0]stringByAppendingPathComponent:@"abc.png"];
// 2. 转换image为NSData保存,PNGRepresentation
NSData *imageData = UIImagePNGRepresentation(image);
[imageData writeToFile:imagePath atomically:YES];
});
}
#pragma mark 响应点击,蓝牙连接按钮,连接对端
- (void)connectPeer
{
// 1. 实例化一个对端选择视图控制器GKPeerPickerController
GKPeerPickerController *picker = [[GKPeerPickerController alloc]init];
// 2. 设置代理为当前控制器
[picker setDelegate:self];
// 3. 展现视图控制器
[picker show];
}
#pragma mark 对端选择器代理方法
// 完成对端连接,didConnectPeer
- (void)peerPickerController:(GKPeerPickerController *)picker
didConnectPeer:(NSString *)peerID toSession:(GKSession *)session
{
NSLog(@"连接已经建立");
// session会话,代表一个完整的连接过程
_gkSession = session;
// 设置数据处理对象,类似于delegate
[_gkSession setDataReceiveHandler:self withContext:nil];
// 必须手动,关闭选择器
[picker dismiss];
}
#pragma mark 响应点击,利用蓝牙的会话,发送图片数据
- (void)sendPhoto
{
// 利用session发送data数据,PNGRepresentation
NSData *imageData =
UIImagePNGRepresentation(_imageButton.imageView.image);
/*
精通TCP协议、UDP协议
1. 要发送的数据(二进制的)
2. 数据发送模式
GKSendDataReliable :确保数据发送成功(TCP协议,对网络压力大)
GKSendDataUnReliable :只管发送不管成功(UDP协议,
对数据完整性要求不高,对网络压力下)*/
[_gkSession sendDataToAllPeers:imageData withDataMode:GKSendDataReliable
error:nil];
}
// 数据接收的代理方法,此方法需要从文档中粘贴出来,此处没有智能提示
- (void)receiveData:(NSData *)data fromPeer:(NSString *)peer inSession:
(GKSession *)session context:(void *)context
{
NSLog(@"接收到数据");
// 将NSData转换成UIImage,之所以能转换成UIImage是因为我们发送的就是UIImage
UIImage *image = [UIImage imageWithData:data];
[_imageButton setImage:image forState:UIControlStateNormal];
}
@end