1 Star 0 Fork 0

XuBill / ios_oc

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
贡献代码
同步代码
取消
提示: 由于 Git 不支持空文件夾,创建文件夹后会生成空的 .keep 文件
Loading...
README

宏定义统一以大写K开头。(为了方便书写可以约定小写k开头);变量,如api等最好使用extern替换,宏只定义方法等不需要改变的代码,为了加快编译速度。部分优化手段只适用宏不改变的情况优化,宏修改重新编译。 https://www.jianshu.com/p/ba5b2f1ab9f8

编写

私有变量推荐以_开头

素材

图片资源针对每个模块创建一个xcassets文件, 图片命名 1.命名规范:不能有中文、大写、特殊符号、空白 2.命名格式(推荐): fileType[function]project[pageName]imageName[status]{.png,@2x.png,@3x.png} 万能公式:类别_功能_模块_页面_名称_状态.png

泛型

建议在定义NSArray和NSDictionary时使用泛型,可以保证程序的安全性:

类名

以HJ开头

版本规范

Xcode 代码块的存放地址:~/Library/Developer/Xcode/UserData/CodeSnippets Xcode 文件模版的存放地址:/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/Xcode/Templates/File Templates/

tableview中cell的复用id

  • 1在需要使用的控制器内这么写,使用static修饰,但这样你如果换了个控制器还得再写一遍很僵硬,不是很推荐.
static NSString *baseInfomationSubCellID = @"CBaseInfoSubCell";
  • 2在cell头文件上声明一个常量,采用extern来修饰,这有个优点,就是当你的cell需要在多个控制器上使用时,会很方便.
//头文件,你要是使用苹果的extern当然也可以
extern NSString *const CBASE_INFOMATION_CELLID;
//实现文件
NSString *const CBASE_INFOMATION_CELLID = @"CBaseInfomationCell";
  • 3在UITableViewCell的基类或者分类中写一个类方法,能够获取cell的类名 + (NSString *)getCellIDStr { return NSStringFromClass([self class]); }

控件可以这样命名,这样联想起来更加的方便

比如说一个姓名label是写成nameLabelnameLab.

条件语句或者参数过多时请换行对齐

[[KLPrestoClient prestoClient] postBaseInfoMationWithEducation:_postParaFlags.education
monthlyIncome:_postParaFlags.monthlyIncome
professionType:_postParaFlags.jobInfo
marriage:_postParaFlags.marriage
cityName:_cityNameStr
cityAddress:_addressStr
latitude:_latitudeStr
longitude:_longitudeStr
isProvidentFund:providentFundModel.selectedIndex
eMailAddress:_EMailAddrStr
censusIsLiveCity:censusModel.selectedIndex
isHud:YES
success:^(BaseModel *model) {

if ([model.status isEqualToString:@"000"]) {

//上传数据成功
[self.navigationController popViewControllerAnimated:YES];

} else {

}

} failture:^(id error) {
}];

尽量多的利用参数和返回值,尽量不要使用全局变量

/**
对城市按照首字母分组
*/
- (NSArray *)p_makeCityGroup:(NSArray *)cityArray{
NSMutableArray *letterDictArray = [NSMutableArray array];
//创建26个数组用来存储
for (int i = 0; i < 26; i ++) {
NSMutableArray *letterCityArray = [NSMutableArray array];
[letterDictArray addObject:letterCityArray];
}

for (CCityModel *model in cityArray) {

//将城市首字母转化为asic码
int asciiCode = [model.cityCode characterAtIndex:3];
int index = asciiCode - 97;
[letterDictArray[index] addObject:model];
}
return [letterDictArray copy];
}

在一些需求巧妙地利用完全初始化方法,不要将不需要外部改变的属性readwrite

/**
普通model
*/
- (instancetype)initNormalModelWithTitle:(NSString *)title answer:(NSString *)answer answerArray:(NSArray *)answerArray {

return [self initBaseInfomationWithTitle:title
answer:answer
selectedIndex:NO_CHOOSE_ANSWER_INDEX
isMap:NO
answerArray:answerArray
isTwoChooseBtnCell:NO
isEMailAddressCell:NO];
}

/**
带地图的model
*/
- (instancetype)initMapModelWithTitle:(NSString *)title answer:(NSString *)answer {

return [self initBaseInfomationWithTitle:title
answer:answer
selectedIndex:NO_CHOOSE_ANSWER_INDEX
isMap:YES
answerArray:nil
isTwoChooseBtnCell:NO
isEMailAddressCell:NO];
}

