IOS_本地通知_消息推送_微博_蓝牙_ImagePicker

齐运诚
2023-12-01
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

 类似资料: