2013年2月5日
UITableView是app开发中常用到的控件,功能很强大,多用于数据的显示。下面以一个简单的实例来介绍tableview的基本用法。(适合新手,高手飘过)
- @interface TableViewTestViewController : UIViewController<UITableViewDataSource,UITableViewDelegate>{
-
- UITableView *DataTable;
-
- NSMutableArray *dataArray1; //定义数据数组1
-
- NSMutableArray *dataArray2;//定义数据数组2
-
- NSMutableArray *titleArray;//定义标题数组
-
- }
-
-
-
- - (void)viewDidLoad
-
- {
-
- [superviewDidLoad];
-
- //初始化tableview
-
- DataTable = [[UITableViewalloc] initWithFrame:CGRectMake(0, 0, 320, 420)];//指定位置大小
-
- [DataTablesetDelegate:self];//指定委托
-
- [DataTablesetDataSource:self];//指定数据委托
-
- [self.viewaddSubview:DataTable];//加载tableview
-
-
-
- dataArray1 = [[NSMutableArrayalloc] initWithObjects:@"中国", @"美国", @"英国", nil];//初始化数据数组1
-
- dataArray2 = [[NSMutableArrayalloc] initWithObjects:@"黄种人", @"黑种人", @"白种人", nil];//初始化数据数组2
-
- titleArray = [[NSMutableArrayalloc] initWithObjects:@"国家", @"种族", nil];//初始化标题数组
-
-
-
- }
-
-
-
- - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
-
- {
-
- // Return YES for supported orientations
-
- return (interfaceOrientation == UIInterfaceOrientationPortrait);
-
- }
-
-
-
-
-
- //每个section显示的标题
-
- - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section{
-
- switch (section) {
-
- case 0:
-
- return [titleArray objectAtIndex:section];//提取标题数组的元素用来显示标题
-
- case 1:
-
- return [titleArray objectAtIndex:section];//提取标题数组的元素用来显示标题
-
- default:
-
- return @"Unknown";
-
- }
-
-
-
- }
-
-
-
- //指定有多少个分区(Section),默认为1
-
- - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
-
- return [titleArray count];//返回标题数组中元素的个数来确定分区的个数
-
- }
-
-
-
- //指定每个分区中有多少行,默认为1
-
- - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
-
- switch (section) {
-
- case 0:
-
- return [dataArray1 count];//每个分区通常对应不同的数组,返回其元素个数来确定分区的行数
-
- break;
-
- case 1:
-
- return [dataArray2 count];
-
- break;
-
- default:
-
- return 0;
-
- break;
-
- }
-
- }
-
-
-
- //绘制Cell
-
- -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
-
-
-
- static NSString *CellIdentifier = @"Cell";
-
- //初始化cell并指定其类型,也可自定义cell
-
- UITableViewCell *cell = (UITableViewCell*)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
-
- if(cell == nil)
-
- {
-
- cell = [[[UITableViewCellalloc]
-
- initWithFrame:CGRectZero
-
- reuseIdentifier:CellIdentifier] autorelease];
-
- }
-
- switch (indexPath.section) {
-
- case 0://对应各自的分区
-
- [[cell textLabel] setText:[dataArray1 objectAtIndex:indexPath.row]];//给cell添加数据
-
- break;
-
- case 1:
-
- [[cell textLabel] setText:[dataArray2 objectAtIndex:indexPath.row]];
-
- break;
-
- default:
-
- [[cell textLabel] setText:@"Unknown"];
-
- }
-
- return cell;//返回cell
-
- }
上面的例子在功能上介绍了tableview的使用,但其在数据处理上具有很大的局限性。当我们要从服务器上请求数据,面对多种可能的数据(主要指数组的个数不稳定)此时上面的switch将无法满足我们的需求了。使用switch可是代码的结构清晰明了,但其局限性很致命(switch中case的个数无法动态指定),下面的另一种方法可解决上述问题。
代码在原由基础上进行的修改:
- @interface TableViewTestViewController : UIViewController<UITableViewDataSource,UITableViewDelegate>{
-
- UITableView *DataTable;
-
- NSMutableArray *dataArray1;
-
- NSMutableArray *dataArray2;
-
- NSMutableArray *titleArray;
-
- NSMutableArray *dataArray; //加入了用于保存数组的数组 dataArray
-
- }
-
-
-
- - (void)viewDidLoad
-
- {
-
- [superviewDidLoad];
-
- DataTable = [[UITableViewalloc] initWithFrame:CGRectMake(0, 0, 320, 420)];
-
- [DataTablesetDelegate:self];
-
- [DataTablesetDataSource:self];
-
- [self.viewaddSubview:DataTable];
-
-
-
- dataArray1 = [[NSMutableArrayalloc] initWithObjects:@"中国", @"美国", @"英国", nil];
-
- dataArray2 = [[NSMutableArrayalloc] initWithObjects:@"黄种人", @"黑种人", @"白种人", nil];
-
- titleArray = [[NSMutableArrayalloc] initWithObjects:@"国家", @"种族", nil];
-
- dataArray = [[NSMutableArrayalloc] initWithObjects:dataArray1, dataArray2, nil]; //初始化dataArray,元素为数组
-
-
-
- }
-
-
-
-
-
- - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
-
- {
-
- // Return YES for supported orientations
-
- return (interfaceOrientation == UIInterfaceOrientationPortrait);
-
- }
-
- //制定个性标题,这里通过UIview来设计标题,功能上丰富,变化多。
-
- - (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
-
- UIView *view = [[[UIViewalloc] initWithFrame:CGRectMake(0, 0, 320, 40)] autorelease];
-
- [view setBackgroundColor:[UIColorbrownColor]];//改变标题的颜色,也可用图片
-
- UILabel *label = [[UILabelalloc] initWithFrame:CGRectMake(5, 5, 100, 30)];
-
- label.textColor = [UIColorredColor];
-
- label.backgroundColor = [UIColorclearColor];
-
- label.text = [titleArrayobjectAtIndex:section];
-
- [view addSubview:label];
-
- return view;
-
- }
-
- //指定标题的高度
-
- - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section{
-
- return 40;
-
- }
-
-
-
- //每个section显示的标题,有了上面的这个就不要了
-
- - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section{
-
- }
-
-
-
- //指定有多少个分区(Section),默认为1
-
- - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
-
- return [titleArraycount];
-
- }
-
-
-
- //指定每个分区中有多少行,默认为1
-
- - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
-
- /* switch (section) {
-
- case 0:
-
- return [dataArray1 count];
-
- break;
-
- case 1:
-
- return [dataArray2 count];
-
- break;
-
- default:
-
- return 0;
-
- break;
-
- }*/
-
- /* for(int i = 0; i < [titleArray count]; i++){
-
- if(section == i){
-
- return [[dataArray objectAtIndex:section] count];
-
- }
-
- }*/
-
- //上面的方法也是可行的,大家参考比较下
-
- return [[dataArray objectAtIndex:section] count]; //取dataArray中的元素,并根据每个元素(数组)来判断分区中的行数。
-
-
-
-
-
- }
-
-
-
- //绘制Cell
-
- -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
-
-
-
- static NSString *CellIdentifier = @"Cell";
-
-
-
- UITableViewCell *cell = (UITableViewCell*)[tableView
-
- dequeueReusableCellWithIdentifier:CellIdentifier];
-
- if(cell == nil)
-
- {
-
- cell = [[[UITableViewCellalloc]
-
- initWithFrame:CGRectZero
-
- reuseIdentifier:CellIdentifier] autorelease];
-
- }
-
-
-
- /*switch (indexPath.section) {
-
- case 0:
-
- [[cell textLabel]
-
- setText:[dataArray1 objectAtIndex:indexPath.row]];
-
- break;
-
- case 1:
-
- [[cell textLabel]
-
- setText:[dataArray2 objectAtIndex:indexPath.row]];
-
- break;
-
- default:
-
- [[cell textLabel]
-
- setText:@"Unknown"];
-
- }*/
-
- //上面的方法也可行,大家比较下。
-
- [[cell textLabel] setText:[[dataArrayobjectAtIndex:indexPath.section]objectAtIndex:indexPath.row]];
-
- //同上,取出dataArray中每个分区所对应的元素(数组),并通过其来取值。 (大家要有想像力, 复制代码试试就明白了)
-
-
-
- return cell;
-
-
-
- }
-
-
-
- //改变行的高度
-
- - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
-
- return40;
-
- }
转自:http://www.cnblogs.com/top5/archive/2012/05/17/2506604.html
UITableView是app开发中常用到的控件,功能很强大,多用于数据的显示。下面以一个简单的实例来介绍tableview的基本用法。(适合新手,高手飘过)
- @interface TableViewTestViewController : UIViewController<UITableViewDataSource,UITableViewDelegate>{
-
- UITableView *DataTable;
-
- NSMutableArray *dataArray1; //定义数据数组1
-
- NSMutableArray *dataArray2;//定义数据数组2
-
- NSMutableArray *titleArray;//定义标题数组
-
- }
-
-
-
- - (void)viewDidLoad
-
- {
-
- [superviewDidLoad];
-
- //初始化tableview
-
- DataTable = [[UITableViewalloc] initWithFrame:CGRectMake(0, 0, 320, 420)];//指定位置大小
-
- [DataTablesetDelegate:self];//指定委托
-
- [DataTablesetDataSource:self];//指定数据委托
-
- [self.viewaddSubview:DataTable];//加载tableview
-
-
-
- dataArray1 = [[NSMutableArrayalloc] initWithObjects:@"中国", @"美国", @"英国", nil];//初始化数据数组1
-
- dataArray2 = [[NSMutableArrayalloc] initWithObjects:@"黄种人", @"黑种人", @"白种人", nil];//初始化数据数组2
-
- titleArray = [[NSMutableArrayalloc] initWithObjects:@"国家", @"种族", nil];//初始化标题数组
-
-
-
- }
-
-
-
- - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
-
- {
-
- // Return YES for supported orientations
-
- return (interfaceOrientation == UIInterfaceOrientationPortrait);
-
- }
-
-
-
-
-
- //每个section显示的标题
-
- - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section{
-
- switch (section) {
-
- case 0:
-
- return [titleArray objectAtIndex:section];//提取标题数组的元素用来显示标题
-
- case 1:
-
- return [titleArray objectAtIndex:section];//提取标题数组的元素用来显示标题
-
- default:
-
- return @"Unknown";
-
- }
-
-
-
- }
-
-
-
- //指定有多少个分区(Section),默认为1
-
- - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
-
- return [titleArray count];//返回标题数组中元素的个数来确定分区的个数
-
- }
-
-
-
- //指定每个分区中有多少行,默认为1
-
- - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
-
- switch (section) {
-
- case 0:
-
- return [dataArray1 count];//每个分区通常对应不同的数组,返回其元素个数来确定分区的行数
-
- break;
-
- case 1:
-
- return [dataArray2 count];
-
- break;
-
- default:
-
- return 0;
-
- break;
-
- }
-
- }
-
-
-
- //绘制Cell
-
- -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
-
-
-
- static NSString *CellIdentifier = @"Cell";
-
- //初始化cell并指定其类型,也可自定义cell
-
- UITableViewCell *cell = (UITableViewCell*)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
-
- if(cell == nil)
-
- {
-
- cell = [[[UITableViewCellalloc]
-
- initWithFrame:CGRectZero
-
- reuseIdentifier:CellIdentifier] autorelease];
-
- }
-
- switch (indexPath.section) {
-
- case 0://对应各自的分区
-
- [[cell textLabel] setText:[dataArray1 objectAtIndex:indexPath.row]];//给cell添加数据
-
- break;
-
- case 1:
-
- [[cell textLabel] setText:[dataArray2 objectAtIndex:indexPath.row]];
-
- break;
-
- default:
-
- [[cell textLabel] setText:@"Unknown"];
-
- }
-
- return cell;//返回cell
-
- }
上面的例子在功能上介绍了tableview的使用,但其在数据处理上具有很大的局限性。当我们要从服务器上请求数据,面对多种可能的数据(主要指数组的个数不稳定)此时上面的switch将无法满足我们的需求了。使用switch可是代码的结构清晰明了,但其局限性很致命(switch中case的个数无法动态指定),下面的另一种方法可解决上述问题。
代码在原由基础上进行的修改:
- @interface TableViewTestViewController : UIViewController<UITableViewDataSource,UITableViewDelegate>{
-
- UITableView *DataTable;
-
- NSMutableArray *dataArray1;
-
- NSMutableArray *dataArray2;
-
- NSMutableArray *titleArray;
-
- NSMutableArray *dataArray; //加入了用于保存数组的数组 dataArray
-
- }
-
-
-
- - (void)viewDidLoad
-
- {
-
- [superviewDidLoad];
-
- DataTable = [[UITableViewalloc] initWithFrame:CGRectMake(0, 0, 320, 420)];
-
- [DataTablesetDelegate:self];
-
- [DataTablesetDataSource:self];
-
- [self.viewaddSubview:DataTable];
-
-
-
- dataArray1 = [[NSMutableArrayalloc] initWithObjects:@"中国", @"美国", @"英国", nil];
-
- dataArray2 = [[NSMutableArrayalloc] initWithObjects:@"黄种人", @"黑种人", @"白种人", nil];
-
- titleArray = [[NSMutableArrayalloc] initWithObjects:@"国家", @"种族", nil];
-
- dataArray = [[NSMutableArrayalloc] initWithObjects:dataArray1, dataArray2, nil]; //初始化dataArray,元素为数组
-
-
-
- }
-
-
-
-
-
- - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
-
- {
-
- // Return YES for supported orientations
-
- return (interfaceOrientation == UIInterfaceOrientationPortrait);
-
- }
-
- //制定个性标题,这里通过UIview来设计标题,功能上丰富,变化多。
-
- - (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
-
- UIView *view = [[[UIViewalloc] initWithFrame:CGRectMake(0, 0, 320, 40)] autorelease];
-
- [view setBackgroundColor:[UIColorbrownColor]];//改变标题的颜色,也可用图片
-
- UILabel *label = [[UILabelalloc] initWithFrame:CGRectMake(5, 5, 100, 30)];
-
- label.textColor = [UIColorredColor];
-
- label.backgroundColor = [UIColorclearColor];
-
- label.text = [titleArrayobjectAtIndex:section];
-
- [view addSubview:label];
-
- return view;
-
- }
-
- //指定标题的高度
-
- - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section{
-
- return 40;
-
- }
-
-
-
- //每个section显示的标题,有了上面的这个就不要了
-
- - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section{
-
- }
-
-
-
- //指定有多少个分区(Section),默认为1
-
- - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
-
- return [titleArraycount];
-
- }
-
-
-
- //指定每个分区中有多少行,默认为1
-
- - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
-
- /* switch (section) {
-
- case 0:
-
- return [dataArray1 count];
-
- break;
-
- case 1:
-
- return [dataArray2 count];
-
- break;
-
- default:
-
- return 0;
-
- break;
-
- }*/
-
- /* for(int i = 0; i < [titleArray count]; i++){
-
- if(section == i){
-
- return [[dataArray objectAtIndex:section] count];
-
- }
-
- }*/
-
- //上面的方法也是可行的,大家参考比较下
-
- return [[dataArray objectAtIndex:section] count]; //取dataArray中的元素,并根据每个元素(数组)来判断分区中的行数。
-
-
-
-
-
- }
-
-
-
- //绘制Cell
-
- -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
-
-
-
- static NSString *CellIdentifier = @"Cell";
-
-
-
- UITableViewCell *cell = (UITableViewCell*)[tableView
-
- dequeueReusableCellWithIdentifier:CellIdentifier];
-
- if(cell == nil)
-
- {
-
- cell = [[[UITableViewCellalloc]
-
- initWithFrame:CGRectZero
-
- reuseIdentifier:CellIdentifier] autorelease];
-
- }
-
-
-
- /*switch (indexPath.section) {
-
- case 0:
-
- [[cell textLabel]
-
- setText:[dataArray1 objectAtIndex:indexPath.row]];
-
- break;
-
- case 1:
-
- [[cell textLabel]
-
- setText:[dataArray2 objectAtIndex:indexPath.row]];
-
- break;
-
- default:
-
- [[cell textLabel]
-
- setText:@"Unknown"];
-
- }*/
-
- //上面的方法也可行,大家比较下。
-
- [[cell textLabel] setText:[[dataArrayobjectAtIndex:indexPath.section]objectAtIndex:indexPath.row]];
-
- //同上,取出dataArray中每个分区所对应的元素(数组),并通过其来取值。 (大家要有想像力, 复制代码试试就明白了)
-
-
-
- return cell;
-
-
-
- }
-
-
-
- //改变行的高度
-
- - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
-
- return40;
-
- }
转自:http://www.cnblogs.com/top5/archive/2012/05/17/2506604.html
这篇学习的主要内容是Multiview,在我们学习iphone旋转的时候,介绍过多个view的使用方法,不过这里的view和旋转屏幕中所指的多个view是不同的,旋转屏幕中涉及到的多个view是在一个xib文件中的,而我们这里所指的mulitview,则是指多个xib,在多个xib中进行view的切换,也就是从一个xib切换到另一个xib,而每个xib中只有一个view。
另外的一个不同点体现在创建项目的时候,到目前为止,我们创建的所有项目的template都是single view,这次创建的项目将使用新的template。
Multiview applicatin的基本架构,一般来说,一个multiview application会有一个主要的controller来控制view的呈现,这个主要的controller可以是toolbar(iphone上的Safari打开后,地下的一排按钮就是toolbar)或者是tab bar(iphone打开phone,最下面一个一个的tab),或者其他的一些控件,他们控制到底那个view应该显示,那个view应该被隐藏,也就是说,至少需要3个view才能实现view的切换,一个主要的controller view,2个其他的用于切换的view,主要的controller view是一直显示在屏幕上的,而其他的view中,只有1个会显示出来,其他的都被隐藏。ok,下面开始一步一步实现multiview吧,再说下去会越来越糊涂的。
0)项目简介
今天要做的例子中包含3个view,一个controller view,我们会使用toolbar,2个用于切换的view,一个蓝色底,一个黄色底,他们中间都有一个button,单击button会有一个警告框弹出,告诉用户当前显示的是哪个view。
1)创建一个工程,选择Empty Application
这次不再选择Single View Application,而选择Empty Application,项目中的所有文件我们都会手动进行添加。
单击Next按钮,之后的操作和创建Single View项目一样,设定项目名称“View Switcher”,设定项目保存路径,项目创建完成。
2)添加View Controller
由于我们使用的模板是Empty Application,因此当创建完项目后,只有以下一些文件
里面并没有我们需要的controller view,也没有任何xib文件,这些都是需要我们手动添加的。使用快捷键command+N或者菜单栏File>New>New File...,在弹出的窗口中,左边选择Cocoa Touch,右边选择UIViewController subclass,点击Next按钮
填写类名BIDSwitchViewController,其他都是默认选项(注意最后一个checkbox,如果选择了,则将创建一个和BIDSwitchViewController关联的xib文件,我们在这里可以选上,但是为了弄清楚view controller和xib文件是如何关联在一起的,在这个项目中我们暂时不选,后面我们会手动连接这两个文件),点击Next按钮。
选择保持的位置,保存在“View Switcher”目录下,完成创建。
BIDSwitchViewController是项目的最顶层的view controller(root controller),它用于控制另外2个view的切换,下面按照同样的方法,创建另外2个view controller,一个名字教BIDBlueViewController,另一个叫做BIDYellowViewController,他们都不需要关联xib,且都保存在“View Switcher”目录下。创建完成后的“View Switcher”结构如下
3)添加xib文件
使用快捷键command+N或者菜单栏File>New>New File...,在弹出的窗口中,左边选择User Interface,右边选择View,点击Next按钮
Device Family中选择iphone,点击Next
命名为SwitchView.xib,同样保持在“View Switcher”目录下,点击Create,完成创建。
使用同样的方法创建另外两个xib,分别命名为BlueView.xib和YellowView.xib。至此,我们所有的文件都已经创建完毕,整个的“View Switcher”结构图如下
接下来就是写代码的工作了。
4)编辑BIDAppDelegate文件
当一个app启动的时候,我们都会默认的把一个view载入当前的iphone窗口(application's main window),在这个例子中,这个view就是我们的root view,即BIDSwitchViewController。我们是在BIDAppDelegate文件中设置默认载入的view的,因此首先打开BIDAppDelegate.h,添加class BIDSwitchViewController,和它的一个property,如下
#import <UIKit/UIKit.h> @class BIDSwitchViewController; @interface BIDAppDelegate : UIResponder <UIApplicationDelegate> @property (strong, nonatomic) UIWindow *window; @property (strong, nonatomic) BIDSwitchViewController *switchViewController; @end
其中,@class是告诉BIDAppDelegate,后面的BIDSwitchViewController是一个类,应该以类的方式处理该对象,后面在声明property的时候,BIDAppDelegate就知道BIDSwitchViewController是一个类,不会不认该对象。
接着打开BIDAppDelegate.m,添加如下代码
#import "BIDAppDelegate.h" #import "BIDSwitchViewController.h" @implementation BIDAppDelegate @synthesize window = _window; @synthesize switchViewController; - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; // Override point for customization after application launch. self.switchViewController = [[BIDSwitchViewController alloc] initWithNibName:@"SwitchView" bundle:nil]; UIView *switchView = self.switchViewController.view; CGRect switchViewFrame = switchView.frame; switchViewFrame.origin.y += [UIApplication sharedApplication].statusBarFrame.size.height; switchView.frame = switchViewFrame; [self.window addSubview:switchView]; self.window.backgroundColor = [UIColor whiteColor]; [self.window makeKeyAndVisible]; return YES; } ......
首先import BIDSwitchViewController,然后声明synthesize,对应于头文件中的property。
didFinishLaunchingWithOption方法,当一个app载入完成后需要做一些什么事情,在这里,我们指定了哪个view被载入到windows中作为默认显示的view。
self.switchViewController = [[BIDSwitchViewControlleralloc] initWithNibName:@"SwitchView" bundle:nil];
通过xib(在旧的版本中,xib被称为nib,因此这里出现的是NibName)的名字来制定初始化哪个view
UIView *switchView = self.switchViewController.view;
获取view
CGRect switchViewFrame = switchView.frame;
得到view的frame,也就是这个view的显示位置,在前几篇的文章中提到过这个属性。
switchViewFrame.origin.y += [UIApplicationsharedApplication].statusBarFrame.size.height;
我觉得这句话比较重要,它将view的位置往下移动了20point(point在非retina屏幕中是20px,在retina屏幕中是40px),这样就不会挡住iphone顶部的状态栏了。
switchView.frame = switchViewFrame;
将修改过的frame从新赋值给switchView
[self.window addSubview:switchView];
将switchView设置成window的subview。怎么理解这句话呢,就是说,一个app只有一个窗口(window),这个window只能同时显示一个view,且这个view是基于这个window而存在的,是放在这个window里面的,因此称之为window的subview,子视图。
5)编辑BIDSwitchViewController.h
BIDSwitchViewController是root controller,用于控制其他2个view的切换,因此需要在其头文件中声明其他两个controller,然后需要定义一个Action,用来完成对2个view的切换,将BIDSwitchViewController.h修改成如下
#import <UIKit/UIKit.h> @class BIDBlueViewController; @class BIDYellowViewController; @interface BIDSwitchViewController : UIViewController @property (strong, nonatomic) BIDBlueViewController *blueViewController; @property (strong, nonatomic) BIDYellowViewController *yellowViewController; - (IBAction)switchViews:(id)sender; @end
代码还是很好理解的,和前面在BIDAppDelegate.h中添加BIDSwitchViewController是一样的。
6)关联BIDSwitchViewController和SwitchView.xib
在Project Navigator中选中SwitchView.xib,在xib的dock中选中File's Owner
然后在Identity inspector中将Class改成BIDSwitchViewController
这样就将SwitchView.xib关联到了BIDSwitchViewController,如果我们选择Connections inspector,会看到我们刚才在BIDSwitchViewController.h中定义的Action:switchViews出现在Received Actions,我们之后就可以将这个Action关联到SwitchView.xib的控件上。
7)在SwitchView.xib上添加Toolbar
在这个例子总,我们切换veiw的方式是点击Toolbar上的一个button,然后切换2个view,SwitchView.xib使我们的root view,因此我们需要在SwitchView.xib上添加一个toolbar,然后点击toolbar上的按钮,切换BlueView.xib和YellowView.xib。
选中SwitchView.xib,在object library中找到Toolbar
拖动到View上,放在最下方
默认的,已经有一个button在Toolbar上了,双击button改变文字,将文字改成“Switch Views”
接着就是将“Switch Views”按钮关联到switchViews,选中“Switch Views”,control-dragged到File's Owner,在弹出的框中选中switchViews
打开Connections inspector,我们可以看到关联后的情况
有一个不同的地方,Toolbar上的button不像一般的button,会有很多的方法让你进行关联,Toolbar上button的Sent Actions(其他的button叫做Send Events,有很多个方法)只有一个方法,而它的作用相当于一般button的touch up inside。
8)关联SwitchView.xib和BIDSwitchViewController's view outlet
BIDSwitchViewController继承自UIViewController,在UIViewController中有一个outlet view,另外当我们在做第6)步的时候,将SwitchView.xib的class改成了BIDSwitchViewController,所以我们要将这个view关联到SwitchView.xib,关联的方法是选中SwitchView.xib,然后选中File's Owner,control-drag到下面的View
释放鼠标后,在填出的框中选则view,这样就关联好了。
关联好后,查看Connections inspector,也可以看到关联后的结果
9)编辑BIDSwitchViewController.m
添加如下代码
#import "BIDSwitchViewController.h" #import "BIDYellowViewController.h" #import "BIDBlueViewController.h" @implementation BIDSwitchViewController @synthesize yellowViewController; @synthesize blueViewController;
2个#import这个很好理解,因为BIDSwitchViewController是root controller,会控制另外2个controller,因此需要把另外2个controller引入进来,这样才可以对他们进行操作。
2个synthesize对着头文件中的2个property。
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib. - (void)viewDidLoad { self.blueViewController = [[BIDBlueViewController alloc] initWithNibName:@"BlueView" bundle:nil]; [self.view insertSubview:self.blueViewController.view atIndex:0]; [super viewDidLoad]; }
首先去掉viewDidLoad的注释,然后添加以上的代码。从最后一句可以看出,viewDidLoad方法继承自UIViewController,在这里对其重载,这个方法发生在当view已经载入完成后,我们所要做的是当root view载入完成后,在载入root view的subview,在我们的这个例子中是BlueView。BlueView的载入方法和前面的一样,使用initWithNibName,然后作为subView插入到当前的view中(当前的view就是root view,也就是SwitchView)。
- (IBAction)switchViews:(id)sender { if(self.yellowViewController.view.superview == nil) { if(self.yellowViewController == nil) { self.yellowViewController = [[BIDYellowViewController alloc] initWithNibName:@"YellowView" bundle:nil]; } [blueViewController.view removeFromSuperview]; [self.view insertSubview:self.yellowViewController.view atIndex:0]; } else { if (self.blueViewController ==nil) { self.blueViewController = [[BIDBlueViewController alloc] initWithNibName:@"BlueView" bundle:nil]; } [yellowViewController.view removeFromSuperview]; [self.view insertSubview:self.blueViewController.view atIndex:0]; } }
实现switchViews Action,上面的代码还是很好理解的,首先判断当前哪个subview是没有superview的,因为这2个subview不会同时显示,当blueSubview显示时,YellowSubview就会从root view中移除,因此不会具有superview,当得知那个subview没有superview,就说明应该显示这个subview。知道该显示哪个subview后,再判断这个subview是否还存在(是否需要重新载入初始化),然后将另一个subview从superview中移除,再将subview显示出来。
- (void)didReceiveMemoryWarning { // Releases the view if it doesn't have a superview. [super didReceiveMemoryWarning]; // Release any cached data, images, etc that aren't in use. if (self.blueViewController.view.superview == nil){ self.blueViewController = nil; } else { self.yellowViewController = nil; } }
当ios的内存不够用时,didReceiveMemoryWarning会被系统自动调用,来释放可利用的内存。在这里如果哪个subview没有显示,就释放该subview,腾出内存。
至此BIDSwitchViewController的所有代码都写好了,下面就应该处理BIDBlueVeiwController和BIDYellowViewController了。
(友情提示,时不时的编译一下你的project,尽早发现问题,容易修改,否则到后面自己都不知道错在哪里)
10)编辑BlueView.xib和YellowView.xib
分别在BlueView.xib和YellowView.xib上添加一个button,并命名为“Press me”。
修改BlueView.xib的class为BIDBlueViewController,修改YellowView.xib的class为BIDYellowController(修改方法:选中xib,点击File's Owner,在Identity inspector中更改class)
class改变了,就需要重新关联一下File's owner的view,方法和之前的一样,选中File‘s Owner,control-drag到下面的View上,在弹出的框中选择view,关联完毕,2个xib都需要进行这个操作。
在Attributes inspector中,将BlueView.xib的background颜色改成蓝色
同样的方法将YellowView.xib的background颜色改成黄色
还有一个地方需要设置,因为我们是在root view中显示这2个subview,而root view有一个toolbar在最下方,因此subview需要把toolbar的位置空出来,再进行自己的布局,还是打开Attributes inspector,在Simulated Metrics栏中有很多现象,他们都是用来模拟iphone屏幕上各种占位控件的,我们将Button Bar的选项设成Toolbar,这样xib就会空出Toolbar的位置来进行布局计算了
仔细看的话,“Press me”按钮的位置往上移动了那么一点点
11)在BIDBlueViewController和BIDYellowViewController中添加代码
在BIDBlueViewController.h中添加Action,如下
@interface BIDBlueViewController : UIViewController - (IBAction)blueButtonPressed; @end
在BIDBlueViewController.m中实现blueButtonPressed,如下
- (IBAction)blueButtonPressed { UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Blue View Button Pressed" message:@"You pressed the button on the blue view" delegate:nil cancelButtonTitle:@"Yep, I did" otherButtonTitles:nil]; [alert show]; }
在BIDYellowViewController.h添加Action,如下
@interface BIDYellowViewController : UIViewController - (IBAction)yellowButtonPressed; @end
在BIDYellowViewController.m中实现yellowButtonPressed,如下
- (IBAction)yellowButtonPressed { UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Yellow View Button Pressed" message:@"You pressed the button on the yellow view" delegate:nil cancelButtonTitle:@"Yep, I did" otherButtonTitles:nil]; [alert show]; }
代码都很简单,就不多做解释了。
12)关联button和Action
打开BlueView.xib,选中“Press me”按钮,control-drag到File's owner释放,在填出的框中选择blueButtonPressed。
打开YellowView.xib,选中“Press me”按钮,control-drag到File's owner释放,在填出的框中选择yellowButtonPressed。
13)编译运行
至此我们已经可以编译运行程序了,编译成功后,iphone模拟器中显示的效果(“Press me”按钮的效果就不演示了)
按下“Switch Views”按钮,BlueSubview会切换到YellowSubview
14)更炫的切换view的方法
有没有发现上面切换view效果很无聊,ios中有更炫的切换view的方法,使用动画的方式切换view,打开BIDSwitchViewController.m,重新编辑switchViews方法,如下
- (IBAction)switchViews:(id)sender { [UIView beginAnimations:@"View Flip" context:nil]; [UIView setAnimationDuration:1.25]; [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut]; if(self.yellowViewController.view.superview == nil) { if(self.yellowViewController == nil) { self.yellowViewController = [[BIDYellowViewController alloc] initWithNibName:@"YellowView" bundle:nil]; } [UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:self.view cache:YES]; [blueViewController.view removeFromSuperview]; [self.view insertSubview:self.yellowViewController.view atIndex:0]; } else { if (self.blueViewController ==nil) { self.blueViewController = [[BIDBlueViewController alloc] initWithNibName:@"BlueView" bundle:nil]; } [UIView setAnimationTransition:UIViewAnimationTransitionFlipFromLeft forView:self.view cache:YES]; [yellowViewController.view removeFromSuperview]; [self.view insertSubview:self.blueViewController.view atIndex:0]; } [UIView commitAnimations]; }
[UIViewbeginAnimations:@"View Flip" context:nil];
先可以不用理解这句话的意思,因为我也没有理解,反正这行代码是声明一个animation block,前一个参数是设置animation block的title,后一个参数是设置一个对象,我也搞不清楚是干什么的,大概在以后的学习中会有所了解。
[UIViewsetAnimationDuration:1.25];
设定动画时间,即切换view的时间
[UIViewsetAnimationCurve:UIViewAnimationCurveEaseInOut];
设定动画的运动方式,开始慢,中间快,最后慢,大家开始看ios自己的说明吧。(An ease-in ease-out curve causes the animation to begin slowly, accelerate through the middle of its duration, and then slow again before completing. This is the default curve for most animations.)
[UIViewsetAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:self.view cache:YES];
设定切换的样式,一共有4个值可以选:
UIViewAnimationTransitionFlipFromRight
UIViewAnimationTransitionFlipFromLeft
UIViewAnimationTransitionFlipCurUp
UIViewAnimationTransitionFlipCurDown
这个大家自试试就可以知道了
[UIViewcommitAnimations];
当所有动画的值设置完毕后,提交动画,之后view就会按照设定的动画进行view的切换了。
(此图截于书本,因此不同清晰)
15)总结
ok,所有的功能都已经完成了,在这个例子中,我们使用toolbar来完成对不同view的切换,我们需要一个root view进行总的控制,然后多个subview进行切换,最后还使用一个比较炫的效果进行view之间的转换,内容很充实!
View Switcher
原文地址:http://www.cnblogs.com/minglz/archive/2012/12/11/2809368.html
在SQL语句优化过程中,我们经常会用到hint,现总结一下在SQL优化过程中常见Oracle HINT的用法:1. /*+ALL_ROWS*/表明对语句块选择基于开销的优化方法,并获得最佳吞吐量,使资源消耗最小化.例如:SELECT /*+ALL+_ROWS*/ EMP_NO,EMP_NAM,DAT_IN FROM BSEMPMS WHERE EMP_NO='SCOTT';2. /*+FIRST_ROWS*/表明对语句块选择基于开销的优化方法,并获得最佳响应时间,使资源消耗最小化.例如:SELECT /*+FIRST_ROWS*/ EMP_NO,EMP_NAM,DAT_IN FROM BSEMPMS WHERE EMP_NO='SCOTT';3. /*+CHOOSE*/表明如果数据字典中有访问表的统计信息,将基于开销的优化方法,并获得最佳的吞吐量;表明如果数据字典中没有访问表的统计信息,将基于规则开销的优化方法;例如:SELECT /*+CHOOSE*/ EMP_NO,EMP_NAM,DAT_IN FROM BSEMPMS WHERE EMP_NO='SCOTT';4. /*+RULE*/表明对语句块选择基于规则的优化方法.例如:SELECT /*+ RULE */ EMP_NO,EMP_NAM,DAT_IN FROM BSEMPMS WHERE EMP_NO='SCOTT';5. /*+FULL(TABLE)*/表明对表选择全局扫描的方法.例如:SELECT /*+FULL(A)*/ EMP_NO,EMP_NAM FROM BSEMPMS A WHERE EMP_NO='SCOTT';6. /*+ROWID(TABLE)*/提示明确表明对指定表根据ROWID进行访问.例如:SELECT /*+ROWID(BSEMPMS)*/ * FROM BSEMPMS WHERE ROWID>='AAAAAAAAAAAAAA'AND EMP_NO='SCOTT';7. /*+CLUSTER(TABLE)*/提示明确表明对指定表选择簇扫描的访问方法,它只对簇对象有效.例如:SELECT /*+CLUSTER */ BSEMPMS.EMP_NO,DPT_NO FROM BSEMPMS,BSDPTMSWHERE DPT_NO='TEC304' AND BSEMPMS.DPT_NO=BSDPTMS.DPT_NO;8. /*+INDEX(TABLE INDEX_NAME)*/表明对表选择索引的扫描方法.例如:SELECT /*+INDEX(BSEMPMS SEX_INDEX) USE SEX_INDEX BECAUSE THERE ARE FEWMALE BSEMPMS */ FROM BSEMPMS WHERE SEX='M';9. /*+INDEX_ASC(TABLE INDEX_NAME)*/表明对表选择索引升序的扫描方法.例如:SELECT /*+INDEX_ASC(BSEMPMS PK_BSEMPMS) */ FROM BSEMPMS WHERE DPT_NO='SCOTT';10. /*+INDEX_COMBINE*/为指定表选择位图访问路经,如果INDEX_COMBINE中没有提供作为参数的索引,将选择出位图索引的布尔组合方式.例如:SELECT /*+INDEX_COMBINE(BSEMPMS SAL_BMI HIREDATE_BMI)*/ * FROM BSEMPMSWHERE SAL<5000000 AND HIREDATE<SYSDATE;11. /*+INDEX_JOIN(TABLE INDEX_NAME)*/提示明确命令优化器使用索引作为访问路径.例如:SELECT /*+INDEX_JOIN(BSEMPMS SAL_HMI HIREDATE_BMI)*/ SAL,HIREDATEFROM BSEMPMS WHERE SAL<60000;12. /*+INDEX_DESC(TABLE INDEX_NAME)*/表明对表选择索引降序的扫描方法.例如:SELECT /*+INDEX_DESC(BSEMPMS PK_BSEMPMS) */ FROM BSEMPMS WHERE DPT_NO='SCOTT';13. /*+INDEX_FFS(TABLE INDEX_NAME)*/对指定的表执行快速全索引扫描,而不是全表扫描的办法.例如:SELECT /*+INDEX_FFS(BSEMPMS IN_EMPNAM)*/ * FROM BSEMPMS WHERE DPT_NO='TEC305';14. /*+ADD_EQUAL TABLE INDEX_NAM1,INDEX_NAM2,...*/提示明确进行执行规划的选择,将几个单列索引的扫描合起来.例如:SELECT /*+INDEX_FFS(BSEMPMS IN_DPTNO,IN_EMPNO,IN_SEX)*/ * FROM BSEMPMS WHERE EMP_NO='SCOTT' AND DPT_NO='TDC306';15. /*+USE_CONCAT*/对查询中的WHERE后面的OR条件进行转换为UNION ALL的组合查询.例如:SELECT /*+USE_CONCAT*/ * FROM BSEMPMS WHERE DPT_NO='TDC506' AND SEX='M';16. /*+NO_EXPAND*/对于WHERE后面的OR 或者IN-LIST的查询语句,NO_EXPAND将阻止其基于优化器对其进行扩展.例如:SELECT /*+NO_EXPAND*/ * FROM BSEMPMS WHERE DPT_NO='TDC506' AND SEX='M';17. /*+NOWRITE*/禁止对查询块的查询重写操作.18. /*+REWRITE*/可以将视图作为参数.19. /*+MERGE(TABLE)*/能够对视图的各个查询进行相应的合并.例如:SELECT /*+MERGE(V) */ A.EMP_NO,A.EMP_NAM,B.DPT_NO FROM BSEMPMS A (SELET DPT_NO,AVG(SAL) AS AVG_SAL FROM BSEMPMS B GROUP BY DPT_NO) V WHERE A.DPT_NO=V.DPT_NOAND A.SAL>V.AVG_SAL;20. /*+NO_MERGE(TABLE)*/对于有可合并的视图不再合并.例如:SELECT /*+NO_MERGE(V) */ A.EMP_NO,A.EMP_NAM,B.DPT_NO FROM BSEMPMS A (SELECT DPT_NO,AVG(SAL) AS AVG_SAL FROM BSEMPMS B GROUP BY DPT_NO) V WHERE A.DPT_NO=V.DPT_NO AND A.SAL>V.AVG_SAL;21. /*+ORDERED*/根据表出现在FROM中的顺序,ORDERED使ORACLE依此顺序对其连接.例如:SELECT /*+ORDERED*/ A.COL1,B.COL2,C.COL3 FROM TABLE1 A,TABLE2 B,TABLE3 C WHERE A.COL1=B.COL1 AND B.COL1=C.COL1;22. /*+USE_NL(TABLE)*/将指定表与嵌套的连接的行源进行连接,并把指定表作为内部表.例如:SELECT /*+ORDERED USE_NL(BSEMPMS)*/ BSDPTMS.DPT_NO,BSEMPMS.EMP_NO,BSEMPMS.EMP_NAM FROM BSEMPMS,BSDPTMS WHERE BSEMPMS.DPT_NO=BSDPTMS.DPT_NO;23. /*+USE_MERGE(TABLE)*/将指定的表与其他行源通过合并排序连接方式连接起来.例如:SELECT /*+USE_MERGE(BSEMPMS,BSDPTMS)*/ * FROM BSEMPMS,BSDPTMS WHERE BSEMPMS.DPT_NO=BSDPTMS.DPT_NO;24. /*+USE_HASH(TABLE)*/将指定的表与其他行源通过哈希连接方式连接起来.例如:SELECT /*+USE_HASH(BSEMPMS,BSDPTMS)*/ * FROM BSEMPMS,BSDPTMS WHERE BSEMPMS.DPT_NO=BSDPTMS.DPT_NO;25. /*+DRIVING_SITE(TABLE)*/强制与ORACLE所选择的位置不同的表进行查询执行.例如:SELECT /*+DRIVING_SITE(DEPT)*/ * FROM BSEMPMS,DEPT@BSDPTMS WHERE BSEMPMS.DPT_NO=DEPT.DPT_NO;26. /*+LEADING(TABLE)*/将指定的表作为连接次序中的首表.27. /*+CACHE(TABLE)*/当进行全表扫描时,CACHE提示能够将表的检索块放置在缓冲区缓存中最近最少列表LRU的最近使用端例如:SELECT /*+FULL(BSEMPMS) CAHE(BSEMPMS) */ EMP_NAM FROM BSEMPMS;28. /*+NOCACHE(TABLE)*/当进行全表扫描时,CACHE提示能够将表的检索块放置在缓冲区缓存中最近最少列表LRU的最近使用端例如:SELECT /*+FULL(BSEMPMS) NOCAHE(BSEMPMS) */ EMP_NAM FROM BSEMPMS;29. /*+APPEND*/直接插入到表的最后,可以提高速度.insert /*+append*/ into test1 select * from test4 ;30. /*+NOAPPEND*/通过在插入语句生存期内停止并行模式来启动常规插入.insert /*+noappend*/ into test1 select * from test4 ;
参考blog:http://blog.csdn.net/tianlesoftware/article/details/4969702
WordPress是一套很方便的個人部落格系統架設軟體,免費開放的原始碼,任何人都可以取得、修改、架設。但你知道嗎?其實WordPress除了個人部落格之外,其實還有另一個Project,就是「WordPress MU」。這個WordPress MU是多用戶的WordPress架設程式,架設成功的話就可以自己經營BSP了,自己就像無名小站站長或是痞客邦這樣的部落格服務提供商,提供給有部落格需求的使用者使用。
雖然知道的人不多,但現在更棒的是這個WordPress MU從WordPress3.0版開始直接整合到WordPress之中,算是一項隱藏功能,需要透過一個代碼才能啟用這項服務,以往架設WordPress MU是要在額外架設,現在完全不用了,直接在自己本來的部落格系統內就可以啟用WordPress MU,有興趣的話趕快來喚醒沉睡的WordPress MU吧!
目前全球最大的WordPress MU使用者就是WordPress.com這個免費的WordPress免費部落格服務,這個網站就是由WordPress MU系統建立的,如果把WordPress MU經營的好當然就會像那樣囉!以往MU系統是額外獨立的專案,從3.0版的WordPress就把它整合進來,不再成為一個獨立的專案程式了,現在任何WordPress的使用者都可以把自己的網站改裝成WordPress MU。
WordPress MU被簡稱為「WPMU」,但全名其實是「WordPress Multi User」多用戶程式。這套程式之所以大家會很少聽到是因為對於一般使用者來說,用途其實不大,因為大家架設網站都是獨立架設、擁有自己的網站,很少有人和別人共用一個網址,利用他的子網域或是子資料夾架設獨立的WordPress。
那這套程式不就沒用了嗎?其實並不然。如果你有三五好友想要擁有一個部落格,但是不想要使用常見的BSP部落格,可是如果要自架,又不會改程式碼的話,又或是另一種情況,假若你有工作上的需要,需要架設多個WordPress,可是想要同一管理,這個WordPress MU就可以幫上忙了,因為他可以開通多個部落格,網站的設定統一由最大的管理者「超級管理」來處理,其他使用者只要負責使用就可以了,這樣一來對管理者來說管理輕鬆,對其他用戶來說也方便使用。
第1步 首先請您下載程式並進行WordPress的安裝,詳細安裝過程這邊不多做說明,如果不會安裝請參考:如何架設安裝WordPress部落格?,先將WordPress架設起來。當您的WordPress架設好後,請下載FTP內的wp-config.php檔案,在檔案內加入語法,避免加錯位置,可在「/* 設定完成,請儲存檔案。然後開始 Blogging 吧! */」之上加入,儲存後將檔案上傳到FTP中。
define('WP_ALLOW_MULTISITE', true);
第2步 重新整理部落格後台,點擊左方【工具】→「網誌網路」,進入後請將網誌網路的標題和聯絡信箱設定好,並點擊﹝安裝﹞。
[請注意]
如果您是從現有的部落格修改wp-config.php,想改裝成WordPress MU多用戶系統,而非剛剛新架設的WordPress,那在子網域安裝部分無法設定,系統會強制您只能使用子目錄分類,來區分每個部落格。如果您是新架設的,那會出現子網域設定,請參考後面的教學說明。
錯誤訊息是:The main site in a sub-directory install will need to use a modified permalink structure, potentially breaking existing links.
第3步 一旦設定好後,就無法再變更網站結構類型了。接著請按照畫面指示的訊息新增資料。
第4步 請開啟FTP連上網站後在「/public_html/wp-content」目錄下新建一個資料夾「blogs.dir」並設定資料夾屬性為「777」,因為這邊是要儲存用戶上傳的檔案。
第5步 接著請下載FTP根目錄中的「wp-config.php」請將WordPress後台指示的資料加入倒wp-config.php的「/* 設定完成,請儲存檔案。然後開始 Blogging 吧! */」這句話之上,儲存然後上傳。
語法可能如下,但不完全一樣。
define('WP_ALLOW_MULTISITE', true); define( 'MULTISITE', true ); define( 'SUBDOMAIN_INSTALL', false ); $base = '/'; define( 'DOMAIN_CURRENT_SITE', 'wpblog.net.ru' ); define( 'PATH_CURRENT_SITE', '/' ); define( 'SITE_ID_CURRENT_SITE', 1 ); define( 'BLOG_ID_CURRENT_SITE', 1 );
第6步 接著請再將FTP上的「.htaccess」檔案下載,並根據WordPress後台指示的說明將資料加入到「.htaccess」檔案中,設定好後請上傳。
語法類似以下,但可能不完全一樣。
RewriteEngine On RewriteBase / RewriteRule ^index\.php$ - [L] # uploaded files RewriteRule ^([_0-9a-zA-Z-]+/)?files/(.+) wp-includes/ms-files.php?file=$2 [L] # add a trailing slash to /wp-admin RewriteRule ^([_0-9a-zA-Z-]+/)?wp-admin$ $1wp-admin/ [R=301,L] RewriteCond %{REQUEST_FILENAME} -f [OR] RewriteCond %{REQUEST_FILENAME} -d RewriteRule ^ - [L] RewriteRule ^([_0-9a-zA-Z-]+/)?(wp-(content|admin|includes).*) $2 [L] RewriteRule ^([_0-9a-zA-Z-]+/)?(.*\.php)$ $2 [L] RewriteRule . index.php [L]
第7步 設定好後,請重新登入WordPress後台,如果啟動成功進入後就會看到左上角會多出一個「超級管理」,這就是WordPress MU的管理選項,可以在那邊新增用戶、設定等等,因為升級成MU之後,原本的部落格也會屬於WordPress MU的一部分,所以在畫面中會多出限制用戶的儲存空間選項,預設都是10MB的儲存空間,使用者可以自己調整。
第8步 點擊【超級管理】→﹝選項﹞可以對MU站點做設定,不過這有些部分的中文描述好像怪怪的,有點不通順就是了。設定上大家自己可以玩玩看囉!
第9步 點擊【超級管理】中的「網誌」則可以建立新網誌,就是開一個獨立的部落格,開設在子資料夾內。輸入您要的網站名稱在網誌位址以及網誌標題和該網誌站長的聯絡信箱就可以了,伺服器將會自動寄信通知部落格使用者。
第10步 在網誌的清單中可以點擊您剛剛建立的部落格,點進去後可以對部落格做一些設定與調整,當然也可以保持預設不動作。
第11步 建立好的部落格就像這樣子囉!
WordPress MU 設定子網域
前面有提到,如果是新安裝的WordPress,那在您啟動WordPress MU功能同時,設定選項中會讓使用者選擇「子網域」或是「子目錄」。當然設定成子網域會比較好看,網址感覺高級一點,但相對的困難度也提高,因為需要動到系統設定檔案,目前網路上還沒有一個教學是針對「虛擬主機(Share Hosting)」,因為需要動到系統的阿帕契和DNS之類的設定,所以非常的麻煩。
第1步 如果是新架設的WordPress,在啟動MU功能時,會在【工具】→「網誌網路」中看見「子網域」和「子目錄」的設定,請您選擇子網域進行設定。請記住這邊一但選擇了網站架構,就不能進行更改,如果強制更改原始碼,可能會出現無法意料的錯誤。
第2步 接著WordPress會偵測您的空間是否有辦法自動建立子網域,但在虛擬主機中,實驗的結果都是會失敗的,因為一般使用者沒有權限去調整伺服器的設定。以最常見的虛擬主機系統cPanel來說,用戶無法對其網址進行變更,必須由cPanel管理者透過WHM內的DNS功能進行調整才行。如果您是自架主機,基本上應該就有權限可以設定,因此請先根據這頁面內的資料把網站設定一下,這邊的設定就跟前面提到的部分是一樣的,因此就不多做說明。
第3步 接著就是設定伺服器或虛擬主機以及網址部份了。關於虛擬主機要設定的「Wildcard DNS Record」等等之類的,以下有幾篇教學可以參考看看:這裡、這裡、這裡。如果虛擬主機支援的話,只要到DNS代管站新增一筆A紀錄,然後網域部分請輸入通用符號「*」,然後再輸入IP並新增就可以了。
大部分DNS代管站都可以,當然仍是有可能不支援的,目前測試的GoDaddy是可以新增前面提到所謂的「Wildcard DNS Record」資料。
You can create a wildcard A record by setting the Host Name value to “*" (asterisk). The wildcard causes the server to respond with the IP address specified instead of an error if the subdomain queried does not exist within your zone file.
第4步 設定好後,您可以自由的新增部落格,新增部落格的時候會發現網誌位址部分變成讓使用者輸入網域囉!
以下展示網站為殺氣測試,使用H-Sphere空間作為測試!
主網域部落格:http://tgcc.org.ru/
子網域部落格:http://happy.tgcc.org.ru/
基本上設定就是這樣子而已,其實如果不使用子網域,一般虛擬主機都可以很輕鬆的啟用WordPress MU多用戶功能。不過有些人可能啟用會失敗,那就是主機不支援不支援固定網址的功能,您的Apache的「mod_rewrite」這個模組被禁用了,如果是個人用戶可以到系統檔案「httpd.conf」把分號去掉,如果是虛擬主機請聯絡管理員。
如果你本身沒有多用戶需求,建議不要啟動MU,因為啟動MU之後,部落格的資料庫會多一些資料表,每建立一個部落格,就會多出10多張的資料表。另外,啟動MU之後系統資源也會吃比較重,因為就等於在一個網站上架設好幾個部落格在運作,只是管理上比獨立架設方便,如果您有需要架設MU,最好要挑選一個限制比較少的虛擬主機來架設,否則三天兩頭資源就吃完了,空間被停是早晚的事情。
这两天在全力设计东方设计图库频道 期间尝试了多种办法来尽可能的与东方设计工作室主站集成在一起,起初尝试了WordPress的Multisite功能,分别以Sub directory和Sub domain的形式分别各自试了一次,发觉,WP一旦开启了Multisite以后结构变得复杂了很多,而且不够稳定,数据库表也一下子飙升了很多,显得非常臃肿,显然这个并不是我所要的效果,于是经过整个周末的来回尝试,最后放弃了Multisite的形式,还是全新安装了一个WP,经过反复调试,已经初具模型,但是问题就是用户也得重新注册一次,这个显然再次违背了我的初衷,经过反复Google,终于找到了一个完美的解决方案,那就是两个完全独立的WordPress共享同一个数据表,堪称完美,不敢独享,现将教程共享给各位。
因为图库站新建的WP已经搭建出来了,而这个集成必须是后边这个WP需要在共享前一个数据库的用户表的基础上全新安装才可以实现,而且两个WP必须建在同一个数据库里边,这个问题不大,只要改变一下前缀即可,于是说干就敢。
第一步、通过WP的工具》导出功能将已经建立好的文章页面等统统导出成一个XML文件;
第二步、修改新建的WP的配置文件wp-config.php如下所示:
$table_prefix = ‘blogb_’;
修改数据库表前缀为新的前缀,防止和第一个WP冲突,然后在同个文件里找到
/* That’s all, stop editing! Happy blogging. */
在这断话上方插入:
define(‘CUSTOM_USER_TABLE’, ‘wp_users’); define(‘CUSTOM_USER_META_TABLE’, ‘wp_usermeta’);
注意这里的wp_users和wp_usermeta都是第一个WP的用户数据表,这里我们假设第一个WP用了默认的前缀;
第三步、修改完配置文件以后,就可以开始安装第二个WP,安装过程不是本教程讨论的范畴,因此略过;
第四步、安装完成你会发现可以直接用第一个WP网站的管理员直接登陆第二个WP网站后台,然后进入工具》导入,将第一步导出的XML文件重新导入,然后进行一些必要的配置即可。
搞定收工,经过测试非常完美,至此,在任意第一个或者第二个上新注册的用户,立马可以直接用来登陆另外一个网站的后台,Fantastic,所谓踏破铁鞋无觅处、得来全不费工夫,这几天的忙活没有白费,有了这个方法,理论上你可以设置任意多个独立的WP系统共用同一个用户数据表,有点类似于discuz的ucenter,但是这个显然整合的更彻底,直接就是同一个表,不用担心还需要再次同步的问题。
wordpress网站后台登陆界面有个Logo图标,在自己的网站摆着官方的图标,很多人看起来很不舒服,所以大家都希望更换掉这个图标,为此,小编推荐两种wordpress更换图标的方法:
准备一张命名为logo-login.gif的背景透明的图片大小规格为310px*70px
在wordpress根目录的wp-admin/images文件夹中找到logo-login.gif文件,
用这张图片覆盖替换为自己准备好的logo-login.gif图片即可
访问后台登陆界面,图标已更换。
优点:简单,快捷,适合新手使用;
缺点:更新升级版本时又得重新修改。
在主题函数文件functions.php中,添加如下一行,以修改链接地址:
add_filter(‘login_headerurl’, create_function(false,’return get_bloginfo(‘siteurl’);”));
在主题函数文件functions.php中,添加如下一行,以修改链接地址的标题提示:
add_filter(‘login_headertitle’, create_function(false,”return get_bloginfo(‘description’);”));
在主题函数文件functions.php中,添加如下内容,以修改由CSS控制显示的链接图片:
function nowspark_login_head() { echo ‘<style type=”text/css”>body.login #login h1 a {background:url(http://www.mengzhiyi.info/wp-content/themes/mengzhiyi/images/buttom_logo.gif) no-repeat 0 0 transparent;height: 31px;width: 155px;padding:0;margin:0 auto 1em;}</style>’;}add_action(“login_head”, “nowspark_login_head”);//modify the background image
将url中链接修改为你自己的链接即可!
优点:更新版本无需重新更改,更改图片的同时把链接地址和标题提示也同时修改掉了;(本站推荐使用方法)
具体过程如下:
1、InstantRails-2.0安装后,在配置环境变量path中配置ruby/bin目录(如果系统中有多个RUBY,执行命令行的时候系统认的就是path中的)
2、进入DOS命令行,执行gem update --system,结果
Updating RubyGems...
ERROR: While executing gem ... (Gem::RemoteSourceException)
HTTP Response 302 fetching http://rubygems.org/yaml
这是因为gem的配置过低,无法进行远程更新,执行gem -v 发现是1.0.1
3、从下面这个地址下载 rubygems-update-1.3.7.gem,http://rubyforge.org/frs/download.php/70695/rubygems-update-1.3.7.gem
然后DOS命令进行该文件所在的目录,执行gem install --local rubygems-update-1.3.7.gem,出现信息
Successfully installed rubygems-update-1.3.7
1 gem installed
Installing ri documentation for rubygems-update-1.3.7...
Installing RDoc documentation for rubygems-update-1.3.7...
Could not find main page README
Could not find main page README
Could not find main page README
Could not find main page README
执行gem -v查看,发现并没有更新成功,Could not find main page README是什么意思我没弄明白,但是我从http://production.s3.rubygems.org/yaml上发现这么一句
If you have an older version of RubyGems installed, then you can still
do it in two steps:
$ gem install rubygems-update # again, might need to be admin/root
$ update_rubygems # ... here too
我照着再执行 update_rubygems,接着出现的信息很多,就不帖出来,再执行gem -v,发现更新成功,已经是1.3.7了
这一步是一切成功的源泉!!!!!!
4、接着再执行gem update --system,提示
Updating RubyGems
Nothing to update
这是为什么我不明白,请高手指点一下
5、再执行gem update rails --include-dependencies,提示信息
Updating installed gems
Updating rails
ERROR: Error installing rails:
actionpack requires rack (~> 1.0.0, runtime)
Gems updated: activesupport, activerecord
Installing ri documentation for activesupport-2.3.3...
Installing ri documentation for activerecord-2.3.3...
Installing RDoc documentation for activesupport-2.3.3...
Installing RDoc documentation for activerecord-2.3.3...
执行rails -v,发现还是2.0.2没有更新成功,根据actionpack requires rack (~> 1.0.0, runtime),应该是actionpack 需要1.0.0版本的rack
6、执行gem install rack -v=1.0.0
Successfully installed rack-1.0.0
1 gem installed
Installing ri documentation for rack-1.0.0...
Installing RDoc documentation for rack-1.0.0...
更新成功
7、再次执行 gem update rails --include-dependencies
出现信息
Updating installed gems
Updating rails
Successfully installed rake-0.8.7
Successfully installed activesupport-2.3.8
Successfully installed activerecord-2.3.8
Successfully installed rack-1.1.0
Successfully installed actionpack-2.3.8
Successfully installed actionmailer-2.3.8
Successfully installed activeresource-2.3.8
Successfully installed rails-2.3.8
Gems updated: rake, activesupport, activerecord, rack, actionpack, actionmailer, activeresource, rails
Installing ri documentation for rake-0.8.7...
Installing ri documentation for activesupport-2.3.8...
Installing ri documentation for activerecord-2.3.8...
Installing ri documentation for rack-1.1.0...
Installing ri documentation for actionpack-2.3.8...
Installing ri documentation for actionmailer-2.3.8...
Installing ri documentation for activeresource-2.3.8...
Installing ri documentation for rails-2.3.8...
Installing RDoc documentation for rake-0.8.7...
Installing RDoc documentation for activesupport-2.3.8...
Installing RDoc documentation for activerecord-2.3.8...
Installing RDoc documentation for rack-1.1.0...
Installing RDoc documentation for actionpack-2.3.8...
Installing RDoc documentation for actionmailer-2.3.8...
Installing RDoc documentation for activeresource-2.3.8...
Installing RDoc documentation for rails-2.3.8...
执行rails -v,发现已更新成功
总结:rails更新有两种方式:1、联机更新;2本地更新
联机更新过程中如果出现HTTP Response 302 fetching http://rubygems.org/yaml无法更新,有两种情况
一是gem的版本过低,二是与服务器的连接不通
此时可以试着加入其他服务器地址
gem source -l 查看列表
gem source -a http://rubygems.org 加入新的服务器地址
或者直接gem install rubygems-update --source http://rubygems.org
本地更新需要下载相应的gem包,版本需与要更新的rails版本对应,同时安装顺序有要求,因此gem包之间有依赖关系
顺序从上面的显示信息中可以看出来
Successfully installed rake-0.8.7
Successfully installed activesupport-2.3.8
Successfully installed activerecord-2.3.8
Successfully installed rack-1.1.0
Successfully installed actionpack-2.3.8
Successfully installed actionmailer-2.3.8
Successfully installed activeresource-2.3.8
Successfully installed rails-2.3.8
至于gem包的下载地址都在http://rubyforge.org/,但是有些项目的并不好找到,可以在google中直接搜索,就能找到在http://rubyforge.org/中的地址。