我经常觉得需要将Objective-C代码拆分成多个文件以提高可读性.我想避免上课并打电话给他们.我想简单导入(比如在php中).
如果有人可以请参考一个有效的例子.
rob*_*off 13
你说"我想避免上课并打电话给他们."你需要克服你对增加课程的恐惧.如果您觉得需要将类的实现拆分为多个文件,那么您可能会尝试在单个类中执行太多操作.你需要让那个班级("委托")将一些责任交给其他班级.
也就是说,有几种方法可以拆分一个类的实现.除了修复膨胀的类设计之外,更好的方法是使用类别或类扩展.您可以在Objective-C编程语言中阅读有关类别和扩展的所有内容.请注意,链接器会在创建可执行文件时将类别和扩展合并到类中,因此在您自己的类上使用类别或扩展时不会有运行时间损失.
更糟糕的方法是使用C预处理程序的#include
指令将多个文件粘贴在一起.您可以从实现文件中取出一些方法并将它们粘贴到新的"片段"文件中,然后#include
将片段文件放在实现文件中. 这样做会使您更难理解源代码. 我不建议这样做,但无论如何这里是一个例子:
#import "MyObject.h"
@implementation MyObject
- (void)aMethod { ... }
#include "MyObject-moreMethods.m"
@end
Run Code Online (Sandbox Code Playgroud)
// Note: do not include this target in the “Compile Sources” build phase of your target.
// And **NO** @implementation statement here!
- (void)methodTwo { ... }
- (void)methodThree { ... }
Run Code Online (Sandbox Code Playgroud)
Kaa*_*glu 11
在这种情况下,我认为您正在查看类别:
您所要做的就是在.h文件中创建一个新的.h .m对:
#import MyClass.h
@interface MyClass(Networking)
//method declarations here
@end
Run Code Online (Sandbox Code Playgroud)
并在.m文件中:
#import MyClass+Networking.h
@implementation MyClass(Networking)
//method definitions here
@end
Run Code Online (Sandbox Code Playgroud)
在MyClass.m文件中 - 执行#import MyClass + Networking.h并完成所有设置.这样你就可以扩展你的课程.
[编辑/更新 - 我已经放弃了下面描述的方法,支持使用类别,如其他一些答案所述.我的典型情况是,随着视图添加了控件组件,视图控制器文件变得难以处理,因为添加了代码以适应控件的各种委托和数据源方法.现在,我在视图控制器文件中添加代码存根,然后在类类别中实现它们.例如,我可能有一个AlbumViewController屏幕,它有一个搜索栏和一个集合视图,所以我创建了类别AlbumViewController + SearchBar和AlbumViewController + CollectionView.这允许View Controller类保持合理的大小,而不会产生下面列出的包含文件的任何缺点.唯一的缺点是必须公开声明任何实例变量,即属性,才能访问它们.
我还想分割我的文件,但在某些情况下认为类别不是正确的解决方案.例如,当nib增长到包含多个对象(例如表,按钮,导航栏,选项卡等)时,需要将所有支持方法放在viewcontroller.m文件中,这可能会导致文件非常庞大且难以处理.
在本次讨论中,我将引用原始/标准.m文件作为父文件,将子文件.m文件作为子文件引用.
目标是拥有单个父.h和.m,以及多个子.m文件,每个文件都可以独立编辑,但编译好像所有子.m文件都在父.m文件中一样.
如果想要能够将所有与表相关的方法放在一个文件中,对其进行编辑,然后将其编译为就像它包含在viewcontroller.m实现文件中一样,那么这将非常有用.这似乎是可能的,但需要一点努力,并且有一个(可能是严重的)缺点.
要记住的是,使用了两种不同的工具:IDE(提供智能源编辑)和编译/制作系统,将项目的源代码转换为可运行的应用程序.
为了使IDE按预期工作,子文件需要看起来是该类实现的一部分.这可以通过在条件编译宏中包装@implementation和@end指令来实现.当自己编辑文件时,IDE会将子文件视为类的主体,但编译器不会.
为了让编译器不要抱怨,你不能将子文件视为目标的一部分 - 而是通过预处理器#include指令引入它们.这可以通过在创建(或添加到项目)文件时不将它们添加到目标,或者通过在"构建阶段" - >"编译源"窗格中删除它们来实现.
然后#include父.m文件正文中的子.m文件.编译器将它们"就地"加载并根据需要编译源代码而不会抱怨.
这种方法(到目前为止)的缺点是调试器不承认孩子的方法,并在断点穿上它们不会打破.出于这个原因,我建议这种方法只能在代码经过全面测试后使用,或者用于相对简单且众所周知的代码块,例如表委托和数据源方法.
以下是带有表和nib中的文本字段的项目的.h和.m文件,其中支持委托方法在子.m文件中定义.在nib中,接口对象正常连接,并将委托设置为文件所有者.
文件(父)"MyViewController.h":
#import <UIKit/UIKit.h>
@interface MyViewController : UIViewController
@property (retain, nonatomic) IBOutlet UITableView *myTable;
@property (retain, nonatomic) IBOutlet UITextField *myTextField;
@end
Run Code Online (Sandbox Code Playgroud)
文件(父)MyViewController.m:
#import "MyViewController.h"
#define VIEW_CONTROLLER_MAIN_BODY 1
@interface MyViewController ()
@end
@implementation MyViewController
#include "MyViewController_TableMethods.m"
#include "MyViewController_TextFieldMethods.m"
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)dealloc {
[_myTable release];
[_myTextField release];
[super dealloc];
}
Run Code Online (Sandbox Code Playgroud)
文件(子)MyViewController_TableMethods.m:
#import <UIKit/UIKit.h>
#import "MyViewController.h"
#ifndef VIEW_CONTROLLER_MAIN_BODY
@implementation ViewController
#endif
#pragma mark -
#pragma mark Table View Common Methods
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;
{
return 5;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
{
static NSString *myIdentifier = @"myCellIdentifier";
static UITableViewCellStyle myStyle = UITableViewCellStyleSubtitle;
UITableViewCell *cell = [self.myTable dequeueReusableCellWithIdentifier:myIdentifier];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:myStyle reuseIdentifier:myIdentifier] autorelease];
}
cell.textLabel.text = @"Title";
cell.detailTextLabel.text = @"Details";
cell.accessoryType = UITableViewCellAccessoryNone;
return cell;
}
#ifndef VIEW_CONTROLLER_MAIN_BODY
@end
#endif
Run Code Online (Sandbox Code Playgroud)
文件(子)MyViewController_TextFieldMethods.m:
#import <UIKit/UIKit.h>
#import "MyViewController.h"
#ifndef VIEW_CONTROLLER_MAIN_BODY
@implementation MyViewController
#endif
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
self.myTextField.text = @"Woo hoo!";
return YES;
}
#ifndef VIEW_CONTROLLER_MAIN_BODY
@end
#endif
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
9252 次 |
最近记录: |