/**
二选一model
*/
- (instancetype)initTwoChooseOneModelWithTitle:(NSString *)title answerArray:(NSArray *)answerArray {
//index传-1表示二选一未选择
return [self initBaseInfomationWithTitle:title
answer:@""
selectedIndex:NO_CHOOSE_ANSWER_INDEX
isMap:NO
answerArray:answerArray
isTwoChooseBtnCell:YES
isEMailAddressCell:NO];
}

/**
带邮箱的model
*/
- (instancetype)initEMailModelWithTitle:(NSString *)title defaultAnswer:(NSString *)defaultAnswer{
//index传-1表示未输入
return [self initBaseInfomationWithTitle:title
answer:defaultAnswer
selectedIndex:NO_CHOOSE_ANSWER_INDEX
isMap:NO
answerArray:nil
isTwoChooseBtnCell:NO
isEMailAddressCell:YES];
}

/**
完全初始化
*/
- (instancetype)initBaseInfomationWithTitle:(NSString *)title answer:(NSString *)answer selectedIndex:(NSInteger)selectedIndex isMap:(BOOL)isMap answerArray:(NSArray *)answerArray isTwoChooseBtnCell:(BOOL)isTwoChooseBtnCell isEMailAddressCell:(BOOL)isEMailAddressCell{
if (self = [super init]) {
_title = title;
_answer = answer;
_selectedIndex = selectedIndex;
_isMap = isMap;
_answerArray = answerArray;
_isTwoChooseBtnCell = isTwoChooseBtnCell;
_isEMailAddressCell = isEMailAddressCell;
}
return self;
}

@end

Objective-C 编程风格指南

Controller注释、命名示例

  • 1、请在类文件顶部注明作者姓名
  • 2、控件命名请使用 控件作用拼接数据类型 (例如:UIButton => settingButton UIButton => submitButton UILabel => companyLabel )
  • 3、一个方法中代码尽量不要超过20行,如超过请考虑按职责将代码拆分到子方法中,保障主方法流程清晰
  • 4、类、类成员(变量或方法)顶部应添加注释说明清楚类的职责、变量的作用或者方法的提供的功能
  • 5、方法内注释请使用 双斜杠加空格再加说明文案
//
// JLaunchViewController.m
// J1000
//
// Created by 作者姓名 on 17/2/8.
// Copyright © 2017年 user. All rights reserved.
//

#import "JLaunchViewController.h"

@interface JLaunchViewController ()<UIScrollViewDelegate>

/*
* 引导页位置指示器
*/
@property (weak, nonatomic) IBOutlet UIPageControl *dotPageControl;

/*
* 引导图容器
*/
@property (weak, nonatomic) IBOutlet UIScrollView *intrScrollView;

/*
* 进入按钮
*/
@property (weak, nonatomic) IBOutlet UIButton *nextButton;

@end

@implementation JLaunchViewController{
/*
* 引导图数组
*/
NSMutableArray * _imageArray;
}

- (void)viewDidLoad {
[super viewDidLoad];

// 初始化界面
[self initView];

// 数据绑定()
[self dataBind];
}

- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}

#pragma mark - UI
/*
* 初始化界面
*/
- (void)initView{

// 设置scrollView属性(隐藏水平滚动条,边框不反弹、整页翻动、关联代理类)
self.intrScrollView.showsHorizontalScrollIndicator = NO;
self.intrScrollView.bounces = NO;
self.intrScrollView.pagingEnabled = YES;
self.intrScrollView.delegate = self;

// 设置pageControl属性(设置指示圆点默认色值与选中色值、背景颜色、整页翻动后再切换当前位置)
self.dotPageControl.currentPageIndicatorTintColor = [UIColor blackColor];
self.dotPageControl.pageIndicatorTintColor = [UIColor whiteColor];
self.dotPageControl.backgroundColor = [UIColor clearColor];
self.dotPageControl.defersCurrentPageDisplay = YES;

// 默认隐藏底部按钮
self.nextButton.hidden = YES;
}

/*
* 数据绑定
*/
- (void)dataBind{

// 测试
_imageArray = [[NSMutableArray alloc]initWithObjects:@1, @2, @2, @2, @2, nil];

// 设置ScrollView内容的宽度与高度
self.intrScrollView.contentSize = CGSizeMake(ScreenWidth * _imageArray.count, ScreenHeight);

// 循环添加图片
for (int i = 0; i< _imageArray.count ; i++) {
UIImageView * imageView = [[UIImageView alloc] initWithFrame:CGRectMake(ScreenWidth * i, 0, ScreenWidth, ScreenHeight)];
imageView.contentMode = UIViewContentModeScaleAspectFit;
imageView.backgroundColor = i == 0 ? [UIColor greenColor] : [UIColor orangeColor];
[self.intrScrollView addSubview:imageView];
}

// 设置pageControl圆点总数与当前位置
self.dotPageControl.numberOfPages = _imageArray.count;
self.dotPageControl.currentPage = 0;

}
#pragma mark - target
/*
* 进入按钮单击事件处理函数
*/
- (IBAction)didClickNextBtn:(id)sender {

if (self.loginSwitchVCBlock) {
self.loginSwitchVCBlock();
}
}

