IOS 开发学习(3): IOS UI架构设计
来源:互联网 发布:mac chrome广告终结者 编辑:程序博客网 时间:2024/05/22 01:48
IOS 严格秉承MVC模式, 即每个View的出现将有相应的Controller负责其逻辑事物, 因此IOS的UI设计中需要首先考虑MVC的问题. 在本博客中,在兼顾MVC的同时,考虑了两点设计中常用的问题。
1. IOS中对可重用UI的处理(能重用的UI通过Controller特别封装, 提供给其它View进行重用)
UI涉及的一个非常重要的问题,跟程序设计也是一样, 如何管理冗余(即重复信息)的信息, 冗余度的处理实际上不单单是程序设计的死敌,同样是管理的死敌(冗余代码是Bug的温床,同样如此,雷同UI是用户体验的死敌)。
对付重复性,我们这里一个小需求是, 如何实现一个类似于ListView的功能, 让所有的UI的小Item都能不断的加入到父面板中? UI如下:
图:不断增加一个重复的UI
当然,也许有人说用UITableView可以做到, 但是更个性化的Item, 会很需要一个类似的结构来达成我们的目的。并且,你一定会面临这样的问题,相同的数据结构,需要用同一个UI展示。当你辛苦的设计好一个UI以及逻辑之后,发现在另外相似的情况下复用,已经痛不欲生,因此, 这里我们采用的一种方式是: 封装好一个小的UI. 然后随处可用。
a. 隔离
图: 父面板实际上可以是任意的
图:在任意需要的地方,调用这个小东西
b. 代码中加载
- //
- // KEYI_ViewController.m
- // LoadPartView
- //
- // Created by 尘 凡 on 12-12-28.
- // Copyright (c) 2012年 __MyCompanyName__. All rights reserved.
- //
- #import "KEYI_ViewController.h"
- @interface KEYI_ViewController ()
- @end
- @implementation KEYI_ViewController
- - (void)viewDidLoad
- {
- [super viewDidLoad];
- //仅仅只是为了获取view的大小, 这个controller设置为autoRelease
- LiteController *tempControl = [[[LiteController alloc] initWithNibName:@"LiteController" bundle:nil] autorelease];
- UIView *liteView = tempControl.view;
- CGPoint point = liteView.center;
- CGSize size = liteView.bounds.size;
- //不知道为什么, 需要代码初始化这个ScrollView, IB拖拉的方式构造界面,会无效
- UIScrollView *parentView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.height)];
- [self.view addSubview:parentView];
- int len = 75;
- for (int i = 0; i < len; i++) {
- CGFloat centX = point.x;
- CGFloat centY = point.y + i * size.height;
- NSString *string = [NSString stringWithFormat:@"%d",i];
- [self addItems:centX :centY:parentView:string];
- }
- parentView.contentSize = CGSizeMake(320, len* size.height);
- parentView.scrollEnabled = YES;
- }
- - (void) addItems:(CGFloat)centX:(CGFloat)centY:(UIScrollView *)parentView:(NSString*)title
- {
- LiteController *contr = [[LiteController alloc] initWithNibName:@"LiteController" bundle:nil];
- UIView *aItem = contr.view;
- [contr.textLabel setText:title];
- aItem.center = CGPointMake(centX, centY);
- aItem.backgroundColor = [UIColor grayColor];
- [parentView addSubview:aItem];
- }
- - (void)viewDidUnload
- {
- [super viewDidUnload];
- // Release any retained subviews of the main view.
- }
- - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
- {
- return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
- }
- - (void)dealloc {
- [super dealloc];
- }
- @end
2. IOS中对个性化页面的处理: 个性化中,公用UI进行提炼, 个性化的UI自己负责自己的Controller以及XIB文件
下图是一个典型的个性化页面处理情况,点击4个Tab按钮将出现不同的UI.
面对这样的个性化特征很强的界面, 按照程序设计的低耦合原则, 应该将可变化的部分, 安插在影响最小的位置,比如【注册】的UI/逻辑不能影响【登陆】的UI以及逻辑, 这里,我是按照这样的方式:
a. 公共部分, 如上层按钮, 放在一个controller中. 见下图:
图: 一个全局的Controller, 相当PC中CPU的作用: 组装
b. 各个按钮对应的不同界面,各自建立Controller. 见下图:
图: 【登陆】已经被封装到自己的Controller, 最小耦合度原则
图: 【注册】已经被封装到自己的Controller, 最小耦合度原则
c. 关键的代码, 加载各自不同的Controller
头文件
- //
- // ControllerUsrMgr.h
- // keyiApp
- //
- // Created by 尘 凡 on 12-12-14.
- // Copyright (c) 2012年 __MyCompanyName__. All rights reserved.
- //
- #import <UIKit/UIKit.h>
- #import "ControllerMod.h"
- #import "ControllerLogin.h"
- #import "ControllerRegister.h"
- #import "ControllerForget.h"
- #import "ToolUI.h"
- @interface ControllerUsrMgr : UIViewController
- {
- IBOutlet UILabel *selTitle;
- IBOutlet UIButton *changeBtn;
- IBOutlet UIButton *forgotBtn;
- IBOutlet UIButton *regBtn;
- IBOutlet UIButton *loginBtn;
- IBOutlet UIView *parentView;
- IBOutlet UILabel *titleInfo;
- NSArray *btnArr;
- NSArray *selImgArr;
- NSArray *unSelImgArr;
- NSArray *upperTitle;
- NSArray *lowerTitle;
- ControllerLogin *loginCtr;
- ControllerRegister *registerCtrl;
- }
- - (IBAction)actionLogin:(UIButton *)sender;
- - (IBAction)actionRegister:(UIButton *)sender;
- - (IBAction)actionForgot:(UIButton *)sender;
- - (IBAction)actionChange:(UIButton *)sender;
- @end
源文件
- //
- // ControllerUsrMgr.m
- // keyiApp
- //
- // Created by 尘 凡 on 12-12-14.
- // Copyright (c) 2012年 __MyCompanyName__. All rights reserved.
- //
- #import "ControllerUsrMgr.h"
- @interface ControllerUsrMgr ()
- @end
- @implementation ControllerUsrMgr
- - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
- {
- self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
- if (self) {
- // Custom initialization
- unSelImgArr = [[NSArray alloc] initWithObjects:@"usr_mgr_login_nosel.png",@"usr_mgr_reg_nosel.png",@"usr_mgr_mod_nosel.png",@"usr_mgr_login_nosel.png", nil];
- selImgArr = [[NSArray alloc] initWithObjects:@"usr_mgr_login_sel.png",@"usr_mgr_reg_sel.png",@"usr_mgr_mod_sel.png",@"usr_mgr_login_sel.png", nil];
- lowerTitle = [[NSArray alloc] initWithObjects:@"请填写登陆信息",@"请填写注册信息",@"请填写申诉信息",@"请填写修改信息", nil];
- upperTitle = [[NSArray alloc] initWithObjects:@"用户登陆",@"用户注册",@"忘记密码",@"修改密码", nil];
- loginCtr = [[ControllerLogin alloc]initWithNibName:@"ControllerLogin" bundle:nil];
- registerCtrl = [[ControllerRegister alloc]initWithNibName:@"ControllerRegister" bundle:nil];
- }
- return self;
- }
- - (void)viewDidLoad
- {
- [super viewDidLoad];
- btnArr = [[NSArray alloc] initWithObjects:loginBtn,regBtn,changeBtn,forgotBtn, nil] ;
- [self actionLogin:loginBtn];
- }
- - (void)viewDidUnload
- {
- [loginBtn release];
- loginBtn = nil;
- [regBtn release];
- regBtn = nil;
- [forgotBtn release];
- forgotBtn = nil;
- [changeBtn release];
- changeBtn = nil;
- [parentView release];
- parentView = nil;
- [titleInfo release];
- titleInfo = nil;
- [selTitle release];
- selTitle = nil;
- [super viewDidUnload];
- // Release any retained subviews of the main view.
- // e.g. self.myOutlet = nil;
- }
- - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
- {
- return (interfaceOrientation == UIInterfaceOrientationPortrait);
- }
- - (void)dealloc {
- [loginBtn release];
- [regBtn release];
- [forgotBtn release];
- [changeBtn release];
- [parentView release];
- [titleInfo release];
- [selTitle release];
- [super dealloc];
- }
- - (IBAction)actionLogin:(UIButton *)sender {
- [ToolUI removeSubView:parentView];
- [parentView addSubview:loginCtr.view];
- [self highLightButton:sender];
- }
- - (IBAction)actionRegister:(UIButton *)sender {
- [ToolUI removeSubView:parentView];
- [parentView addSubview:registerCtrl.view];
- [self highLightButton:sender];
- }
- - (IBAction)actionForgot:(UIButton *)sender {
- [ToolUI removeSubView:parentView];
- [self highLightButton:sender];
- }
- - (void) pressOne:(UIButton *)curBtn {
- if (curBtn == loginBtn)
- {
- [curBtn performSelector:@selector(highLightButton:) withObject:curBtn afterDelay:0.1];
- }
- }
- - (void) highLightButton:(UIButton *)b{
- for (int i = 0; i < btnArr.count; i++) {
- UIButton *item = [btnArr objectAtIndex:i];
- NSString *unSel = [unSelImgArr objectAtIndex:i];
- NSString *sel = [selImgArr objectAtIndex:i];
- if (b == item) {
- [item setBackgroundImage:[UIImage imageNamed:sel] forState:UIControlStateNormal];
- [selTitle setText:[upperTitle objectAtIndex:i]];
- [titleInfo setText:[lowerTitle objectAtIndex:i]];
- }
- else {
- [item setBackgroundImage:[UIImage imageNamed:unSel] forState:UIControlStateNormal];
- }
- }
- }
- - (IBAction)actionChange:(UIButton *)sender {
- [ToolUI removeSubView:parentView];
- [self highLightButton:sender];
- }
- @end
附注:
参考 1: 苹果教程: UIViewControler知识
参考2: 中枪: XCode ios iphone 变态的资源管理 非常混乱的说....
参考3: 中枪, 删除默认的view之后产生的新问题
- IOS 开发学习(3): IOS UI架构设计
- IOS 开发学习(3): IOS UI架构设计
- iOS UI架构设计
- iOS开发 UI 设计模式
- iOS开发工程架构设计
- IOS开发指南学习——分层架构设计
- iOS开发视频教程 UI部分:1、iOS概述和架构
- iOS 开发学习摘要: 1. 了解 iOS 的UI设计原则
- iOS开发---UI/UE设计篇
- iOS开发---UI/UE设计篇
- iOS开发---UI/UE设计篇
- iOS开发---UI/UE设计篇
- iOS开发---UI/UE设计篇
- iOS开发---UI/UE设计篇
- UI设计 Android&IOS开发推荐用色
- iOS开发---UI/UE设计篇
- iOS开发项目架构浅谈:iOS架构设计与分层
- iOS学习- 06 UI设计 Sketch使用
- Android开发之如何在WebView中点击链接使用自身打开(解决出现的选择使用第三方应用的问题)
- 《深入理解java虚拟机》之类加载机制
- poj--3624--Charm Bracelet(动态规划 水题)
- 使用Navicat Premium对mssql2008r2授权用户
- MFC绘图知识大全
- IOS 开发学习(3): IOS UI架构设计
- 应对Memcached缓存失效,导致高并发查询DB的几种思路
- 如何将计算机加入到域环境中
- 在Eclipse中安装pydev插件
- android 巨大bug之 ViewPager 子页面中包含TextView singleLine在viewPager中有textview。 当textview的参数为singleLine和grav
- qrcode生成一个带有图片的二维码
- 配置Snappy压缩
- 第四例:Intent启动Activity的几种方式(一)
- 如何对网页的加载进行性能优化