KVC,即是指 NSKeyValueCoding,一个非正式的 Protocol,提供一种机制来间接访问对象的属性。KVO 就是基于 KVC 实现的关键技术之一。
1.KVC:间接访问对象属性 监听属性变化
2.1 KVO:1.保存所有参数 监听着,枚举,携带参数,路径
2.2 创建之类 NSKVONotifying_CZPerson 重写set方法
2.2 set方法,监听着 底层调用自己的方法ObserveValueForKeyPath
KVO 底层实现: 运行时, 创建一个子类对象并且重写子类的set方法 在set方法调用监听着的observeValueForKeyPath
KVO 代码:
//KVO
// key value observed
// 监听对象属性的改变
CZPerson *person = [[CZPerson alloc]init];
self.person = person;
person.name = @"明月心";
person.age = 18;
person.height = 1.8;
//KeyPath 键值路径
[person addObserver:self forKeyPath:@"height" options:NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew context:nil];
//1.保存所有参数 监听者 枚举 携带参数 路劲
//2.创建之类NSKVONotifying_CZPerson 重写set方法
//3.set方法 监听者 底层调用自己的方法observeValueForKeyPath
//KVO的底层实现原理是啥
//运行时 runtim
//person.age = 19;
//isa Class NSKVONotifying_CZPerson 0x00007face0d1a190
person.height = 1.6; //能够执行子类NSKVONotifying_CZPerson的set方法
// 监听者 底层调用自己的方法observeValueForKeyPath
// 在什么地方调用
// key value observed
// 监听对象属性的改变
CZPerson *person = [[CZPerson alloc]init];
self.person = person;
person.name = @"明月心";
person.age = 18;
person.height = 1.8;
//KeyPath 键值路径
[person addObserver:self forKeyPath:@"height" options:NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew context:nil];
//1.保存所有参数 监听者 枚举 携带参数 路劲
//2.创建之类NSKVONotifying_CZPerson 重写set方法
//3.set方法 监听者 底层调用自己的方法observeValueForKeyPath
//KVO的底层实现原理是啥
//运行时 runtim
//person.age = 19;
//isa Class NSKVONotifying_CZPerson 0x00007face0d1a190
person.height = 1.6; //能够执行子类NSKVONotifying_CZPerson的set方法
// 监听者 底层调用自己的方法observeValueForKeyPath
// 在什么地方调用
// KVO 底层实现: 运行时 创建一个子类对象并且重写子类的set方法 在set方法 调用监听者的observeValueForKeyPath
NSLog(@"%@ %zd %f",person.name,person.age,person.height);
}
- (void)dealloc
{
[self.person removeObserver:self forKeyPath:@"height"];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context
{
NSLog(@"%@",change);
}
}
- (void)dealloc
{
[self.person removeObserver:self forKeyPath:@"height"];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context
{
NSLog(@"%@",change);
}
广告:iad
iAd: 广告语 控件
引入框架 头文件
代码:
换肤:
1.工具类思想:封装代码,让用户看的爽的代码,不提供参数,只提供一个接口来设置属性
思路实现:
1.设置三个图片进行自动布局,拖线
2.设置segmenmetControl 的点击方法
3.加载图片设置
4.设置偏好设置NSUserdelfauat
5.设置下标对齐
6设置工具类
7.重写方法
8.添加新的控制器,调用方法
9,设置tabbarcontrol 在ViewDidLoad 默认只会加载一次,,应该把方法写在ViewWillAppear的方法中,这个方法是,,每次程序加载都会调用
方法
这个这个方法 比较调用父类的
9 .设置字体和图片,在工具类添加一个方法,,添加plist ,进行读取,
10 设置颜色
工具类代码:
#import "CZSkinTool.h"
@interface CZSkinTool ()
@end
static NSString *_skin;
@implementation CZSkinTool
+(void)load
{
_skin = [[NSUserDefaults standardUserDefaults]objectForKey:@"skin"];
if (_skin == nil) {
_skin = @"blue";
}
}
+ (UIImage *)getImageWithName:(NSString *)imageName
{
// NSString *skin = [[NSUserDefaults standardUserDefaults]objectForKey:@"skin"];
// if (skin == nil) {
// skin = @"blue";
// }
//根据当前的样式 来创建图片
UIImage *image = [UIImage imageNamed:[NSString stringWithFormat:@"skin/%@/%@",_skin,imageName]];
return image;
}
+ (void)saveSkin:(NSString *)skin
{
//保存
[[NSUserDefaults standardUserDefaults]setObject:skin forKey:@"skin"];
//立即保存
[[NSUserDefaults standardUserDefaults]synchronize];
_skin = skin;
}
+ (UIColor *)getColorWithKey:(NSString *)key
{
//myLabel_textColor 255,166,222
//myView_bg 255,66,0
// NSDictionary *dict = @{@"myLabel_textColor":@"255,166,222" , @"myView_bg":@"255,66,0"};
//字典弊端
//plist
NSString *path = [[NSBundle mainBundle]pathForResource:[NSString stringWithFormat:@"skin/%@/color.plist",_skin] ofType:nil];
NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:path];
//key
NSString *colorStr = dict[key]; //"233,89,89"
NSArray *allColorStr = [colorStr componentsSeparatedByString:@","];
CGFloat r = [allColorStr[0] floatValue]/255.0;
CGFloat g = [allColorStr[1] floatValue]/255.0;
CGFloat b = [allColorStr[2] floatValue]/255.0;
return [UIColor colorWithRed:r green:g blue:b alpha:1.0];
}
@end
内购思路
1. 导入框架
2. 引入头文件
3. 请求商品
4.设置代理,实现方法出现商品数据
4. UITableView展示商品
3. 用户点击选择购买
4. 添加交易队列
5. 设置代理监听交易状态
6. 完成交易
代码如下:
- (void)viewDidLoad {
[super viewDidLoad];
//1.请求商品
//1.1读取JSON文件
NSString *path =[[NSBundle mainBundle]pathForResource:@"products.json" ofType:nil];
//二进制读写
NSData *data =[NSData dataWithContentsOfFile:path];
//反序列化进行读写
NSArray *tempArray =[NSJSONSerialization JSONObjectWithData:data options:0 error:NULL];
//抽取数组其中一组元素
NSArray *arrm = [tempArray valueForKey:@"productId"];
//数组转集合,,运行是是数组,编译是是集合
NSSet *steProuduct = [NSSet setWithArray:arrm];
//发送请求
SKProductsRequest *resquest = [[SKProductsRequest alloc]initWithProductIdentifiers:steProuduct];
//设置代理展示数据
resquest.delegate = self;
//开始
[resquest start];
//添加到交易队列
[super viewDidLoad];
//1.请求商品
//1.1读取JSON文件
NSString *path =[[NSBundle mainBundle]pathForResource:@"products.json" ofType:nil];
//二进制读写
NSData *data =[NSData dataWithContentsOfFile:path];
//反序列化进行读写
NSArray *tempArray =[NSJSONSerialization JSONObjectWithData:data options:0 error:NULL];
//抽取数组其中一组元素
NSArray *arrm = [tempArray valueForKey:@"productId"];
//数组转集合,,运行是是数组,编译是是集合
NSSet *steProuduct = [NSSet setWithArray:arrm];
//发送请求
SKProductsRequest *resquest = [[SKProductsRequest alloc]initWithProductIdentifiers:steProuduct];
//设置代理展示数据
resquest.delegate = self;
//开始
[resquest start];
//添加到交易队列
[[SKPaymentQueue defaultQueue]addTransactionObserver:self];
}
//删除交易队列
- (void)dealloc{
NSLog(@"我走了");
[[SKPaymentQueue defaultQueue]removeTransactionObserver:self];
}
- (IBAction)resumeclict:(id)sender {
//恢复交易队列,,有可能有些客户买了非消耗品就是终身拥有的
[[SKPaymentQueue defaultQueue]restoreCompletedTransactions];
}
//5.添加监听着监听交易队列
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray<SKPaymentTransaction *> *)transactions{
for (SKPaymentTransaction * t in transactions) {
/*
SKPaymentTransactionStatePurchasing, // 交易正被添加到交易队列
SKPaymentTransactionStatePurchased, // 在交易队列中 客户已经支付 需要客户端完成支付
SKPaymentTransactionStateFailed, //失败了 队列中没有
SKPaymentTransactionStateRestored, //客户端完成交易
SKPaymentTransactionStateDeferred //在队列中状态还不确定 NS_ENUM_AVAILABLE_IOS(8_0),
*/
if (t.transactionState == SKPaymentTransactionStatePurchasing) {
//6.完成购买
NSLog(@"购买完成,提供增值服务");
}else if (t.transactionState ==SKPaymentTransactionStatePurchased ) {
NSLog(@"客户已经支付完成");
}else if (t.transactionState == SKPaymentTransactionStateFailed){
NSLog(@"任务失败");
}else if (t.transactionState ==SKPaymentTransactionStateRestored ){
NSLog(@"恢复完成");
}else{
NSLog(@"状态不确定");
}
}
}
//2.展示商品
//代理方法当收到服务器响应后会调用的方法
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response{
//forin循环
/*
localizedTitle //产品名称
localizedDescription //产品描述
price//价格
productIdentifier//产品唯一标识
*/
for (SKProduct *sk in response.products) {
NSLog(@"%@,%@,%@,%@",sk.localizedTitle,sk.localizedDescription,sk.price,sk.productIdentifier);
}
//赋值给数组展示数据
self.productArray = response.products;
//更新
[self.tableView reloadData];
}
#pragma mark 数据源方法
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return self.productArray.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString * ID = @"cell";
UITableViewCell *cell =[tableView dequeueReusableCellWithIdentifier:ID];
if (!cell) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ID];
}
SKProduct *pro = self.productArray[indexPath.row];
cell.textLabel.text = [NSString stringWithFormat:@"%@ %@",pro.localizedTitle,pro.price];
cell.detailTextLabel.text = [NSString stringWithFormat:@"%@,%@",pro.localizedDescription,pro.productIdentifier];
cell.textLabel.numberOfLines = 0;
cell.detailTextLabel.numberOfLines = 0;
return cell;
}
//3.用户交钱
//4.添加到交易队列
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
SKProduct *skpro =self.productArray[indexPath.row];
SKPayment *pay = [SKPayment paymentWithProduct:skpro];
[[SKPaymentQueue defaultQueue]addPayment:pay];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
return 80;
//删除交易队列
- (void)dealloc{
NSLog(@"我走了");
[[SKPaymentQueue defaultQueue]removeTransactionObserver:self];
}
- (IBAction)resumeclict:(id)sender {
//恢复交易队列,,有可能有些客户买了非消耗品就是终身拥有的
[[SKPaymentQueue defaultQueue]restoreCompletedTransactions];
}
//5.添加监听着监听交易队列
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray<SKPaymentTransaction *> *)transactions{
for (SKPaymentTransaction * t in transactions) {
/*
SKPaymentTransactionStatePurchasing, // 交易正被添加到交易队列
SKPaymentTransactionStatePurchased, // 在交易队列中 客户已经支付 需要客户端完成支付
SKPaymentTransactionStateFailed, //失败了 队列中没有
SKPaymentTransactionStateRestored, //客户端完成交易
SKPaymentTransactionStateDeferred //在队列中状态还不确定 NS_ENUM_AVAILABLE_IOS(8_0),
*/
if (t.transactionState == SKPaymentTransactionStatePurchasing) {
//6.完成购买
NSLog(@"购买完成,提供增值服务");
}else if (t.transactionState ==SKPaymentTransactionStatePurchased ) {
NSLog(@"客户已经支付完成");
}else if (t.transactionState == SKPaymentTransactionStateFailed){
NSLog(@"任务失败");
}else if (t.transactionState ==SKPaymentTransactionStateRestored ){
NSLog(@"恢复完成");
}else{
NSLog(@"状态不确定");
}
}
}
//2.展示商品
//代理方法当收到服务器响应后会调用的方法
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response{
//forin循环
/*
localizedTitle //产品名称
localizedDescription //产品描述
price//价格
productIdentifier//产品唯一标识
*/
for (SKProduct *sk in response.products) {
NSLog(@"%@,%@,%@,%@",sk.localizedTitle,sk.localizedDescription,sk.price,sk.productIdentifier);
}
//赋值给数组展示数据
self.productArray = response.products;
//更新
[self.tableView reloadData];
}
#pragma mark 数据源方法
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return self.productArray.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString * ID = @"cell";
UITableViewCell *cell =[tableView dequeueReusableCellWithIdentifier:ID];
if (!cell) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ID];
}
SKProduct *pro = self.productArray[indexPath.row];
cell.textLabel.text = [NSString stringWithFormat:@"%@ %@",pro.localizedTitle,pro.price];
cell.detailTextLabel.text = [NSString stringWithFormat:@"%@,%@",pro.localizedDescription,pro.productIdentifier];
cell.textLabel.numberOfLines = 0;
cell.detailTextLabel.numberOfLines = 0;
return cell;
}
//3.用户交钱
//4.添加到交易队列
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
SKProduct *skpro =self.productArray[indexPath.row];
SKPayment *pay = [SKPayment paymentWithProduct:skpro];
[[SKPaymentQueue defaultQueue]addPayment:pay];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
return 80;
}