IOS6的发布facebook决定放弃使用Three2o这套框架,Three20的官网已经很久没有更新了,目前只有GitHub上在维护,所以决定将现在工程中的Three2o框架移除。本篇文章MOMO就写写我在移除Three20框架的一些经验以及教训。
一.界面切换
在AppDelegate中打开程序的入口窗口,用过Three20的朋友看到下面的方式应该不陌生吧。
1 | if (![navigator restoreViewControllers]) |
4 |
[navigator openURLAction:[TTURLAction actionWithURLPath:@ "tt://Tab" ]]; |
我们首先把它先改了,如果你的程序不需要导航栏可以不加UINavigationController。
1 | UINavigationController *navController = [[[UINavigationController alloc]initWithRootViewController:[[[LoginViewController alloc]init] autorelease]]autorelease]; |
3 | self.window.rootViewController = navController; |
5 | [self.window makeKeyAndVisible]; |
此时,入口视图方法我们已经修改完毕,接着我们修改二级菜单,子菜单之间的切换。
处理子菜单时Three20依然在AppDelegate中就声明了所有ViewController,并且依次给他们起了一个别名。
2 | [map from:@ "tt://Schedule" toModalViewController:[ScheduleViewController class ]]; |
3 | [map from:@ "tt://Schedule" toModalViewController:[ScheduleViewController class ]]; |
4 | [map from:@ "tt://Schedule" toSharedViewController:[ScheduleViewController class ]]; |
这三种是最常用的类型,其实核心也无非就是两种,这里我直接写IOS源生的实现方式,记得把TTViewController换成UIViewController:
1.向右推出一个新ViewController
1 | [self.navigationController pushViewController:[[[SignUpViewController alloc]init]autorelease] animated:YES]; |
默认的话进入新ViewController的时候左上角会有一个返回的按钮,点击该按钮后会返回到之前的界面。当然如果你是自定义返回按钮的话,需要写代码来手动返回。
在新推的界面中执行下面代码即可直接返回。
1 | [self.navigationController popViewControllerAnimated:YES]; |
2.向上覆盖一个新ViewController
同样,如果不需要导航栏的话去掉UINavigationController即可。
1 | UINavigationController *viewNavController = [[UINavigationController alloc] initWithRootViewController:[[[newViewController alloc]init]autorelease]]; |
2 | [self presentViewController:viewNavController animated:YES completion:^{ }]; |
正如上面所说这是一个向上覆盖的ViewController ,不需要时就需关闭它。
1 | [self dismissViewControllerAnimated:YES completion:^{ }]; |
二、自定义TabBar
Three20研究院之完全自定义TabBar(八)这是320实现自定义的方式,有兴趣的朋友去看看,这里我只说如何把Three20自定义的TabBar 用源生的方式来写。
.h文件
01 | #import <Foundation/Foundation.h> |
04 | #import "ChannelViewController.h" |
05 | #import "InvitationsViewController.h" |
06 | #import <UIKit/UIKit.h> |
08 | @interface UserCenterViewController : UITabBarController<UITabBarControllerDelegate> |
.m文件
01 | #import "UserCenterViewController.h" |
03 | @implementation UserCenterViewController |
07 |
if (self = [super init]) |
11 |
[self.view setFrame:CGRectMake(0, 0, 320, 460)]; |
12 |
UIView *tabBarView=[[[UIView alloc] initWithFrame:CGRectMake(0, 480-48, 320, 48)] autorelease]; |
14 |
[self.view addSubview:tabBarView]; |
16 |
UIImageView *backGroundView=[[[UIImageView alloc] initWithImage:[Utility getImageByName:@ "tabBar_background" :@ "png" ]] autorelease]; |
17 |
[tabBarView addSubview:backGroundView]; |
20 |
UIButton* button0 = [UIButton buttonWithType:UIButtonTypeCustom]; |
21 |
button0.frame = CGRectMake(0, 0, 160, 48); |
22 |
[button0 setTitle:@ "婚礼" forState:UIControlStateNormal]; |
23 |
[button0 setBackgroundImage:[Utility getImageByName:@ "tk_03-l" :@ "png" ] forState:UIControlStateNormal]; |
25 |
[button0 addTarget:self action:@selector(ButtonPressed:) forControlEvents:UIControlEventTouchUpInside]; |
27 |
[tabBarView addSubview:button0]; |
29 |
UIButton* button1 = [UIButton buttonWithType:UIButtonTypeCustom]; |
30 |
[button1 setTitle:@ "邀请" forState:UIControlStateNormal]; |
31 |
[button1 setBackgroundImage:[Utility getImageByName:@ "tk_03-l" :@ "png" ] forState:UIControlStateNormal]; |
32 |
button1.frame = CGRectMake(160, 0, 160, 48); |
34 |
[button1 addTarget:self action:@selector(ButtonPressed:) forControlEvents:UIControlEventTouchUpInside]; |
35 |
[tabBarView addSubview:button1]; |
37 |
ChannelViewController *channel = [[[ChannelViewController alloc]init]autorelease]; |
38 |
InvitationsViewController *invitation = [[[InvitationsViewController alloc]init]autorelease]; |
40 |
UINavigationController *navigationController= [[[UINavigationController alloc] initWithRootViewController:invitation]autorelease]; |
42 |
[navigationController viewDidAppear:YES]; |
43 |
[navigationController viewWillAppear:YES]; |
46 |
self.viewControllers = [[[NSMutableArray alloc]initWithObjects:channel,navigationController, nil]autorelease]; |
59 | -( void )ButtonPressed:(id)buttonID |
62 |
UIButton *button = (UIButton *)buttonID; |
63 |
self.selectedIndex =button.tag; |
66 | -( void )viewWillAppear:( BOOL )animated |
68 |
[super viewWillAppear:animated]; |
69 |
[self.navigationController setNavigationBarHidden:YES animated:NO]; |
72 | <strong>所谓自定义Tabbar原理就是自定义按钮,点击按钮后切换tabbar指向的viewcontroller即可。</strong> |

