iOS开发——UI进阶篇(五)通知、代理、kvo的应用和对比,购物车
一、通知
1、通知中心(NSNotificationCenter)
每一个应用程序都有一个通知中心(NSNotificationCenter)实例,专门负责协助不同对象之间的消息通信
任何一个对象都可以向通知中心发布通知(NSNotification),描述自己在做什么。其他感兴趣的对象(Observer)可以申请在某个特定通知发布时(或在某个特定的对象发布通知时)收到这个通知
2、通知(NSNotification)
一个完整的通知一般包含3个属性:
- (NSString *)name; // 通知的名称
- (id)object; // 通知发布者(是谁要发布通知)
- (NSDictionary *)userInfo; // 一些额外的信息(通知发布者传递给通知接收者的信息内容)
初始化一个通知(NSNotification)对象
+ (instancetype)notificationWithName:(NSString *)aName object:(id)anObject;
+ (instancetype)notificationWithName:(NSString *)aName object:(id)anObject userInfo:(NSDictionary *)aUserInfo;
- (instancetype)initWithName:(NSString *)name object:(id)object userInfo:(NSDictionary *)userInfo;
3、发布通知
通知中心(NSNotificationCenter)提供了相应的方法来帮助发布通知
- (void)postNotification:(NSNotification *)notification;
发布一个notification通知,可在notification对象中设置通知的名称、通知发布者、额外信息等
- (void)postNotificationName:(NSString *)aName object:(id)anObject;
发布一个名称为aName的通知,anObject为这个通知的发布者
- (void)postNotificationName:(NSString *)aName object:(id)anObject userInfo:(NSDictionary *)aUserInfo;
发布一个名称为aName的通知,anObject为这个通知的发布者,aUserInfo为额外信息
4、注册通知监听器
通知中心(NSNotificationCenter)提供了方法来注册一个监听通知的监听器(Observer)
- (void)addObserver:(id)observer selector:(SEL)aSelector name:(NSString *)aName object:(id)anObject;
observer:监听器,即谁要接收这个通知
aSelector:收到通知后,回调监听器的这个方法,并且把通知对象当做参数传入
aName:通知的名称。如果为nil,那么无论通知的名称是什么,监听器都能收到这个通知
anObject:通知发布者。如果为anObject和aName都为nil,监听器都收到所有的通知
- (id)addObserverForName:(NSString *)name object:(id)obj queue:(NSOperationQueue *)queue usingBlock:(void (^)(NSNotification *note))block;
name:通知的名称
obj:通知发布者
block:收到对应的通知时,会回调这个block
queue:决定了block在哪个操作队列中执行,如果传nil,默认在当前操作队列中同步执行
5、取消注册通知监听器
通知中心不会保留(retain)监听器对象,在通知中心注册过的对象,必须在该对象释放前取消注册。否则,当相应的通知再次出现时,通知中心仍然会向该监听器发送消息。因为相应的监听器对象已经被释放了,所以可能会导致应用崩溃
通知中心提供了相应的方法来取消注册监听器
- (void)removeObserver:(id)observer;
- (void)removeObserver:(id)observer name:(NSString *)aName object:(id)anObject;
一般在监听器销毁之前取消注册(如在监听器中加入下列代码):
- (void)dealloc {
//[super dealloc]; 非ARC中需要调用此句
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
6、UIDevice通知
UIDevice类提供了一个单粒对象,它代表着设备,通过它可以获得一些设备相关的信息,比如电池电量值(batteryLevel)、电池状态(batteryState)、设备的类型(model,比如iPod、iPhone等)、设备的系统(systemVersion)
通过[UIDevice currentDevice]可以获取这个单粒对象
UIDevice对象会不间断地发布一些通知,下列是UIDevice对象所发布通知的名称常量:
UIDeviceOrientationDidChangeNotification // 设备旋转
UIDeviceBatteryStateDidChangeNotification // 电池状态改变
UIDeviceBatteryLevelDidChangeNotification // 电池电量改变
UIDeviceProximityStateDidChangeNotification // 近距离传感器(比如设备贴近了使用者的脸部)
7、键盘通知
我们经常需要在键盘弹出或者隐藏的时候做一些特定的操作,因此需要监听键盘的状态
键盘状态改变的时候,系统会发出一些特定的通知
UIKeyboardWillShowNotification // 键盘即将显示
UIKeyboardDidShowNotification // 键盘显示完毕
UIKeyboardWillHideNotification // 键盘即将隐藏
UIKeyboardDidHideNotification // 键盘隐藏完毕
UIKeyboardWillChangeFrameNotification // 键盘的位置尺寸即将发生改变
UIKeyboardDidChangeFrameNotification // 键盘的位置尺寸改变完毕
系统发出键盘通知时,会附带一下跟键盘有关的额外信息(字典),字典常见的key如下:
UIKeyboardFrameBeginUserInfoKey // 键盘刚开始的frame
UIKeyboardFrameEndUserInfoKey // 键盘最终的frame(动画执行完毕后)
UIKeyboardAnimationDurationUserInfoKey // 键盘动画的时间
UIKeyboardAnimationCurveUserInfoKey // 键盘动画的执行节奏(快慢)
下面通过购物车案例了解通知、代理以及kvo的使用
二、通知
cell内部:
// 发布通知
[[NSNotificationCenter defaultCenter] postNotificationName:@"plusClickNotification" object:self];
// 发布通知
[[NSNotificationCenter defaultCenter] postNotificationName:@"minusClickNotification" object:self];
控制器中:
// 注册通知监听器
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
[center addObserver:self selector:@selector(plusClick:) name:@"plusClickNotification" object:nil];
[center addObserver:self selector:@selector(minusClick:) name:@"minusClickNotification" object:nil]; // 监听通知
- (void)plusClick:(NSNotification *)note
{
self.buyButton.enabled = YES; // 取出cell(通知的发布者)
XMGWineCell *cell = note.object;
// 计算总价
int totalPrice = self.totalPriceLabel.text.intValue + cell.wine.money.intValue;
// 设置总价
self.totalPriceLabel.text = [NSString stringWithFormat:@"%d", totalPrice];
} - (void)minusClick:(NSNotification *)note
{
// 取出cell(通知的发布者)
XMGWineCell *cell = note.object;
// 计算总价
int totalPrice = self.totalPriceLabel.text.intValue - cell.wine.money.intValue;
// 设置总价
self.totalPriceLabel.text = [NSString stringWithFormat:@"%d", totalPrice]; self.buyButton.enabled = totalPrice > ;
}
全代码:
/****************** XMGWine*********************/
#import <Foundation/Foundation.h> @interface XMGWine : NSObject
@property (copy, nonatomic) NSString *money;
@property (copy, nonatomic) NSString *name;
@property (copy, nonatomic) NSString *image; /** 数量 */
@property (nonatomic, assign) int count;
@end #import "XMGWine.h" @implementation XMGWine @end /***************** XMGCircleButton*****************/
#import <UIKit/UIKit.h> @interface XMGCircleButton : UIButton @end #import "XMGCircleButton.h" @implementation XMGCircleButton - (void)awakeFromNib
{
// 设置边框颜色
self.layer.borderColor = [UIColor redColor].CGColor;
// 设置边框宽度
self.layer.borderWidth = ;
// 设置圆角半径
self.layer.cornerRadius = self.frame.size.width * 0.5;
} @end /****************** XMGWineCell*********************/
#import <UIKit/UIKit.h>
@class XMGWine, XMGCircleButton; @interface XMGWineCell : UITableViewCell
@property (strong, nonatomic) XMGWine *wine;
@end #import "XMGWineCell.h"
#import "XMGWine.h"
#import "XMGCircleButton.h" @interface XMGWineCell()
@property (weak, nonatomic) IBOutlet XMGCircleButton *minusButton;
@property (weak, nonatomic) IBOutlet UIImageView *imageImageView;
@property (weak, nonatomic) IBOutlet UILabel *nameLabel;
@property (weak, nonatomic) IBOutlet UILabel *moneyLabel;
@property (weak, nonatomic) IBOutlet UILabel *countLabel;
@end @implementation XMGWineCell - (void)setWine:(XMGWine *)wine
{
_wine = wine; self.imageImageView.image = [UIImage imageNamed:wine.image];
self.nameLabel.text = wine.name;
self.moneyLabel.text = wine.money;
self.countLabel.text = [NSString stringWithFormat:@"%d", wine.count];
self.minusButton.enabled = (wine.count > );
} /**
* 加号点击
*/
- (IBAction)plusClick {
// 修改模型
self.wine.count++; // 修改数量label
self.countLabel.text = [NSString stringWithFormat:@"%d", self.wine.count]; // 减号能点击
self.minusButton.enabled = YES; // 发布通知
[[NSNotificationCenter defaultCenter] postNotificationName:@"plusClickNotification" object:self];
} /**
* 减号点击
*/
- (IBAction)minusClick {
// 修改模型
self.wine.count--; // 修改数量label
self.countLabel.text = [NSString stringWithFormat:@"%d", self.wine.count]; // 减号按钮不能点击
if (self.wine.count == ) {
self.minusButton.enabled = NO;
} // 发布通知
[[NSNotificationCenter defaultCenter] postNotificationName:@"minusClickNotification" object:self];
}
@end /****************** ViewController*********************/
#import <UIKit/UIKit.h> @interface ViewController : UIViewController
@end #import "ViewController.h"
#import "XMGWineCell.h"
#import "XMGWine.h"
#import "MJExtension.h" @interface ViewController () <UITableViewDataSource>
@property (weak, nonatomic) IBOutlet UIButton *buyButton;
@property (weak, nonatomic) IBOutlet UITableView *tableView;
/** 酒数据 */
@property (nonatomic, strong) NSArray *wineArray;
/** 总价 */
@property (weak, nonatomic) IBOutlet UILabel *totalPriceLabel;
@end @implementation ViewController
- (NSArray *)wineArray
{
if (!_wineArray) {
self.wineArray = [XMGWine objectArrayWithFilename:@"wine.plist"];
}
return _wineArray;
} - (void)viewDidLoad {
[super viewDidLoad]; // 监听通知
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
[center addObserver:self selector:@selector(plusClick:) name:@"plusClickNotification" object:nil];
[center addObserver:self selector:@selector(minusClick:) name:@"minusClickNotification" object:nil];
} - (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
} #pragma mark - 按钮点击
- (IBAction)clear {
self.totalPriceLabel.text = @""; // 将模型里面的count清零
for (XMGWine *wine in self.wineArray) {
wine.count = ;
} // 刷新
[self.tableView reloadData]; self.buyButton.enabled = NO;
} - (IBAction)buy {
// 打印出所有要买的东西
for (XMGWine *wine in self.wineArray) {
if (wine.count) {
NSLog(@"%d件【%@】", wine.count, wine.name);
}
}
} #pragma mark - 监听通知
- (void)plusClick:(NSNotification *)note
{
self.buyButton.enabled = YES; // 取出cell(通知的发布者)
XMGWineCell *cell = note.object;
// 计算总价
int totalPrice = self.totalPriceLabel.text.intValue + cell.wine.money.intValue;
// 设置总价
self.totalPriceLabel.text = [NSString stringWithFormat:@"%d", totalPrice];
} - (void)minusClick:(NSNotification *)note
{
// 取出cell(通知的发布者)
XMGWineCell *cell = note.object;
// 计算总价
int totalPrice = self.totalPriceLabel.text.intValue - cell.wine.money.intValue;
// 设置总价
self.totalPriceLabel.text = [NSString stringWithFormat:@"%d", totalPrice]; self.buyButton.enabled = totalPrice > ;
} #pragma mark - <UITableViewDataSource>
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.wineArray.count;
} - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *ID = @"wine";
XMGWineCell *cell = [tableView dequeueReusableCellWithIdentifier:ID]; cell.wine = self.wineArray[indexPath.row]; return cell;
} @end
购物车(通知)
Main.storyboard
三、代理
这是我总结的关于协议和代理
这里有两句话写错了,应该是“要想其他对象成为我的代理,必须先遵守我的协议”
cell.delegate = self; // 设置控制器为cell的代理
@interface ViewController () <UITableViewDataSource, XMGWineCellDelegate, UITableViewDelegate> // 控制器必须先遵守cell的协议
这就相当于设置TableView(TableView.delegate = self)的代理为控制器时,控制器也要遵守<UITableViewDelegate>这个协议
依次类推,dog对象,cat对象,person对象,任何对象想成为我的代理,都必须遵守我的协议
那么在这个例子中
cell内部:
// 通知代理(调用代理的方法)
// respondsToSelector:能判断某个对象是否实现了某个方法
if ([self.delegate respondsToSelector:@selector(wineCellDidClickPlusButton:)]) {
[self.delegate wineCellDidClickPlusButton:self];
} // 通知代理(调用代理的方法)
if ([self.delegate respondsToSelector:@selector(wineCellDidClickMinusButton:)]) {
[self.delegate wineCellDidClickMinusButton:self];
}
控制器:
#pragma mark - <XMGWineCellDelegate>
- (void)wineCellDidClickMinusButton:(XMGWineCell *)wineCell
{
// 计算总价
int totalPrice = self.totalPriceLabel.text.intValue - wineCell.wine.money.intValue; // 设置总价
self.totalPriceLabel.text = [NSString stringWithFormat:@"%d", totalPrice]; self.buyButton.enabled = totalPrice > ; // 将商品从购物车中移除
if (wineCell.wine.count == ) {
[self.wineCar removeObject:wineCell.wine];
}
} - (void)wineCellDidClickPlusButton:(XMGWineCell *)wineCell
{
// 计算总价
int totalPrice = self.totalPriceLabel.text.intValue + wineCell.wine.money.intValue; // 设置总价
self.totalPriceLabel.text = [NSString stringWithFormat:@"%d", totalPrice]; self.buyButton.enabled = YES; // 如果这个商品已经在购物车中,就不用再添加
if ([self.wineCar containsObject:wineCell.wine]) return; // 添加需要购买的商品
[self.wineCar addObject:wineCell.wine];
}
这样通过通知代理,调用代理方法来实现点击加号减号按钮时计算总价
部分代码:
/****************** XMGWineCell.h****************/
#import <UIKit/UIKit.h>
@class XMGWine, XMGCircleButton, XMGWineCell; @protocol XMGWineCellDelegate <NSObject>
@optional
- (void)wineCellDidClickPlusButton:(XMGWineCell *)wineCell;
- (void)wineCellDidClickMinusButton:(XMGWineCell *)wineCell;
@end @interface XMGWineCell : UITableViewCell
@property (strong, nonatomic) XMGWine *wine; /** 代理对象 */
@property (nonatomic, weak) id<XMGWineCellDelegate> delegate;
@end /****************** XMGWineCell.m****************/ #import "XMGWineCell.h"
#import "XMGWine.h"
#import "XMGCircleButton.h" @interface XMGWineCell()
@property (weak, nonatomic) IBOutlet XMGCircleButton *minusButton;
@property (weak, nonatomic) IBOutlet UIImageView *imageImageView;
@property (weak, nonatomic) IBOutlet UILabel *nameLabel;
@property (weak, nonatomic) IBOutlet UILabel *moneyLabel;
@property (weak, nonatomic) IBOutlet UILabel *countLabel;
@end @implementation XMGWineCell - (void)setWine:(XMGWine *)wine
{
_wine = wine; self.imageImageView.image = [UIImage imageNamed:wine.image];
self.nameLabel.text = wine.name;
self.moneyLabel.text = wine.money;
self.countLabel.text = [NSString stringWithFormat:@"%d", wine.count];
self.minusButton.enabled = (wine.count > );
} /**
* 加号点击
*/
- (IBAction)plusClick {
// 修改模型
self.wine.count++; // 修改数量label
self.countLabel.text = [NSString stringWithFormat:@"%d", self.wine.count]; // 减号能点击
self.minusButton.enabled = YES; // 通知代理(调用代理的方法)
// respondsToSelector:能判断某个对象是否实现了某个方法
if ([self.delegate respondsToSelector:@selector(wineCellDidClickPlusButton:)]) {
[self.delegate wineCellDidClickPlusButton:self];
}
} /**
* 减号点击
*/
- (IBAction)minusClick {
// 修改模型
self.wine.count--; // 修改数量label
self.countLabel.text = [NSString stringWithFormat:@"%d", self.wine.count]; // 减号按钮不能点击
if (self.wine.count == ) {
self.minusButton.enabled = NO;
} // 通知代理(调用代理的方法)
if ([self.delegate respondsToSelector:@selector(wineCellDidClickMinusButton:)]) {
[self.delegate wineCellDidClickMinusButton:self];
}
}
@end /****************** ViewController****************/
#import "ViewController.h"
#import "XMGWineCell.h"
#import "XMGWine.h"
#import "MJExtension.h" @interface ViewController () <UITableViewDataSource, XMGWineCellDelegate, UITableViewDelegate>
@property (weak, nonatomic) IBOutlet UIButton *buyButton;
@property (weak, nonatomic) IBOutlet UITableView *tableView;
/** 酒数据 */
@property (nonatomic, strong) NSArray *wineArray;
/** 总价 */
@property (weak, nonatomic) IBOutlet UILabel *totalPriceLabel; /** 购物车对象(存放需要购买的商品) */
@property (nonatomic, strong) NSMutableArray *wineCar;
@end @implementation ViewController
- (NSMutableArray *)wineCar
{
if (!_wineCar) {
_wineCar = [NSMutableArray array];
}
return _wineCar;
} - (NSArray *)wineArray
{
if (!_wineArray) {
self.wineArray = [XMGWine objectArrayWithFilename:@"wine.plist"];
}
return _wineArray;
} - (void)viewDidLoad {
[super viewDidLoad]; } #pragma mark - <XMGWineCellDelegate>
- (void)wineCellDidClickMinusButton:(XMGWineCell *)wineCell
{
// 计算总价
int totalPrice = self.totalPriceLabel.text.intValue - wineCell.wine.money.intValue; // 设置总价
self.totalPriceLabel.text = [NSString stringWithFormat:@"%d", totalPrice]; self.buyButton.enabled = totalPrice > ; // 将商品从购物车中移除
if (wineCell.wine.count == ) {
[self.wineCar removeObject:wineCell.wine];
}
} - (void)wineCellDidClickPlusButton:(XMGWineCell *)wineCell
{
// 计算总价
int totalPrice = self.totalPriceLabel.text.intValue + wineCell.wine.money.intValue; // 设置总价
self.totalPriceLabel.text = [NSString stringWithFormat:@"%d", totalPrice]; self.buyButton.enabled = YES; // 如果这个商品已经在购物车中,就不用再添加
if ([self.wineCar containsObject:wineCell.wine]) return; // 添加需要购买的商品
[self.wineCar addObject:wineCell.wine];
} #pragma mark - 按钮点击
- (IBAction)clear {
// 将模型里面的count清零
for (XMGWine *wine in self.wineCar) {
wine.count = ;
} // 刷新
[self.tableView reloadData]; // 清空购物车数据
[self.wineCar removeAllObjects]; self.buyButton.enabled = NO;
self.totalPriceLabel.text = @"";
} - (IBAction)buy {
// 打印出所有要买的东西
for (XMGWine *wine in self.wineCar) {
NSLog(@"%d件【%@】", wine.count, wine.name);
}
} #pragma mark - <UITableViewDataSource>
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.wineArray.count;
} - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *ID = @"wine";
XMGWineCell *cell = [tableView dequeueReusableCellWithIdentifier:ID]; cell.delegate = self;
cell.wine = self.wineArray[indexPath.row]; return cell;
} @end
购物车(代理)
四、KVO
关于kvo的介绍在前面有一章节专门讲过,那这里就不多说了
懒加载时添加监听
- (NSArray *)wineArray
{
if (!_wineArray) {
self.wineArray = [XMGWine objectArrayWithFilename:@"wine.plist"]; // 添加监听 监听count这个属性值的变化
for (XMGWine *wine in self.wineArray) {
[wine addObserver:self forKeyPath:@"count" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];
}
}
return _wineArray;
}
只要count属性值有变化,就会调用下面这个方法
#pragma mark - KVO监听
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(XMGWine *)wine change:(NSDictionary *)change context:(void *)context
{
// NSKeyValueChangeNewKey == @"new"
int new = [change[NSKeyValueChangeNewKey] intValue];
// NSKeyValueChangeOldKey == @"old"
int old = [change[NSKeyValueChangeOldKey] intValue]; if (new > old) { // 增加数量 点击了加号按钮
int totalPrice = self.totalPriceLabel.text.intValue + wine.money.intValue;
self.totalPriceLabel.text = [NSString stringWithFormat:@"%d", totalPrice];
self.buyButton.enabled = YES;
} else { // 数量减小 点击了减号按钮
int totalPrice = self.totalPriceLabel.text.intValue - wine.money.intValue;
self.totalPriceLabel.text = [NSString stringWithFormat:@"%d", totalPrice];
self.buyButton.enabled = totalPrice > ;
}
}
五、代理、通知、KVO对比
1、 通知(NSNotificationCenter\NSNotification)
任何对象之间都可以传递消息
使用范围:
1个对象可以发通知给N个对象
1个对象可以接受N个对象发出的通知
缺点:
必须得保证通知的名字在发出和监听时是一致的
2、 KVO
仅仅是能监听对象属性的改变(灵活度不如通知和代理)
3、 代理
使用范围
1个对象只能设置一个代理(假设这个对象只有1个代理属性)
1个对象能成为多个对象的代理
比`通知`规范(包括命名规范、利用程序员之间的交流)
建议使用`代理`多于`通知`
iOS开发——UI进阶篇(五)通知、代理、kvo的应用和对比,购物车的更多相关文章
- iOS开发——UI进阶篇(十五)Quartz2D介绍
一.Quartz2D简介 1.什么是Quartz2DQuartz 2D是一个二维绘图引擎,同时支持iOS和Mac系统 Quartz 2D能完成的工作绘制图形 : 线条\三角形\矩形\圆\弧等绘制文字绘 ...
- iOS开发——UI进阶篇(三)自定义不等高cell,如何拿到cell的行高,自动计算cell高度,(有配图,无配图)微博案例
一.纯代码自定义不等高cell 废话不多说,直接来看下面这个例子先来看下微博的最终效果 首先创建一个继承UITableViewController的控制器@interface ViewControll ...
- iOS开发——UI进阶篇(七)程序启动原理、打电话、发短信
一.Info.plist常见的设置 1.建立一个工程后,会在Supporting files文件夹下看到一个“工程名-Info.plist”的文件,该文件对工程做一些运行期的配置,非常重要,不能删除 ...
- iOS开发——UI进阶篇(十七)CALayer,核心动画基本使用
一.CALayer简介 1.CALayer在iOS中,文本输入框.一个图标等等,这些都是UIView你能看得见摸得着的东西基本上都是UIView,比如一个按钮.一个文本标签.一个其实UIView之所以 ...
- iOS开发——UI进阶篇(十二)事件处理,触摸事件,UITouch,UIEvent,响应者链条,手势识别
触摸事件 在用户使用app过程中,会产生各种各样的事件 一.iOS中的事件可以分为3大类型 触摸事件加速计事件远程控制事件 响应者对象在iOS中不是任何对象都能处理事件,只有继承了UIResponde ...
- iOS开发——UI进阶篇(十九)UISearchBar控件简介
最近用到搜索功能.总结一下 搜索,无疑可以使用UISearchBar控件! 那就先了解一下UISearchBar控件吧! UISearchBar控件就是要为你完成搜索功能的一个专用控件.它集成了很多你 ...
- iOS开发——UI进阶篇(十六)Quartz2D实战小例子
一.画线 只有在drawRect中才能获取到跟view相关联的上下文 - (void)drawRect:(CGRect)rect {} 一条线 // 1.获取跟当前View相关联的layer上下文(画 ...
- iOS开发——UI进阶篇(九)block的巧用
前面有提到通知.代理.kvo等方法来协助不同对象之间的消息通信,今天再介绍一下用block来解决这个问题 接着前面的例子 这里将功能在复述一遍 我把用block和通知放在一起比较,当然代理和kvo如何 ...
- iOS开发——UI进阶篇(八)pickerView简单使用,通过storyboard加载控制器,注册界面,通过xib创建控制器,控制器的view创建,导航控制器的基本使用
一.pickerView简单使用 1.UIPickerViewDataSource 这两个方法必须实现 // 返回有多少列 - (NSInteger)numberOfComponentsInPicke ...
随机推荐
- CSS3-box-flex弹性盒布局
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" ...
- css013 构建基于浮动的布局
css013 构建基于浮动的布局 基于浮动的布局时利用float属性是网页上的元素并排,并创建列 float有三个值:left .right .none 1.假设要把一张图片浮动到网页的左侧 .flo ...
- 线性回归和批量梯度下降法python
通过学习斯坦福公开课的线性规划和梯度下降,参考他人代码自己做了测试,写了个类以后有时间再去扩展,代码注释以后再加,作业好多: import numpy as np import matplotlib. ...
- apache无法正常启动,80端口被占用的解决方法
apache无法正常启动,80端口被占用的解决方法 网上的方法: 仔细查看提示: make_sock: could not bind to address 0.0.0.0:80 恍然大悟,计算机上安装 ...
- Java对象的多态性(转型)
多态性在面向对象中主要有两种体现: <1>方法的重载与覆写 <2>对象的多态性 对象的多态性:向上转型:子类对象-->父类对象,向上转型会自动完成 向下转型:父类对象-- ...
- 解惑好文:移动端H5页面高清多屏适配方案 (转)
转自:http://mobile.51cto.com/web-484304.htm https://github.com/amfe/lib-flexible/blob/master/src/makeg ...
- MongoDB学习笔记(索引)(转)
一.索引基础: MongoDB的索引几乎与传统的关系型数据库一模一样,这其中也包括一些基本的优化技巧.下面是创建索引的命令: > db.test.ensureIndex({" ...
- mysql存储过程之异常处理篇
mysql存储过程也提供了对异常处理的功能:通过定义HANDLER来完成异常声明的实现 语法如下: DECLARE handler_type HANDLER FOR condition_value[, ...
- eclipse的安装环境及eclipse下maven的配置安装
之前安装zookeeper的时候,就配置过linux下的java环境,即安装过linux JDK,配置过JAVA_HOME 和PATH 变量,,, 现在要运行一个java客户端,来消费kafka ...
- sql server 得到数据库字典
SELECT 表名=case when a.colorder=1 then d.name else '' end, 表说明=case when a. ...