UI:用UITableView制作通讯录的关键代码
分析{功能分析(打电话、添加联系人、修改联系人),模块分析(联系人展示、详情模块、添加模块)}
拿到一个项目,首先分析项目框架(工程框架)
首先:判断是否是用户第一次安装:(如果是的,那就加载用户引导页面)(如果不是,那就显示用户联系人的主页面)
其次:用户联系人的主页面VC(用一个协助类 addressbookheleper类(做数据处理相关的内容,属于MVC的M层。只处理相关的数据,这里是为VC瘦身)去提供相应的方法 给 controller (ContactListViewController) )这里面有这几个方法:为VC提供tableViewCell某一分区得到行数、分区个数、对应的分区的标题、右侧的索引、是否要删除某分区、是否要删除某一行、移动某分区的某一行、返回对应行的联系人、添加联系人。
#import "AppDelegate.h"
#import "ContactListViewController.h"
#import "MainNavigationController.h"//程序导航栏是同样的风格,所以这里用公用的类 @interface AppDelegate () @end @implementation AppDelegate -(void)dealloc{
[_window release];
[super dealloc];
} - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible]; //判断是否是第一次安装
//如果是,则指定为引导用户页为第一启动(为 window 的跟视图控制器)否则进入程序的主页面 //设置 根视图控制器
ContactListViewController * mainVC = [[ContactListViewController alloc]initWithStyle:UITableViewStylePlain];
//创建导航控制器
MainNavigationController * navl = [[MainNavigationController alloc]initWithRootViewController:mainVC];
//指定为 window 根视图控制器
self.window.rootViewController = navl;
//释放所有权
[mainVC release];
[navl release]; return YES;
}
Appdelegate.m文件
#import <Foundation/Foundation.h>
#import "Contact.h" @interface AddressBookHelper : NSObject //提供相应的方法,给对应的 controller (ContactListViewController) + (NSInteger)numberOfSection;//返回分区个数 + (NSInteger)numberOfRowsInSection:(NSInteger)section;//返回对应分区的行数 + (NSString *)titleForHeaderInSection:(NSInteger)section;//返回对应分区的标题 + (NSArray *)sectionIndexTitles;//返回右侧索引的标题 #pragma mark---delete
+ (BOOL)isNeedToDeleteWholeSection:(NSInteger)section;//是否要删除整个分区 + (void)deleteWholeSection:(NSInteger)section;//删除整个分区 + (void)deleteRowAtIndexPath:(NSIndexPath *)indexPath;//删除一行 #pragma mark---move
+ (void)moveFromIndexPath:(NSIndexPath *)sourceIndexPath ToIndexPath:(NSIndexPath *)destinationindexPath;//移动某分区某行 #pragma mark---返回对应行所需的联系人
+ (Contact *)contactAtIndexPath:(NSIndexPath *)indexPath; #pragma mark---添加联系人
+(void)addContact:(Contact *)newContact; @end
方法的声明
//
// AddressBookHelper.m #import "AddressBookHelper.h"
#import <UIKit/UIKit.h> /*
AddressHelper 类 是通讯录列表的界面的辅助类,帮助(ContactListViewController )做数据处理相关的内容,为 ContactListViewController 瘦身,该类可有可无 属于 MVC 的 M 层的类
M层的类 只处理相关的数据(和数据有关的类都是M层)如:数据解析类 数据请求类 数据本地化
*/
@interface AddressBookHelper ()
//存储外层的大字典
@property(nonatomic,retain)NSMutableDictionary * dataSource;
//存储拍好序的 key
@property(nonatomic,retain)NSMutableArray * sortedKeys; @end @implementation AddressBookHelper
static AddressBookHelper * helper ;//让生命周期与程序的生命周期一致
//单例方法
+ (AddressBookHelper *)defaultHelper{
//安全处理保证多线程下是安全的
@synchronized(self){
if (!helper) {
helper = [[AddressBookHelper alloc]init];
[helper readDataFromPlist];//获取本地 plist 文件
}
}
return helper;
} //获取本地文件
-(void)readDataFromPlist{
//获取文件。获取外层字典的信息
NSString * filePath = [[NSBundle mainBundle] pathForResource:kPlistName ofType:@"plist"];
NSDictionary * dict = [NSDictionary dictionaryWithContentsOfFile:filePath];
self.dataSource = [NSMutableDictionary dictionaryWithCapacity:dict.count];
//2.1遍历外层字典的key
for (NSString * key in dict) {
// NSArray * group = [dict objectForKey:key];
//2.2通过key 获取联系人分组数据
NSArray * group = dict[key];
//2.3创建一个可变数组 来存放联系人对象
NSMutableArray * perArr = [NSMutableArray arrayWithCapacity:group.count];
//2.4遍历分组数组 获得联系人小字典
for (NSDictionary * dic in group) {
//2.5将对象封装到字典
Contact * contact = [[Contact alloc]initWithDic:dic];
//2.6将联系人字典添加到存放对象的数组
[perArr addObject:contact];
[contact release];
}
//2.7将存放对象的数组以及key 存放到 大字典里
[self.dataSource setObject:perArr forKey:key];//(可变字典可以这样格式写,不可变的不能这样写)
//获得排好序的 key
NSArray * sorted = [[_dataSource allKeys]sortedArrayUsingSelector:@selector(compare:)];
self.sortedKeys = [NSMutableArray arrayWithArray:sorted];
}
} //提供相应的方法,给对应的 controller (ContactListViewController) //返回分区个数
+ (NSInteger)numberOfSection{
return [[self defaultHelper].dataSource count];
// [self defaultHelper].sortedKeys.count;
} //返回对应分区的行数
+ (NSInteger)numberOfRowsInSection:(NSInteger)section{
return [helper.dataSource [helper.sortedKeys[section]] count];
} //返回对应分区的标题
+ (NSString *)titleForHeaderInSection:(NSInteger)section{
return helper.sortedKeys[section];
} //返回右侧索引的标题
+ (NSArray *)sectionIndexTitles{
return helper.sortedKeys;
} #pragma mark---delete
//是否要删除整个分区
+ (BOOL)isNeedToDeleteWholeSection:(NSInteger)section{
//获取对应分组的联系人数组
NSArray * group = helper.dataSource[helper.sortedKeys[section]];
//如果该分组只有一元素,就代表只有一个人
if (group.count == ) {
return YES;//则需要删除整个分区
}
return NO;//否则不需要删除
} //删除整个分区
+ (void)deleteWholeSection:(NSInteger)section{
//1.获取对应的 key
NSString * key = helper.sortedKeys[section];
//2.从字典中删除 key 的分组数组
[helper.dataSource removeObjectForKey:key];
//3.从key 数组中删除 key
[helper.sortedKeys removeObject:key]; /*
//从字典删除对应的分组的数组
[helper.dataSource removeObjectForKey:helper.sortedKeys[section]];
//从拍好序的 key 数组中移除 key 值
[helper.sortedKeys removeObjectAtIndex:section];
*/
} //删除一行
+ (void)deleteRowAtIndexPath:(NSIndexPath *)indexPath{
//1.获取对应的分组
NSMutableArray * group = helper.dataSource[helper.sortedKeys[indexPath.section]];//这里要导入 <UIKit/UIKit.h>框架
//2.从对应的分组中移除
[group removeObjectAtIndex:indexPath.row];//根据下标索引去删除
} #pragma mark---move
//移动某分区某行
+ (void)moveFromIndexPath:(NSIndexPath *)sourceIndexPath ToIndexPath:(NSIndexPath *)destinationindexPath{
/*
//获取对应分组的数组
NSMutableArray * group = helper.dataSource[helper.sortedKeys[sourceIndexPath.section]];
//获取对应的联系人
Contact * per =[[group objectAtIndex:sourceIndexPath.row]retain];
//从对应位置移除
[group removeObjectAtIndex:sourceIndexPath.row];
//插入联系人
[group insertObject:per atIndex:destinationindexPath.row];
*/ NSString * key = [helper.sortedKeys objectAtIndex:sourceIndexPath.section];
NSMutableArray * group = [helper.dataSource objectForKey:key];
Contact * per = [[group objectAtIndex:sourceIndexPath.row]retain];
[group removeObjectAtIndex:sourceIndexPath.row];
[group insertObject:per atIndex:destinationindexPath.row];
[per release]; }
#pragma mark---返回对应行所需的联系人
+ (Contact *)contactAtIndexPath:(NSIndexPath *)indexPath{
//测试的假数据
// Contact * per = [[Contact alloc]initWithDic:@{@"name":@"张三",@"gender":@"男",@"phoneNum":@"13523526303",@"photo":@"jia"}];
// return per; Contact * per = helper.dataSource[helper.sortedKeys[indexPath.section]][indexPath.row];
return per; //对的写法
// NSArray * group = helper.dataSource[helper.sortedKeys[indexPath.section]];
// Contact * per = group[indexPath.row];
// return per; //对
// return helper.dataSource[helper.sortedKeys[indexPath.section]][indexPath.row];
} #pragma mark---添加联系人
+(void)addContact:(Contact *)newContact{ } -(void)dealloc{
self.dataSource = nil;
self.sortedKeys = nil;
[super dealloc]; } @end
方法的实现
并提供相对应的借口,供VC里的数据处理使用
然后:在联系人的主页面要实现对数据与用户页面的交互功能
#import <UIKit/UIKit.h> @interface ContactListViewController : UITableViewController<UITableViewDelegate> @end 、、、、、、、ContactListViewController.m文件
//
// ContactListViewController.m #import "ContactListViewController.h"
#import "AddressBookHelper.h"
#import "Contact.h"
#import "AddContactViewController.h"
#import "MainNavigationController.h"
#import "DetailViewController.h"
#import "CustomContactCellTabviewCell.h" @interface ContactListViewController ()<MakeACallDelegate> @end @implementation ContactListViewController - (void)viewDidLoad {
[super viewDidLoad];
[self customizedNavBar];//配置该页面的导航条
//注册 cell
[self.tableView registerClass:[CustomContactCellTabviewCell class] forCellReuseIdentifier:@"reuse"];
}
#pragma mark---配置该页面的导航条
-(void)customizedNavBar{
self.navigationItem.title = @"XXXX通讯录";
self.navigationItem.rightBarButtonItem = self.editButtonItem;
UIBarButtonItem * left = [[UIBarButtonItem alloc]initWithImage:[[UIImage imageNamed:@"add_contact"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal] style:UIBarButtonItemStylePlain target:self action:@selector(handleAddAction:)];
self.navigationItem.leftBarButtonItem = left;
[left release];
}
#pragma mark---模态进入添加联系人页面
-(void)handleAddAction:(UIBarButtonItem *)sender{
AddContactViewController * addContactVC = [[AddContactViewController alloc]init];
MainNavigationController * mainVC = [[MainNavigationController alloc]initWithRootViewController:addContactVC];
mainVC.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentViewController:mainVC animated:YES completion:^{ }];
[addContactVC release];
[mainVC release];
}
#pragma mark--内存警告处理
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
if ([self isViewLoaded] && !self.view.window) {
self.view = nil;
}
} #pragma mark - UITableViewDataSource 两个必须实现方法
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
// 通过助手类 返回分区的个数
return [AddressBookHelper numberOfSection];
} - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// 通过助手类 返回分区的行数
return [AddressBookHelper numberOfRowsInSection:section];
} #pragma mark---信息展示
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
CustomContactCellTabviewCell * cell = [tableView dequeueReusableCellWithIdentifier:@"reuse" forIndexPath:indexPath];
//cell 控件的赋值操作
//1.
Contact * contact = [AddressBookHelper contactAtIndexPath:indexPath];
//2.
// cell.contact = contact;
//为系统默认的控件赋值
[cell configureCell:contact];
//视图控制器完成拨打电话
cell.delegate = self;
cell.indexPath = indexPath;
return cell;
} -(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section{
return [AddressBookHelper titleForHeaderInSection:section];
} #pragma mark---右侧的索引的标题
-(NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView{
return [AddressBookHelper sectionIndexTitles];
} #pragma mark--- cell 行高设置
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
return ;
} #pragma mark---tableViewcell 是否可以编辑
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
return YES;
} /* */
#pragma mark---重写方法去编辑 tableviewcell
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
if ([AddressBookHelper isNeedToDeleteWholeSection:indexPath.section]) {
//数据源删除
[AddressBookHelper deleteWholeSection:indexPath.section];
//UI 界面
[tableView deleteSections:[NSIndexSet indexSetWithIndex:indexPath.section] withRowAnimation:UITableViewRowAnimationLeft];
}else{
//数据源删除
[AddressBookHelper deleteRowAtIndexPath:indexPath];
//UI 界面
[tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
}
else if (editingStyle == UITableViewCellEditingStyleInsert) {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
}
} #pragma mark---移动操作
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath {
//调用助手类 完成对应的移动操作
[AddressBookHelper moveFromIndexPath:fromIndexPath ToIndexPath:toIndexPath];
} #pragma mark---移动设置(cell是否可以移动)
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath {
return YES;
} #pragma makr---限制移动的范围,禁止跨区移动
-(NSIndexPath *)tableView:(UITableView *)tableView targetIndexPathForMoveFromRowAtIndexPath:(NSIndexPath *)sourceIndexPath toProposedIndexPath:(NSIndexPath *)proposedDestinationIndexPath{
if (sourceIndexPath.section == proposedDestinationIndexPath.section) {
return proposedDestinationIndexPath;
}
return sourceIndexPath;
} #pragma mark---点击进入详情页面 (UITableViewDelegate)
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
//push 进入联系人详情页面
DetailViewController * detailVC = [[DetailViewController alloc]init];
//属性传值 [self.navigationController pushViewController:detailVC animated:YES];
[detailVC release];
} #pragma mark---MakeACallDelegate 协议方法实现
//拨打电话
-(void)dial:(NSIndexPath *)indexPath{
Contact * contact = [AddressBookHelper contactAtIndexPath:indexPath];
UIWebView * webview = [[UIWebView alloc]init];
[webview loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"tel:%@",contact.phoneNum]]]];
[webview release]; } @end
ContactListViewController.m & .h文件
其中要用到的数据层类 M
Contact.h文件 #import <Foundation/Foundation.h> @interface Contact : NSObject
@property(nonatomic,copy)NSString * name;
@property(nonatomic,copy)NSString * gender;
@property(nonatomic,copy)NSString * phoneNum;
@property(nonatomic,copy)NSString * photo; -(instancetype)initWithDic:(NSDictionary *)dic;
@end Contact.m 文件 #import "Contact.h" @implementation Contact -(instancetype)initWithDic:(NSDictionary *)dic{
self = [super init];
if (self) {
//KVC 赋值
[self setValuesForKeysWithDictionary:dic];
}
return self;
}
//对应的KVC 赋值的错误安全处理
-(void)setValue:(id)value forUndefinedKey:(NSString *)key{ }
-(void)dealloc{
self.name = nil;
self.gender = nil;
self.phoneNum = nil;
self.photo = nil;
[super dealloc];
}
@end
contact.h & .m 文件
视图类 V
#import <UIKit/UIKit.h>
@class Contact; //为 callBtn 制订协议,实现拨打电话
@protocol MakeACallDelegate <NSObject> -(void)dial:(NSIndexPath *)indexPath; @end @interface CustomContactCellTabviewCell : UITableViewCell
@property (nonatomic ,retain) UIImageView *photoView;
@property (nonatomic ,retain) UILabel *nameLabel;
@property (nonatomic ,retain) UILabel *phoneLabel;
@property (nonatomic ,retain) UIButton *callBtn;
@property(nonatomic,assign)id<MakeACallDelegate>delegate;
@property(nonatomic,retain)NSIndexPath * indexPath;//存储当前点击 call 的索引
@property(nonatomic,retain)Contact * contact;//声明一个联系人对象的属性
//为cell 上的控件赋值
-(void)configureCell:(Contact *)contact;
@end //
// CustomContactCellTabviewCell.m #import "CustomContactCellTabviewCell.h"
#import "Contact.h"
#import "AddressBookHelper.h" @implementation CustomContactCellTabviewCell - (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
[self.contentView addSubview:self.photoView];
[self.contentView addSubview:self.nameLabel];
[self.contentView addSubview:self.phoneLabel];
[self.contentView addSubview:self.callBtn];
} return self;
} #pragma lazy loading 实现控件的创建
- (UIImageView *)photoView {
if (!_photoView) {
self.photoView = [[UIImageView alloc] initWithFrame:CGRectMake(, , , )];
_photoView.layer.cornerRadius = 5.0;
_photoView.layer.masksToBounds = YES;
} return [[_photoView retain]autorelease]; }
- (UILabel *)nameLabel {
if (!_nameLabel) {
self.nameLabel = [[UILabel alloc] initWithFrame:CGRectMake(, , self.frame.size.width / , )];
}
return [[_nameLabel retain]autorelease]; }
- (UILabel *)phoneLabel {
if (!_phoneLabel) {
self.phoneLabel = [[UILabel alloc] initWithFrame:CGRectMake( + self.frame.size.width / , , self.frame.size.width / , )];
}
return [[_phoneLabel retain]autorelease]; }
- (UIButton *)callBtn {
if (!_callBtn) {
self.callBtn = [UIButton buttonWithType:UIButtonTypeSystem];
_callBtn.frame = CGRectMake(self.frame.size.width - , , , );
//添加触发
[_callBtn addTarget:self action:@selector(handleCall:) forControlEvents:UIControlEventTouchUpInside];
[_callBtn setImage:[UIImage imageNamed:@"action_call"] forState:UIControlStateNormal];
}
return _callBtn;
}
#pragma mark---打电话按钮
- (void)handleCall:(UIButton *)sender {
if (!_delegate && [_delegate respondsToSelector:@selector(dial:)]) {
[_delegate dial:self.indexPath];
}
} - (void)dealloc {
self.nameLabel = nil;
self.photoView = nil;
self.phoneLabel = nil;
self.callBtn = nil;
[super dealloc];
} - (void)awakeFromNib {
// Initialization code
} - (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated]; // Configure the view for the selected state
} //第一种 : 自定义方法实现对 cell 的控件的赋值
-(void)configureCell:(Contact *)contact{
self.nameLabel.text = contact.name;
self.phoneLabel.text = contact.phoneNum;
self.photoView.image = [UIImage imageNamed:contact.photo]; } //第二种 :重写 setter 方法 为 cell 上的方法赋值
/*
-(void)setContact:(Contact *)contact{
if (_contact != contact) {
[_contact release];
_contact = [contact retain];
}
self.nameLabel.text = contact.name;
self.phoneLabel.text = contact.phoneNum;
self.photoView.image = [UIImage imageNamed:contact.photo]; }
*/ @end
contactContactCelltableCell.h & .m 文件
其他参考:参考
UI:用UITableView制作通讯录的关键代码的更多相关文章
- iOS开发UI篇—UITableview控件简单介绍
iOS开发UI篇—UITableview控件简单介绍 一.基本介绍 在众多移动应⽤用中,能看到各式各样的表格数据 . 在iOS中,要实现表格数据展示,最常用的做法就是使用UITableView,UIT ...
- iOS开发UI篇—UITableview控件基本使用
iOS开发UI篇—UITableview控件基本使用 一.一个简单的英雄展示程序 NJHero.h文件代码(字典转模型) #import <Foundation/Foundation.h> ...
- iOS开发UI篇—UITableview控件使用小结
iOS开发UI篇—UITableview控件使用小结 一.UITableview的使用步骤 UITableview的使用就只有简单的三个步骤: 1.告诉一共有多少组数据 方法:- (NSInteger ...
- Fire Balls 10——UI界面的制作
版权申明: 本文原创首发于以下网站: 博客园『优梦创客』的空间:https://www.cnblogs.com/raymondking123 优梦创客的官方博客:https://91make.top ...
- 在android程序中加入widget(窗口小部件)并与之交互的关键代码
摘要: widget(窗口小部件)可以增强应用程序的交互性, 是很多应用中都会用到的功能,本文不求大而全,但是会给出程序与widget交互的关键代码 正文: 其实widget是嵌入(embedded) ...
- 实现手电筒Flash Light 关键代码
实现手电筒Flash Light 关键代码 实现Flash的逻辑 view.setOnClickListener(new OnClickListener() { @Override public vo ...
- Jquery UI 组合树 - ComboTree 集成Wabacus4.1 代码剖析
Jquery UI 1.3 (组合树 - ComboTree ) 集成Wabacus4.1 集成Spring 代码剖析 使用时,请下载需要Jquery ui包进行配置 combotree.js 的代码 ...
- Android之打开闪光灯关键代码
在AndroidManifest中注册相应的权限: <uses-permission android:name="android.permission.FLASHLIGHT" ...
- easyui-datagrid通过action从数据库获取数据的关键代码
实际上是结合struts2来从数据获取json格式的数据. 关键代码: GetUserAction.java代码 package com.log.control; import java.io ...
随机推荐
- 【2017多校训练2+计算几何+板】HDU 6055 Regular polygon
http://acm.hdu.edu.cn/showproblem.php?pid=6055 [题意] 给定n个格点,问有多少个正多边形 [思路] 因为是格点,只可能是正方形 枚举正方形的对角线,因为 ...
- react.js 父子组件数据绑定实时通讯
import React,{Component} from 'react' import ReactDOM from 'react-dom' class ChildCounter extends Co ...
- 全局Session-GlobalSession
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; import org.spri ...
- 《TCP/IP详解卷1:协议》——第3章 IP:网际协议(转载)
1.引言 IP是TCP/IP协议族中最核心的协议.所有的TCP.UDP.ICMP及IGMP数据都以IP数据报格式传输.IP提供不可靠. 无连接的数据报传送服务. (1)不可靠 它不能保证IP数据报能成 ...
- Speculative store buffer
A speculative store buffer is speculatively updated in response to speculative store memory operatio ...
- Piggy-Bank--hdu1114(完全背包)
http://acm.hdu.edu.cn/showproblem.php?pid=1114 Problem Description Before ACM can do anything, a bud ...
- lombok注解简化实体类getting 和 setting 方法
实体类注解,将以往的get/set方法简化为标签注解,让代码看着更简洁. Maven依赖: <dependency> <groupId>org.projectlombok< ...
- 简论远程通信(RPC,Webservice,RMI,JMS的区别)
RPC(Remote Procedure Call Protocol)RPC使用C/S方式,采用http协议,发送请求到服务器,等待服务器返回结果.这个请求包括一个参数集和一个文本集,通常形成“cla ...
- @Aspect注解无效
Pointcut的execution配置正确的话,检查下,是否加了以下jar包 <!-- http://mvnrepository.com/artifact/org.aspectj/aspect ...
- [vxlan] 一 Why VXLAN
想了解一个事物/概念,最好的办法是知道它是为什么出现的,为了解决那些问题而出现.这里,就用这种方式来学习一下VXLAN VXLAN (Virtual eXtensible Local Area Net ...