作者:柠檬跑步 王鑫
总结了一些好的习惯,分享一下。
一起共勉。
- 面向对象开发
- id的使用
- 提示文字的统一
- 列表控制器使用
LRBasicListController.swift
- 给
GXBaseViewController
只应该添加分类,而不是添加方法 - 属性不应该全部暴露在
.h
文件中,只有给外界使用的变量才放到.h
文件中,必要的使用使用readOnly
关键字 - 封装代码,封装view,封装model,封装一切可能封装的东西
- 分类名称的写法
- view的高度写成常量
- 项目中少用
storybaord
,以及使用他的注意项 - 三个及以上的变量必须要换行,代码的大小写统一
- .view.frame = CGRect.init(x:lx,y:ly,width:lW,height:lH)的写法
- 使用胖model给控制器减肥,暴露出一个属性,可以让大家减少重复的计算
- 不要去修改牛逼的第三方。sd,afn 我们项目有修改的情况,消耗性能
- 不要无用的打印
- Block的写法
- 图片的命名
- 指定一些颜色,字体,等宏定义
- 给控制器瘦身
- 属性的写法,
nonamatic
,strong
,readonly
- 特殊代码
- 父类不要控制子类的属性,应该在子类中写
面向对象开发
开发必须要面向对象开发,决不允许面向字典开发
面向字典容易出错,不好复用代码等.目前项目都是面向字典开发的
[图片上传失败...(image-927c65-1509616761159)]
[图片上传失败...(image-4a944b-1509616761160)]
//保存房间列表实体
for(NSDictionary *dic in [response.data objectForKey:@"rooms"]){
Rooms *rooms = [Rooms roomsWithDic:dic];
[weakSelf.roomsArray addObject:rooms];
}
这里应该注意
- 1.面向字典开发
- 2.三目运算符的使用不应该太长
只有可控的时候,我们才能使用三目- 如:
NSInteger age = user.gender == 1?0:1
!self.avatarTapBlock?:self.avatarTapBlock();
- 如:
- 3.学习使用Mantle或者MJExtension,用第三方直接字典转模型,演示一下使用方法
//保存房间列表实体
NSArray *keyValues = [response.data objectForKey:@"room_list"];
NSArray *rooms = [Rooms mj_objectArrayWithKeyValuesArray:keyValues context:nil];
[weakSelf.resultRooms addObjectsFromArray:rooms];
id的使用
- 凡是使用id的时候,不论用字符串类型,还是NSNumber(最好使用NString)都要和后台确定一下,用于统一.这样可以减少各种
NSNumber
和字符串之间的转化。 - 别用
int
在OC中,可以使用NSInteger
,少用int
- 如果是
id
是模型Topic
的,我们应该使用tip
,减少id
给我带来的影响.
提示文字的统一
这个就是涉及到了文字的处理,如果我们没有国际化,其实也是可以将常用文字,或者所有的文字全都统一处理,这样将来修改起来比较好用.
static NSString * const LRLimitRunRoomNameTextLengthKey = @"最多允许输入10个字哦~";
static NSString * const LRHaveNetTheFoundationCanUseKey = @"有网络才能进行挑战呦";
static NSString * const LROpenLemonRunLocationNoticeKey = @"请确保定位授权对柠檬跑步开放,\n并移动到";
static NSString * const LROpenSystemLocationNoticeKey = @"GPS未开启,无法获取当前位置";
static NSString * const LRLocatButtonWhereAreYouKey = @"你在哪里?";
包括全局数据常量也应该如此,例如全马和半马的数据。项目中目前有,但是没有格式不对
列表控制器使用LRBasicListController.swift
只要是列表页控制器,都可以直接继承控制器
实现功能:
- 1.上拉加载上拉刷新功能
- 2.提供了一个load数据方法给子类,只需关注要做的网络请求,其他的不用管理
- 3.自动数据操作
- 4.无网络情况
- 5.无数据空白页情况
给GXBaseViewController
只应该添加分类,而不是添加方法
[图片上传失败...(image-774d60-1509616761160)]
还有GXBaseViewController
的showHUD
方法等,建议使用分类
属性不应该全部暴露在.h
文件中,只有给外界使用的变量才放到.h
文件中,必要的使用使用readOnly
关键字
interface LRMineViewController : GXBaseViewController<EMContactManagerDelegate,EMChatManagerDelegate>
property (weak, nonatomic) IBOutlet UITableView *mineTableView;
property (weak, nonatomic) IBOutlet UIView *headerView;
property (weak, nonatomic) IBOutlet UIImageView *topImage;
property (weak, nonatomic) IBOutlet UIImageView *headShadow;
property (weak, nonatomic) IBOutlet UIImageView *headImage;
property (weak, nonatomic) IBOutlet UIImageView *genderImage;
property (weak, nonatomic) IBOutlet UILabel *nameLabel;
property (weak, nonatomic) IBOutlet UIImageView *mineIcon1;
@property (weak, nonatomic) IBOutlet UILabel *mineIconBottom1;
@property (weak, nonatomic) IBOutlet UIImageView *mineIcon2;
@property (weak, nonatomic) IBOutlet UILabel *mineIconBottom2;
@property (weak, nonatomic) IBOutlet UIImageView *mineIcon3;
@property (weak, nonatomic) IBOutlet UILabel *mineIconBottom3;
@property (weak, nonatomic) IBOutlet UIImageView *levelImage;
@property (weak, nonatomic) IBOutlet UILabel *locationLabel;
@property (weak, nonatomic) IBOutlet UIImageView *medalNew;
@property (weak, nonatomic) IBOutlet UIImageView *bestNew;
@property (weak, nonatomic) IBOutlet UILabel *hisDurationLabel;
@property (weak, nonatomic) IBOutlet UILabel *hisDurationBottomLabel;
@property (weak, nonatomic) IBOutlet UILabel *hisDistanceLabel;
@property (weak, nonatomic) IBOutlet UILabel *hisDistanceBottomLabel;
@property (weak, nonatomic) IBOutlet UIButton *hisBackBtn;
@property (weak, nonatomic) IBOutlet UIButton *friendStatusButton;
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *hisDurationBottom;
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *tableViewBottom;
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *mineIcon1Gap;//65
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *mineIcon3Gap;//65
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *friendBtnLeading;
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *friendBtnTrailing;
@property (strong, nonatomic) NSArray *leftStrArray;
@property (strong, nonatomic) NSMutableArray *collectionArray;
@property (strong, nonatomic) NSString *userId;
@property (strong, nonatomic) NSDictionary *medalListDic;
@property (strong, nonatomic) NSString *userAvatar;//别人头像的链接url
@property (strong, nonatomic) NSDictionary *infoDictionary;
@property (strong, nonatomic) UICollectionView *medalCollectionView;
@property (assign, nonatomic) BOOL isFriend;//是否是好友关系
@property (strong, nonatomic) LRAvatarView *avatarView;
@property (assign, nonatomic) BOOL isFromPop;//如果是pop回来 不需要navigation动画
@property (assign, nonatomic) BOOL isFromPush;//如果是从push进来的,navigation隐藏时animation设为YES否则NO
@property (copy, nonatomic) NSString *pointsStr,*gradeStr,*feedStr; //积分 等级 动态
@property (copy, nonatomic) NSString *start_pos;
@property (strong, nonatomic) NSMutableArray *feedsArray;
@property (assign, nonatomic) BOOL isFromAddFriend;//从添加好友进来,直接底部显示‘加为好友’
@property (assign, nonatomic) BOOL isFromFriend;//从好友界面进来
@property (assign, nonatomic) BOOL isFromChatView;//从聊天页面进来
@property (assign, nonatomic) BOOL isFromDiscover;//从发现首页进来,返回时需要执行好友换一组操作
@property (strong, nonatomic) NSString *discoverId;//发现Id
@end
外界可以直接修改所有的参数,之所以别人将这段代码写成这个样子,主要是因为他不想在.m文件中在写interface~
.h文件
@interface LRComment : LRInteract
@property(copy,nonatomic) NSString *parentContent;/** 父级评论内容 */
@property(copy,nonatomic) NSString *parentUserId;/** 父级评论用户编
@property(copy,nonatomic) NSString *parentUsername;/** 父级评论用户名称,若为空,无父级评论 */
@property(strong,nonatomic,readonly) NSMutableArray *linkRangesForParentContent;//保存链接或者评论的地方
@end
.m文件
@interface LRComment()
//保存链接或者评论的地方
@property(strong,nonatomic) NSMutableArray *linkRangesForParentContent;
@end
封装代码,封装view,封装model,封装一切可能封装的东西
项目中大量存在着代码冗余,代码copy,导致了项目的臃肿
- list列表大量的
headerView
动画组加载代码 - 制作一些控制器的时候,会用到view,但是绝大多数都没封装,被人有相同的view,只能重写一个
- 未读消息数view没有封装。导致了未读消息树,有的时候使用了我封装的
SEBadgeButton
,有的时候使用了系统自带的badge,有的时候使用了label
,有的使用是用UIImageView
.基本每次都要复制一样的代码,及其不统一,修改颜色的时候,及其复杂!!! -
cell
的封装,应该暴露一个对象出来,当传递对象之后,然后更新UI和更新布局,越简单越好. - 还有很多,想不起来了...
//有问题的封装,和不封装没有任何区别
#import <UIKit/UIKit.h>
@interface LRMineTableCell : UITableViewCell
@property (weak, nonatomic) IBOutlet UIImageView *iconImage;
@property (weak, nonatomic) IBOutlet UILabel *leftlabel;
@property (weak, nonatomic) IBOutlet UILabel *rightLabel;
@property (weak, nonatomic) IBOutlet UIImageView *lineImage;
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *rightLabelTrailing;
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *lineImageLeading;
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *lineImageTrailing;
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *leftIconleading;
@end
#import "LRMineTableCell.h"
@implementation LRMineTableCell
- (void)awakeFromNib {
[super awakeFromNib];
if(iPhone6P){
self.rightLabelTrailing.constant = self.lineImageLeading.constant = self.lineImageTrailing.constant = 10;
}
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
@end
//实际的使用过程
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
if(!self.userId){
//我的
LRMineTableCell *cell = [tableView dequeueReusableCellWithIdentifier:@"LRMineTableCell"];
if (!cell) {
cell = [[LRMineTableCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"LRMineTableCell"];
}
[cell.iconImage setImage:[UIImage imageNamed:[NSString stringWithFormat:@"MineListIcon%ld",(long)indexPath.row]]];
cell.leftlabel.text = [self.leftStrArray objectAtIndex:indexPath.row];
cell.lineImage.hidden = cell.rightLabel.hidden = YES;
switch (indexPath.row) {
case 0:
{
//消息
cell.lineImage.hidden = NO;
int messageNumber = [[GXTools getUnreadOnlyMessageCount] intValue];
if(messageNumber>0){
for(UIView *view in cell.subviews){
if(view.tag==1001){
[view removeFromSuperview];
}
}
UIImageView *numberBG = [[UIImageView alloc] initWithImage:[UIImage imageNamed:messageNumber>=10?@"MineMessageNumberBG2":@"MineMessageNumberBG1"]];
UILabel *messageNumberLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, numberBG.image.size.width, numberBG.image.size.height)];
messageNumberLabel.backgroundColor = [UIColor clearColor];
messageNumberLabel.textColor = [UIColor whiteColor];
messageNumberLabel.textAlignment = NSTextAlignmentCenter;
messageNumberLabel.font = LR_ANC_FONT(12);
messageNumberLabel.text = messageNumber>99?@"⋅⋅⋅":[NSString stringWithFormat:@"%d",messageNumber];
[numberBG setFrame:CGRectMake(cell.width-30-numberBG.image.size.width, (cell.height-numberBG.image.size.height)/2, numberBG.image.size.width, numberBG.image.size.height)];
numberBG.tag = 1001;
[numberBG addSubview:messageNumberLabel];
[cell addSubview:numberBG];
}else{
for(UIView *view in cell.subviews){
if(view.tag==1001){
[view removeFromSuperview];
}
}
}
}
break;
case 1:
//好友
{
int applyCount = [[GXTools getAsynchronousWithKey:UD_KEY_FRIEND_APPLY_COUNT] intValue];
if(applyCount>0){
for(UIView *view in cell.subviews){
if(view.tag==1002){
[view removeFromSuperview];
}
}
UIImageView *numberBG = [[UIImageView alloc] initWithImage:[UIImage imageNamed:applyCount>=10?@"MineMessageNumberBG2":@"MineMessageNumberBG1"]];
UILabel *applyNumberLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, numberBG.image.size.width, numberBG.image.size.height)];
applyNumberLabel.backgroundColor = [UIColor clearColor];
applyNumberLabel.textColor = [UIColor whiteColor];
applyNumberLabel.textAlignment = NSTextAlignmentCenter;
applyNumberLabel.font = LR_ANC_FONT(12);
applyNumberLabel.text = applyCount>99?@"⋅⋅⋅":[NSString stringWithFormat:@"%d",applyCount];
[numberBG setFrame:CGRectMake(cell.width-30-numberBG.image.size.width, (cell.height-numberBG.image.size.height)/2, numberBG.image.size.width, numberBG.image.size.height)];
numberBG.tag = 1002;
[numberBG addSubview:applyNumberLabel];
[cell addSubview:numberBG];
}else{
for(UIView *view in cell.subviews){
if(view.tag==1002){
[view removeFromSuperview];
}
}
}
}
break;
///正确的写法
import UIKit
let LRInteractCellIndentifier = "LRInteractCellIndentifier"
class LRInteractCell: UITableViewCell {
public class func interactCellWithTableView(_ tableView:UITableView) -> LRInteractCell{
var cell = tableView.dequeueReusableCell(withIdentifier: LRInteractCellIndentifier)
if cell == nil{
cell = LRInteractCell.init(style: .default, reuseIdentifier: LRTopicCellIdentifier)
}
return cell as! LRInteractCell
}
//更新数据
public var interactF:LRInteractFrame?{
didSet{
replyView.interactF = interactF
beFeedStatusView.interactF = interactF
}
}
fileprivate lazy var replyView:LRReplyView = {
let rv = LRReplyView()
return rv
}()
fileprivate lazy var beFeedStatusView:LRBeFeedStatusView = {
let bfsv = LRBeFeedStatusView()
return bfsv
}()
override init(style: UITableViewCellStyle, reuseIdentifier: String?){
super.init(style: style, reuseIdentifier: reuseIdentifier)
setupBasicUI()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder:aDecoder)
setupBasicUI()
}
fileprivate func setupBasicUI(){
self.selectionStyle = .none
isUserInteractionEnabled = true
contentView.isUserInteractionEnabled = true
contentView.addSubview(replyView)
contentView.addSubview(beFeedStatusView)
}
//绘制一个分割线
override func draw(_ rect: CGRect) {
super.draw(rect)
let ctx = UIGraphicsGetCurrentContext()
ctx?.move(to: CGPoint.init(x:LRCommonMargin15,y:height))
ctx?.addLine(to: CGPoint.init(x:LRScreenWidth-LRCommonMargin15,y:height))
LRColorSepLineGray.set()
ctx?.setLineWidth(1)
ctx?.strokePath()
}
}
//外界使用过程,直接给VC减轻负担
//cell
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = LRInteractCell.interactCellWithTableView(tableView)
let cmtFrame = listModels[indexPath.row] as! LRInteractFrame
cell.interactF = cmtFrame
return cell
}
解决:写的时候问问同事在项目中有无该控件,如果有,直接使用,如果没有,自己分装,然后在小群里说一下,让大家知道,避免重复分装
分类名称的写法
分类分为写框架和普通项目
普通项目,建议直接写名称为UIView+LRExtension
。
应该创建一个文件夹,专门存储分类
view的高度写成常量
view如果外界需要他,建议写成一个常量,将来直接使用,好处在于,可以统一调控,很多赋值的界面还是有问题的。OC的话,可以使用extern
关键字
供外界使用,要写LR
项目前缀,SE
是我之前项目的前缀
自己view使用的,直接使用kLR
即可,具体要写清楚是修饰什么东西的.
#import <UIKit/UIKit.h>
extern CGFloat const SEBadgeButtonHeight;
@interface SEBadgeButton : UIButton
@property (nonatomic, copy) NSString *badgeValue;
@property (nonatomic, assign) CGFloat badgeWidth;
@end
#import "SEBadgeButton.h"
#import "NSString+LRExtension.h"
CGFloat const SEBadgeButtonHeight = 100.0;
static CGFloat const kSEBadgeTitleHeight = 44.0;
@interface SEBadgeButton()
@end
使用storyboard
尽量不要是用sb,非要使用sb的话,复杂的页面避免使用sb,sb应该和控制器放在一起,不能将所有的页面全部都一个sb钟,这样牵一发动全身
现在项目中的sb都是一个main非常的不便利,导致了冲突时长发生,而且好多界面都是sb出的,修改起来非常的复杂,给别人带来了不变。所以尽量少用sb.
三个及以上的变量必须要换行,代码的大小写统一
//这个是正确的,但是我们项目中,matchType
的位置很多都写成了MatchType
首字母大写了。这个是不对的。还有,超过了3个参数,就应该在调用和声明的时候,换行,过去我认为没有必要,但是看了别人的代码之后,又会不舒服,所以自己就改了
//函数
/**
* 已完成比赛
*
* @param index 第几页
* @param matchType 比赛的类别 (有两个常量)
* @param ntrpRange 等级
* @param timestamp 时间戳
*/
- (void)fetchCompletedMatchListWithPageIndex:(NSInteger)index
matchType:(NSString *)matchType
ntrpRange:(CGFloat)ntrpRange //等级
timestamp:(NSString *)timestamp
Success:(FetchDataSourceModelSuccessBlock)success
failure:(CustomFailureBlock)failure;
.view.frame = CGRect.init(x:lx,y:ly,width:lW,height:lH)的写法
这个要注意,一共要两点
- 1.换行
- 2.避免计算在init中,看着费事
//不好的方法
_datePicker.frame = CGRectMake(0, kHeight-kPickerHeight, kWidth, kPickerHeight);
_datePickerToolbar.frame = CGRectMake(0, _datePicker.frame.origin.y - kPickerToolBarHeight, kWidth, kPickerToolBarHeight);
//提出来,可以不用换行也行
CGFloat commonMargin = 15;
//1.头像
CGFloat hX = commonMargin;
CGFloat hY = commonMargin;
CGFloat hW = 40;
CGFloat hH = hW;
_headIconF = CGRectMake(hX, hY, hW, hH);
//2.名字
UIFont *nameFont = [[UIFont alloc] initWithSize:13 type:LRFontTypePingFang];
CGFloat nX = commonMargin + CGRectGetMaxX(_headIconF);
CGFloat nY = 19;
CGFloat nW = [interact.userName calculateTextSizeWithTextFont:nameFont].width;
CGFloat nH = commonMargin;
_nameF = CGRectMake(nX, nY, nW, nH);
使用胖model给控制器减肥,暴露出一个属性,可以让大家减少重复的计算
使用胖model,减少数据的重复计算,既可以减少控制器的压力,还能分装代码,一举两得.
更具不同的情况,我们要注意重写他们的set
或者get
方法.
- (void)setShareData:(LRShare *)shareData{
_shareData = shareData;
//在这里计算一下所有的text
NSString *tmpDistance = [GXTools twoDecimalPlacesFromDouleValue:[NSString stringWithFormat:@"%f",shareData.distance/1000.000]];
_shareData.distanceText = [NSString stringWithFormat:@"%@km",tmpDistance];
_shareData.durationText = [GXTools timeFormatFromSeconds:(int)shareData.duration];
_shareData.speedText = [GXTools speedFormatWithSpeed:shareData.speed];
}
//这个位置,应该在整个字典转模型结束去做。写get虽然只会去计算一次,但是也会阻塞主线程,将来再去优化代码
- (NSAttributedString *)beFeedAttriText{
if (_beFeedAttriText == nil){
//应该判断一下是不是需要的类型,如果是需要的类型,那么我们才去计算数据
if (_shareType == LRShareSourceHistory
|| _shareType == LRShareSourceLink
|| _shareType == LRShareSourceScoreList
|| _shareType == LRShareSourceRank)
{
return nil;
}
NSString *feedUserName = _feedUserName;
NSString *feedCnt = nil; //origin的内容
if (_feedContent == nil || _feedContent.length == 0){
feedCnt = @"上传了一张图片";
}else{
feedCnt = _feedContent;
}
//构建出一个 name(橙色):content(灰色)的富文本
NSMutableAttributedString *presentAttriText = [self appendPresentAttriTextWithFeedUserName:feedUserName
feedContent:feedCnt];
//高亮连接
presentAttriText = [self highlightLinksWithPresentAttriText:presentAttriText];
//高亮主题
presentAttriText = [self highlightTopicNameWithPresentAttriText:presentAttriText];
_beFeedAttriText = presentAttriText;
//计算文字的size
_beFeedAttrTextSize = [self calculateTextWithPresentAttriText:presentAttriText];
}
return _beFeedAttriText;
}
不要去修改牛逼的第三方。sd,afn 我们项目有修改的情况,消耗性能
项目中的AFN
和SDWebImage
这些库,影响这很多空间,所以不可以去修改,但是可以写某些分类,减少对整个项目的影响。
- (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageCompletionBlock)completedBlock {
[self sd_cancelCurrentImageLoad];
if ([url.absoluteString containsString:@"profile/avatar?"]) {
NSString *baseUrl;
if([[GXTools getAsynchronousWithKey:UD_KEY_AUDIT_USER_NAME] isEqualToString:@"15811281972"]){
baseUrl = @"http://123.56.228.13:8080/api/v1/";
}else{
baseUrl = BASE_URL;
}
NSURL *cookieHost = [NSURL URLWithString:[NSString stringWithFormat:@"%@%@",baseUrl,@"profile/avatar"]];
NSDictionary *dic = @{@"user_id":[GXTools getAsynchronousWithKey:UD_KEY_USER_ID],
@"token":[GXTools getAsynchronousWithKey:UD_KEY_USER_TOKEN]};
// 设定 cookie
[dic enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
NSHTTPCookie *cookie = [NSHTTPCookie cookieWithProperties:
[NSDictionary dictionaryWithObjectsAndKeys:
[cookieHost host], NSHTTPCookieDomain,
[cookieHost path], NSHTTPCookiePath,
key,NSHTTPCookieName,
obj,NSHTTPCookieValue,
nil]];
[[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookie:cookie];
}];
}
objc_setAssociatedObject(self, &imageURLKey, url, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
if (!(options & SDWebImageDelayPlaceholder)) {
dispatch_main_async_safe(^{
self.image = placeholder;
});
}
不要无用的打印
减少无用的打印,尽量保证打印栏目中的干净,调试完数据之后,及时关闭,因为影响心情和消耗性能.
可以使用LRLog
代替,但是网络的打印不应该全都打印出来,这个非常的不好,现在的项目中控制台永远都不会停止!!!
Block的写法
请使用SDWebImage
的写,有前缀.并且要宏定义一下。然后这样可以将所
LRNoParaBlock
Swift
中用Close
结尾
不要重复写东西,要去看看之前有无写,即使自己写,也要按照标准,少用int
,应该使用NSInteger
图片的命名
1.小写+下划线.说明白具体做什么的。因为图片的命名通常很长,使用小写+下划线能区分出来loc和功能
2.放到文件夹中,并且文件夹的名称用驼峰命名
所属页面(或模块)+干啥的+(状态情况,可有可无)
[图片上传失败...(image-c96047-1509616761160)]
[图片上传失败...(image-4d0db0-1509616761160)]
[图片上传失败...(image-161ef1-1509616761160)]
指定一些颜色,字体,等宏定义
(过去认为没有必要,但是后来发现真的很有必要,统一调控),已于调控,而不是每个位置都写,这样非常的方便。最好等号对其。如果是全局的,那么最好带上前缀,因为在项目中和很多第三方中,宽度的统一是用了kWidth
.都有报错重复。
很多人写项目不喜欢用前缀,是因为将来好放到其他项目中,但是在当前的项目中,看着就特别的不舒服.
let LRFontHKRegularSize13 = UIFont.init(size: 13, type: LRFontType.hkRegular)
let LRFontHKRegularSize14 = UIFont.init(size: 14, type: LRFontType.hkRegular)
let LRFontHKRegularSize15 = UIFont.init(size: 15, type: LRFontType.hkRegular)
let LRFontHKRegularSize17 = UIFont.init(size: 17, type: LRFontType.hkRegular)
//MARK: - 颜色
let LRColorGray33 = UIColor(gray:33)
let LRColorGray74 = UIColor(gray:74)
let LRColorGray165 = UIColor(gray:165)
let LRColorGray204 = UIColor(gray:204)
let LRColorGray232 = UIColor(gray:232)
let LRColorGray246 = UIColor(gray:246)
let LRColorLightOrangeAlphaHalf = UIColor.r(r: 255, g: 165, b: 0,alpha:0.5)//常用的文字橙色半透明
let LRColorSepLineGray = UIColor.colorFromHex(hexValue: 0xeaeaea)//常用的cell分割线灰色
let LRColorAlphaBlackSwift = UIColor.init(red: 0, green: 0, blue: 0, alpha: 0.5)//透明的颜色
public let LRScreenWidth: CGFloat = UIScreen.main.bounds.size.width
public let LRScreenHeight: CGFloat = UIScreen.main.bounds.size.height
public let LRScreenBounds: CGRect = UIScreen.main.bounds
public let LRCommonMargin15:CGFloat = 15.0
public let LRCommonMargin10:CGFloat = 10.0
给控制器瘦身
不要将所有的东西都放到控制器中,代码冗余,还有就是好几千行,不封装等等问题。给别人修改造成了困扰
- 1.控制器写方法啥的都要统一,
handleXXXX
,遵循一套命名的标准规范和顺序 参考文档 - 2.使用胖model,减少代码的重复计算啥的
- 3.分装代码,将和控制器无用的逻辑给不同的view,高度分装。尤其是cell,别封装和不分装似的,没有任何作用。
- 4.代码相同,可以写基类,有利于代码复用
- 5.写工具类,将加工的方法放到工具类中,然后减少垃圾代码的产生
- 6.没事多重构代码,将过去的代码没那么完美,总会有优化的地方
- 7.more...
属性的写法,nonamatic
,strong
,readonly
这个一般会写的比较乱,是因为三者的顺序乱,没有约定
我当时也没有去做处理。所以比较乱
/** befeedStatus富文本属性*/
@property(strong,nonatomic) NSAttributedString *beFeedAttriText;
/** 文字的size*/
@property(assign,nonatomic) CGSize beFeedAttrTextSize;
/** 评论的东西(为了给他行间距) */
@property(strong,nonatomic) NSAttributedString *attriContent;
/** 文字的size*/
@property(assign,nonatomic) CGSize attriContentSize;
/** 判断是什么类型的*/
@property(nonatomic,assign,getter=isInteract,readonly) BOOL interact;
以后的顺序
- 1.
nonamatic
- 2.
strong
- 3.
getter
- 4.
readonly
特殊代码
//别用这种代码
- (void)showMine{
self.hisBackBtn.hidden = self.hisDurationLabel.hidden = self.hisDistanceLabel.hidden = self.hisDistanceBottomLabel.hidden = self.hisDurationBottomLabel.hidden = YES;
self.mineIcon1.hidden = self.mineIcon2.hidden = self.mineIcon3.hidden = self.mineIconBottom1.hidden = self.mineIconBottom2.hidden = self.mineIconBottom3.hidden = NO;
}
- (void)showHis{
self.hisDurationLabel.hidden = self.hisDistanceLabel.hidden = self.hisDistanceBottomLabel.hidden = self.hisDurationBottomLabel.hidden = NO;
self.mineIcon1.hidden = self.mineIcon2.hidden = self.mineIcon3.hidden = self.mineIconBottom1.hidden = self.mineIconBottom2.hidden = self.mineIconBottom3.hidden = self.medalNew.hidden = self.bestNew.hidden = YES;
}
//应该使用懒加载去处理
- (nullable UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section{
if(!self.userId){
return nil;
}else{
//他的
if(self.isFriend){
return nil;
}else{
if(self.feedsArray.count>0){
UIView *footerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, kWidth, 57)];
footerView.backgroundColor = GXColor(255, 255, 255);
UIView *lineView = [[UIView alloc] initWithFrame:CGRectMake(15, 0, kWidth-30, 1)];
lineView.backgroundColor = GXColor(240, 240, 240);
[footerView addSubview:lineView];
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 20, kWidth, 17)];
label.textColor = GXColor(165, 165, 165);
label.font = LRFont(12);
label.textAlignment = NSTextAlignmentCenter;
label.text = @"加为好友查看全部动态";
[footerView addSubview:label];
return footerView;
}else{
return nil;
}
}
}
}
网友评论