#pragma mark - delegate
/*
* 滚动视图滚动事件处理函数
*/
- (void)scrollViewDidScroll:(UIScrollView *)scrollView{
// 当拖动偏移量超过半屏时切换圆点位置
self.dotPageControl.currentPage = (int) (scrollView.contentOffset.x + ScreenWidth/2) /ScreenWidth;

// 判断是否隐藏进入按钮
self.nextButton.hidden = !(self.dotPageControl.currentPage == _imageArray.count - 1);
}

@end

Xcode项目

  • 为避免文件混乱,实际的物理文件应和Xcode项目保持一直。在Xcode中所创建的任何group都应有文件系统中相对应的文件夹。不应仅根据文件类型来进行分组,还需要考虑到其作用。

简写

  • 较长的单词可取单词的头几个字母形成缩写
  • 仅在变量命名,图片命名中使用
名称 缩写
infomation info
message msg
descriptation desc

类的命名

  • 大驼峰式命名:类的命名的时候,每个单词的首字母都采用大写字母。(项目简写+名称+后缀)。
要求 例如
ViewController 使用Controller做后缀 例子: DDFHomeController
View 使用View做后缀 例子: DDFAlertView
UITableCell 使用Cell做后缀 例子: DDFNewsCell
Protocol 使用Delegate或者DataSource作为后缀 例子: UITableViewDelegate
Model 使用model作为后缀 例子: DDFDataModel
单例 manager 例子: DDFUserInfoManager
类的拓展 类名+项目简写+extra 例子: NSString+DDFExtra

宏命名

要求 例如
宏定义方法 小驼峰命名 例子: getImageUrl(url) [NSURL URLWithString:[NSString stringWithFormat:@"%@%@",DDFBaseUrl,url]]
宏定义常量 遵循大驼峰命名(开头以项目简写) 例子:#define DDFWidth self.frame.size.width, KScreenWidth [UIScreen mainScreen].bouds.size.width

变量的命名

  • 用修饰+类型的方式 ,类型简写参考简写。
要求 例如
用修饰+类型的方式 (小驼峰式命名) UIButton *settingButton

property变量

要求 例如
小驼峰式命名 @property (strong, nonatomic) NSSNumber *userId;
NSString 使用copy @property (copy, nonatomic) NSString *userName;
所有属性特性应该显式地列出来 @property (weak, nonatomic) IBOutlet UIView *containerView;

图片命名

  • 可以进行简写 nav,btn,bg,imagev
要求 例如
功能名称_____控件类型 ___自定义参数 share_____btn _weixin

枚举类型

  • 项目简写开头,跟随其后的命名应采用驼峰命名法则,命名应准确表述枚举表示的意义,枚举中各个值都应以定义的枚举类型开头,其后跟随各个枚举值对应的状态、选项或者状态码。
typedef NS_ENUM(NSInteger, DDFRequestState) {
DDFRequestStateInactive,
DDFRequestStateLoading
};

方法命名

  • 使用小驼峰法,规范的方法名应该看起来像一个完整的句子,读过便知函数作用。

  • 在(-/+ )符号之后应加上一个空格

- (void)setExampleText:(NSString *)text image:(UIImage *)image;
+ (void)sendAction:(SEL)aSelector to:(id)anObject forAllCells:(BOOL)flag;

代理命名

  • 名称以标示发送消息的对象的类名开头,省略类名的前缀并⼩小写第⼀个字⺟
- (BOOL)tableView:(NSTableView*)tableView shouldSelectRow:(int)row;
- (BOOL)application:(NSApplication *)sender
openFile:(NSString *)filename;
  • 冒号紧跟在类名之后(随后的那个参数表⽰委派的对象)。该规则不适用于只有一个 sender 参数的⽅法
- (BOOL)applicationOpenUntitledFile:(NSApplication *)sender;

代码组织

  • 在函数分组和protocol/delegate实现中使用#pragma mark -来分类方法,要遵循以下一般结构:
  • 结构按照功能模块划分
  1. 懒加载
  2. 控制器生命周期。
  3. 私有方法
  4. 通知方法
  5. 代理方法。
  6. 公共方法。
  7. 触发事件。

#pragma mark - lazy

- (NSArray *)array {
if(!_array) {

}
return _array;
}

#pragma mark - Lifecycle

- (instancetype)init {}
- (void)dealloc {}
- (void)viewDidLoad {}
- (void)viewWillAppear:(BOOL)animated {}
- (void)didReceiveMemoryWarning {}