接着再说说Tabbar界面切换的特殊情况,正常情况切换界面是在当前ViewController中完成的,可是UITabViewController都是集成了好几个子ViewController,如果切换界面的触发事件在这些子ViewController中的话,就需要在子ViewController中通知父UITabViewController然后在去切换。 不然的话TabBar的按钮是不会消失的。
1 | [self.tabBarController.navigationController pushViewController:[[[ECardViewController alloc]init] autorelease] animated:YES]; |
三、自定义UITableViewCell
Three20研究院之自定义TableView列表详解(二)这是之前我写过的一篇文章,但是在Three20中我是按这种方式实现自定义UITableViewCell,这里我只写如何在IOS源生下实现。
在UITableViewController的全局定义一个自定义Cell的数据源,以数组的形式保存着每一个cell的数据。
NSMutableArray*_dataSourses;
下面这段代码我上面提到的那篇文章中copy的。
01 | #import <Three20/Three20.h> |
03 | @interface TableItem : TTTableLinkedItem { |
12 | @property (nonatomic, copy) NSString *title; |
13 | @property (nonatomic, copy) UIImage *image; |
14 | @property (nonatomic, copy) UIColor *backcolor; |
17 | + (id)itemWithTitle:(NSString *)title |
18 |
image:(UIImage *)image backcolor:(UIColor *) backcolor; |
03 | @implementation TableItem |
05 | @synthesize title = _title,image = _image, backcolor = _backcolor; |
07 | + (id)itemWithTitle:(NSString *)title |
08 |
image:(UIImage *)image backcolor:(UIColor *) backcolor { |
10 |
TableItem *item = [[[self alloc] init] autorelease]; |
13 |
item.backcolor = backcolor; |
19 |
if (self = [super init]) |
32 |
TT_RELEASE_SAFELY(_title); |
33 |
TT_RELEASE_SAFELY(_image); |
34 |
TT_RELEASE_SAFELY(_backcolor); |
TableItem.h就是每一个Cell需要用到的对象,这里我们先把
@interface TableItem:TTTableLinkedItem修改成
@interface TableItem:NSObject
接着是Cell
01 | #import <Three20/Three20.h> |
03 | @interface TableItemCell : TTTableLinkedItemCell { |
07 |
UIImageView *_imageview; |
01 | #import "TableItemCell.h" |
03 | @implementation TableItemCell |
05 | + (CGFloat)tableView:(UITableView*)tableView rowHeightForObject:(id)item |
11 | - (id)initWithStyle:(UITableViewCellStyle)style |
12 |
reuseIdentifier:(NSString*)identifier |
15 |
if (self = [super initWithStyle:UITableViewCellStyleValue2 |
16 |
reuseIdentifier:identifier]) |
20 |
_titleLabel = [[UILabel alloc] initWithFrame:CGRectZero]; |
22 |
[self.contentView addSubview:_titleLabel]; |
24 |
_imageview = [[UIImageView alloc] initWithFrame:CGRectZero]; |
26 |
[self.contentView addSubview:_imageview]; |
35 |
TT_RELEASE_SAFELY(_titleLabel); |
36 |
TT_RELEASE_SAFELY(_imageview); |
40 | - ( void )layoutSubviews { |
41 |
[super layoutSubviews]; |
44 |
[_imageview setFrame:CGRectMake(5,5,70,70)]; |
46 |
[_titleLabel setFrame:CGRectMake(100,0,100,20)]; |
55 | - ( void )setObject:(id)object { |
57 |
[super setObject:object]; |
59 |
TableItem *item = object; |
61 |
[_titleLabel setText:item.title]; |
62 |
[_titleLabel setBackgroundColor:item.backcolor]; |
64 |
[_imageview setImage:item.image]; |
65 |
[_imageview setBackgroundColor:item.backcolor]; |
67 |
self.contentView.backgroundColor = item.backcolor; |
69 |
self.selectionStyle=UITableViewCellSelectionStyleBlue; |
TableItemCell.h就是每一个Cell对象,自定义的布局就是在这里完成。
@interfaceTableItemCell:TTTableLinkedItemCell
修改成
@interfaceTableItemCell:UITableViewCell
此时,自定义Cell的布局我们有了,每一个Cell布局需要的对象我们也有了,下面我们要让UITbaleViewController来将这些Cell绘制出来。
UITbaleViewController中加入代码
1 | -(CGFloat) tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath |
6 |
TimeLineTableItem *item = [_dataSourses objectAtIndex:indexPath.row]; |
1 | -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section |
4 |
return [_dataSourses count]; |
01 | -(UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath |
04 |
static NSString *CellTableIdentifier = @ "TimeLineTabeIndentifier" ; |
06 |
TimeLineTableItemCell *cell = [tableView dequeueReusableCellWithIdentifier:CellTableIdentifier]; |
10 |
cell = [[[TimeLineTableItemCell alloc]initWithStyle:UITableViewCellStyleDefault :CellTableIdentifier ]autorelease]; |
12 |
[cell drawCell:[_dataSourses objectAtIndex:indexPath.row]]; |
17 |
[cell drawCell:[_dataSourses objectAtIndex:indexPath.row]]; |
注:TimeLineTableItem、TimeLineTableItemCell 是我项目中用到的对象,大家不必拘泥于名子如何来起,原理白即可。
另外cell还具有一个刷新的功能,当数据源_dataSourses发生改变后手动调用如下方法即可刷新Cell。程序会重新执行上述三个方法来刷新Cell。
1 | [self.tableView reloadData]; |
一般在Three20工程中将这三部做完剩下的就是一些琐碎的活,在将工程中所有TT开头的对象引用全部去掉,谁都不愿理干体力活,可是脏活累活还是得干,呵呵! 仔细一下很快就把Three20框架移除了。
如下图所示,这里的thrr20路径一定要删除,不然还是会有诡异的错误,呵呵、

最后在fromwork中将所有three20的framwork全部删除,运行一下祝你成功喔,嘿嘿!