#pragma mark - Private

- (void)privateMethod {}

#pragma mark - NSCopying
- (void)didReceiveNotification {}

#pragma mark - UITableViewDataSource
#pragma mark - UITableViewDelegate

#pragma mark - Custom Accessors
- (void)setCustomProperty:(id)value {}
- (id)customProperty {}

#pragma mark - Public
- (void)publicMethod {}
#pragma mark - IBActions

- (IBAction)submitData:(id)sender {}

点表示法

  • 应“仅”用于获取和改变属性。括号表示法用于所有其它实例。
应该:
NSInteger arrayCount = self.array.count;
view.backgroundColor = [UIColor orangeColor];
[UIApplication sharedApplication].delegate;
不应该:
NSInteger arrayCount = [self.array count];
[view setBackgroundColor:[UIColor orangeColor]];
[[UIApplication sharedApplication] delegate];

空格

  • 类方法声明在方法类型与返回类型之间要有空格。
- (void)methodName:(NSString *)string;
  • 条件判断的括号内侧不应有空格。
if (a < b) {
// something
}
  • 关系运算符(如 >=、!=)和逻辑运算符(如 &&、||)两边要有空格。
(someValue > 100)? YES : NO

Literals字面量

  • 在创建NSString,NSDictionary,NSArrayNSNumber等对象的immutable实例时,应使用字面量。需要注意的是,不应将nil传递给NSArrayNSDictionary字面量,否则会引起程序崩溃。
NSArray *names = @[@"Brian", @"Matt", @"Chris", @"Alex", @"Steve", @"Paul"];
NSDictionary *productManagers = @{@"iPhone" : @"Kate", @"iPad" : @"Kamal", @"Mobile Web" : @"Bill"};
NSNumber *shouldUseLiterals = @YES;
NSNumber *buildingZIPCode = @10018;

Case语句

  • 大括号在case语句中并不是必须的,除非编译器强制要求。当一个case语句包含多行代码时,大括号应该加上。
switch (condition) {
case 1:
// ...
break;
case 2: {
// ...
// Multi-line example using braces
break;
}
case 3:
// ...
break;
default:
// ...
break;
}
  • 有很多次,当相同代码被多个cases使用时,一个fall-through应该被使用。一个fall-through就是在case最后移除break语句,这样就能够允许执行流程跳转到下一个case值。为了代码更加清晰,一个fall-through需要注释一下。
switch (condition) {
case 1:
// ** fall-through! **
case 2:
// code executed for values 1 and 2
break;
default:
// ...
break;
}

布尔变量

  • 因为nil将被解析为NO,因此没有必要在条件语句中进行比较。永远不要将任何东西和YES进行直接比较,因为YES被定义为1,而一个BOOL变量可以有8个字节。
if (someObject) {}
if (![anotherObject boolValue]) {}
  • 如果BOOL属性的名字是一个形容词,属性就能忽略"is"前缀,但要指定get访问器的惯用名称。例如:
@property (assign, getter=isEditable) BOOL editable;

条件语句

  • 为避免错误,条件语句体必须使用大括号,即便语句体中的语句可以不必使用大括号(比如只有一行语句)。常见的错误包括在不使用大括号的情况下添加第二行语句,以为它属于if语句的一部分。此外,更可怕的事情是,如果条件语句中的代码行被注释,则本不属于条件语句的下一行代码将变成条件语句的一部分。此外,这种编码风格和所有其它条件语句均保持一致。
应该:
if (!error) {
return success;
}
不应该:
if (!error)
return success;

if (!error) return success;

三元操作符

  • 仅当使用该运算子可以让代码显得更清晰易懂时方可使用三元运算子。更多情况下应使用条件语句。使用类似if的条件语句对多种条件进行判断通常要更容易理解,或使用实例变量。
应该:
result = a > b ? x : y;
不应该:
result = a > b ? x = c > d ? c : d : y;

注释

  • 当需要注释时,注释应该用来解释这段特殊代码为什么要这样做。任何被使用的注释都必须保持最新或被删除。

  • 一般都避免使用块注释,因为代码尽可能做到自解释,只有当断断续续或几行代码时才需要注释。例外:这不应用在生成文档的注释

参考资料 https://www.jianshu.com/p/3508672f26ae 参考这篇文章、为了统一删除部分文字。

空文件

简介

暂无描述 展开 收起
Objective-C
取消

发行版

暂无发行版

贡献者

全部

近期动态

加载更多
不能加载更多了
Objective-C
1
https://gitee.com/li_xu/ios_oc.git
git@gitee.com:li_xu/ios_oc.git
li_xu
ios_oc
ios_oc
master

搜索帮助