1.根據(jù)服務(wù)端返回的json 字符串中的 \n 讓label的文字換行
UIFont *ltextFont = [UIFont systemFontOfSize:14];
NSString *str = @"活動(dòng)時(shí)間:2016年12月23日--2017年1月6日\n作品要求:設(shè)計(jì)稿,形式體裁不限,作品尺寸為A4紙。將作品以圖文的形式參與話題,文字注明城市與名字,自建話題無效。\n評(píng)選方式:平臺(tái)用戶以點(diǎn)贊方式投票\n活動(dòng)獎(jiǎng)勵(lì):前三名的作品除平臺(tái)金幣獎(jiǎng)勵(lì)外,還會(huì)獲得超牛逼涂鴉書籍。";
CGSize size = [str sizeWithFont: ltextFont constrainedToSize:CGSizeMake(CGRectGetWidth([UIScreen mainScreen].bounds), MAXFLOAT)lineBreakMode:NSLineBreakByWordWrapping];
UILabel *label = [[UILabel alloc]initWithFrame:CGRectMake(0,200,size.width,size.height)];
label.numberOfLines = 0; // 最關(guān)鍵的一句
label.text = str;
label.font = ltextFont;
[self.view addSubview:label];
2.顯示時(shí)間(幾分鐘前,幾小時(shí)前,幾天前)
+ (NSString *)compareCurrentTime:(NSString *)str {
NSString *timeStr = @"2016-02-22 19:27:38";
// 將時(shí)間字符串轉(zhuǎn)換為NSDate
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"yyy-MM-dd HH:mm:ss"];
NSDate *timeDate = [dateFormatter dateFromString:timeStr];
// 獲取當(dāng)前時(shí)間
NSDate *currentDate = [NSDate date];
// 獲取當(dāng)前時(shí)間距離timeStr的時(shí)間差
NSTimeInterval timeInterVal = [currentDate timeIntervalSinceDate:timeDate];
long temp = 0;
NSString *resultStr;
if (timeInterVal / 60 < 1) {
resultStr = @"剛剛";
} else if ((temp = timeInterVal / 60) < 60) {
resultStr = [NSString stringWithFormat:@"%ld分鐘前", temp];
} else if ((temp = temp / 60) < 24) {
resultStr = [NSString stringWithFormat:@"%ld小時(shí)前", temp];
} else if ((temp = temp / 24) < 30) {
resultStr = [NSString stringWithFormat:@"%ld天前", temp];
} else if ((temp = temp / 30) < 12) {
resultStr = [NSString stringWithFormat:@"%ld月前", temp];
} else {
temp = temp / 12;
resultStr = [NSString stringWithFormat:@"%ld年前", temp];
}
return resultStr;
}
3.中文斜體
經(jīng)查閱資料-- iOS中不支持中文字體傾斜,只有設(shè)置傾斜角度
// 1.設(shè)置反射。傾斜15度
CGAffineTransform matrix = CGAffineTransformMake(1, 0, tanf(15 * (CGFloat)M_PI / 180), 1, 0, 0);
// 2.取得系統(tǒng)字符并設(shè)置反射
UIFontDescriptor *desc = [ UIFontDescriptor fontDescriptorWithName:[UIFont systemFontOfSize :18].fontName matrix:matrix];
// 3.獲取字體
UIFont *font = [UIFont fontWithDescriptor:desc size:18];
self.rankingBtn.titleLabel.font = font;
// 4.設(shè)置文字的字體,可以畫出來
[string. text drawInRect :dr withFont :font lineBreakMode : NSLineBreakByTruncatingTail ];
// 也可以直接設(shè)置,比如
// [self.rankingBtn setTitle:viewModel.item.ranking forState:UIControlStateNormal];
通過以上方法--繪制出斜體字。
4.iOS四種切除圓角的方法
- 通過shapeLayer設(shè)置
通過bezizerpath設(shè)置一個(gè)路徑,加到目標(biāo)視圖的layer上。代碼如下
// 創(chuàng)建一個(gè)view
UIView *showView = [[UIView alloc] initWithFrame:CGRectMake(100, 100, 100, 100)];
[self.view addSubview:showView];
showView.backgroundColor = [UIColor whiteColor];
showView.alpha = 0.5;
// 貝塞爾曲線(創(chuàng)建一個(gè)圓)
UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(100 / 2.f, 100 / 2.f)
radius:100 / 2.f
startAngle:0
endAngle:M_PI * 2
clockwise:YES];
CAShapeLayer *layer = [CAShapeLayer layer];
layer.frame = showView.bounds;
layer.path = path.CGPath;
[showView.layer addSublayer:layer];
- 通過view的layer設(shè)置
- (UIImageView *)avatarImage {
if (!_avatarImage) {
_avatarImage = [[UIImageView alloc] initWithFrame:CGRectMake(20,10, avatarDiameter, avatarDiameter)];
_avatarImage.backgroundColor = [UIColor grayColor];
_avatarImage.contentMode = UIViewContentModeScaleAspectFit;
_avatarImage.layer.cornerRadius = avatarDiameter/2.0;
_avatarImage.layer.masksToBounds = YES;
[_avatarImage setImage:[UIImage imageNamed:@"test.jpg"]];
}
return _avatarImage;
}
- 通過BezierPath設(shè)置
- (instancetype)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
}
return self;
}
// 自定義一個(gè)類繼承自UIView,使用drawRect畫圓
- (void)drawRect:(CGRect)rect {
// Drawing code
CGRect bounds = self.bounds;
[[UIColor whiteColor] set];
UIRectFill(bounds);
[[UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:CGRectGetWidth(bounds)/2.0] addClip];
[self.image drawInRect:bounds];
}
- 通過貼圖的方式設(shè)置
貼圖的方式是利用一張中間為透明圓形的圖片來進(jìn)行遮蓋,注意:要讓圓形圖片所在的cell的背景顏色與貼圖的背景顏色相同, 代碼如下:
// 頭像控件
self.headerView = [UIButton buttonWithType:UIButtonTypeCustom];
self.headerView.backgroundColor = kColorGlobalCell;
self.headerView.hidden = NO;
self.headerView.tag = NSIntegerMax;
self.headerView.clipsToBounds = YES;
[self.contentView addSubview:self.headerView];
// 鏤空的圓形圖片蓋在頭像上面,目的是讓頭像顯示為圓形,
self.cornerImageView = [[UIImageView alloc] init];
self.cornerImageView.center = self.headerView.center;
self.cornerImageView.image = [UIImage imageNamed:@"corner_circle"];
self.cornerImageView.tag = NSIntegerMax;
[self.contentView addSubview:self.cornerImageView];
self.headerView.frame = self.viewModel.headerFrame;
self.cornerImageView.frame = CGRectMake(0, 0, CGRectGetWidth(self.viewModel.headerFrame)+5, CGRectGetHeight(self.viewModel.headerFrame)+5);
self.cornerImageView.center = self.headerView.center;
利用透明圓形的圖片來進(jìn)行遮蓋,會(huì)引起blending,但性能仍然很高的
Blending:
在iOS的圖形處理中,blending主要指的是混合像素顏色的計(jì)算。最直觀的例子就是,我們把兩個(gè)圖層疊加在一起,如果第一個(gè)圖層的透明的,則最終像素的顏色計(jì)算需要將第二個(gè)圖層也考慮進(jìn)來。這一過程即為Blending。
會(huì)導(dǎo)致blending的原因:
layer(UIView)的Alpha < 1
UIImgaeView的image含有Alpha channel(即使UIImageView的alpha是1,但只要image含透明通道,則仍會(huì)導(dǎo)致Blending)
為什么Blending會(huì)導(dǎo)致性能的損失?
原因是很直觀的,如果一個(gè)圖層是不透明的,則系統(tǒng)直接顯示該圖層的顏色即可。而如果圖層是透明的,則會(huì)引入更多的計(jì)算,因?yàn)樾枰严旅娴膱D層也包括進(jìn)來,進(jìn)行混合后顏色的計(jì)算。
下面是一個(gè)鏤空的圓形圖片
5 將NSInteger類型的秒,轉(zhuǎn)換為00:00:00格式
- (NSString *)coverTime:(NSInteger)secondCount {
// 時(shí)
NSString *tmphh = [NSString stringWithFormat:@"%ld",secondCount / 3600];
NSLog(@"tmphh--%@", tmphh);
if ([tmphh length] == 1){
tmphh = [NSString stringWithFormat:@"0%@",tmphh];
}
// 分
NSString *tmpmm = [NSString stringWithFormat:@"%ld",(secondCount / 60) % 60];
if ([tmpmm length] == 1) {
tmpmm = [NSString stringWithFormat:@"0%@",tmpmm];
}
// 秒
NSString *tmpss = [NSString stringWithFormat:@"%ld",secondCount % 60];
if ([tmpss length] == 1)
{
tmpss = [NSString stringWithFormat:@"0%@",tmpss];
}
// NSLog(@"%@:%@", tmphh, tmpmm);
return [NSString stringWithFormat:@"%@:%@:%@",tmphh,tmpmm,tmpss];
}
6 當(dāng)需要在tableView中展示九宮格布局的情況:
比如
由于,此界面是由一個(gè)tableView構(gòu)成的,現(xiàn)在要在原有的基礎(chǔ)上添加添加一個(gè)子標(biāo)題,點(diǎn)擊后就是這種九宮格布局,為了在原因基礎(chǔ)上搭建界面,最好在tableViewCell中嵌套一個(gè)collectionView,用collectionViewCell展示每一個(gè)九宮格數(shù)據(jù),而且這樣tableView直接把數(shù)據(jù)源給collectionView,方便其展示數(shù)據(jù):
- 首先tableViewCell只需要一個(gè)即可,將collectionView添加到- tableViewCell的contenView中,
- 將collectionView的scrollEnabled設(shè)置為 NO,直接讓tableView接受滾動(dòng)事件,
- 最后需要計(jì)算tableViewCell的高度,其實(shí)tableViewCell的高度就是collectionView的contentSize,如果每個(gè)collectionViewCell高度相同,高度根據(jù)數(shù)據(jù)源的個(gè)數(shù),以及需要每行展示幾個(gè)來計(jì)算,
比如每行展示2個(gè),那就是[ 行數(shù)(數(shù)據(jù)源的個(gè)數(shù) / 2) * 每一行的高度],如果與2取余為1,也要加上一行
7 讓創(chuàng)建出來的UILabel 上下左右有間隙
某些情況下,需要讓UIlabel的上下左右有一定的間隙,有時(shí)候設(shè)置textAlignment并不能解決問題,比如文本已經(jīng)設(shè)置了右對(duì)其了,但需求還是要讓文本向左偏移一些,以下方法即可解決
解決方法:創(chuàng)建UILabel的子類使其能夠讓文字有上下左右的空隙,通過drawTextInRect方法實(shí)現(xiàn)
@implementation XYUserHomePageViewContentLabel {
UIEdgeInsets _insets;
}
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
self.textColor = kColorNameTextBlack;
self.font = kFontWithSize(15);
self.textAlignment = NSTextAlignmentRight;
self.backgroundColor = [UIColor whiteColor];
// 根據(jù)情況設(shè)置UIEdgeInsets _insets屬性
// 讓文本向左偏移15的距離
_insets = UIEdgeInsetsMake(0.0f, 0.0f, 0.0f, 10.0f);
}
return self;
}
- (void)drawTextInRect:(CGRect)rect {
[super drawTextInRect:UIEdgeInsetsInsetRect(rect, _insets)];
}
8 自定義導(dǎo)航條后,側(cè)滑手勢(shì)失效問題:
8.1 第一種情況:恢復(fù)系統(tǒng)默認(rèn)的側(cè)滑手勢(shì)
第一步:自定義一個(gè)導(dǎo)航欄,并重寫它的 viewDidLoad方法
系統(tǒng)默認(rèn)的手勢(shì)為
interactivePopGestureRecognizer
當(dāng)導(dǎo)航控制器響應(yīng)的默認(rèn)手勢(shì)時(shí),我們就重新設(shè)置手勢(shì)的代理不再是系統(tǒng)的 UINavagtionController,而是我們自定義的這個(gè)導(dǎo)航控制器 , 再設(shè)置導(dǎo)航控制器的代理為它自己,因?yàn)橐粫?huì)還要監(jiān)聽它自己的代理方法
- (void)viewDidLoad {
[super viewDidLoad];
__weak typeof(self) weakSelf = self;
if ([self respondsToSelector:@selector(interactivePopGestureRecognizer)]) {
self.interactivePopGestureRecognizer.delegate = weakSelf;
self.delegate = weakSelf;
}
}
第二步 :重寫導(dǎo)航控制器的pushViewController方法
重寫 push 方法最主要的目的是讓這個(gè) pop 手勢(shì)在 push 的時(shí)候變?yōu)椴豢捎茫驗(yàn)榭赡茉?push 過程中用戶很快的進(jìn)行了左滑動(dòng),那么就會(huì)造成 pop 棧中的混亂,導(dǎo)致畫面卡頓,所以為了避免這個(gè)情況,我們必須要設(shè)置在 Push 過程中禁止這個(gè)手勢(shì)的響應(yīng)
- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated {
if (self.childViewControllers.count > 0) {
[viewController setHidesBottomBarWhenPushed:YES];
// 自定義導(dǎo)航條左側(cè)返回按鈕
UIButton *backBarButton = [UIButton buttonWithType:UIButtonTypeCustom];
[backBarButton setImage:[UIImage imageNamed:@"Login_backSel"].xy_originalMode forState:UIControlStateNormal];
backBarButton.contentEdgeInsets = UIEdgeInsetsMake(0, -20, 0, 0);
[backBarButton sizeToFit];
viewController.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:backBarButton];
// 如果自定義返回按鈕后,
if ([self respondsToSelector:@selector(interactivePopGestureRecognizer)]) {
self.interactivePopGestureRecognizer.enabled = NO;
}
}
[super pushViewController:viewController animated:animated];
}
第三步 :監(jiān)聽導(dǎo)航控制器 是否顯示完畢 的 代理方法
這個(gè)方法主要是監(jiān)聽導(dǎo)航欄是否顯示完畢,當(dāng)顯示完畢的時(shí)候我們要進(jìn)行一個(gè)判斷,因?yàn)楫?dāng)控制器ViewController 數(shù)量為1的時(shí)候,用戶如果進(jìn)行了右滑,但問題是當(dāng)前控制器數(shù)量只有一個(gè),那個(gè)這個(gè)方法 POP 什么呢?根本就沒法 POP 嘛,也會(huì)造成了 pop 棧中的混亂,導(dǎo)致畫面一直卡頓,所以我們也要進(jìn)行一個(gè)判斷,判斷控制器數(shù)量只有一個(gè)的時(shí)候,我們就禁止了這個(gè)手勢(shì),反之則開啟
#pragma mark - UINavigationControllerDelegate
- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
if (navigationController.childViewControllers.count == 1) {
self.interactivePopGestureRecognizer.enabled = NO;
} else {
self.interactivePopGestureRecognizer.enabled = YES;
}
}
當(dāng)然,我們?cè)谧远x的導(dǎo)航條的左側(cè)返回按鈕時(shí),監(jiān)聽返回的方法中,最好讓返回按鈕判斷當(dāng)前是 push 還是 modal顯示的,根據(jù)當(dāng)前情況進(jìn)行 pop 和 disMiss
- (void)backBarButton {
// 判斷兩種情況: push 和 present
if ([self isPresent]) {
[self dismissViewControllerAnimated:YES completion:^{
}];
}else {
[[self navigationController] popViewControllerAnimated:YES];
}
}
- (BOOL)isPresent {
BOOL isPresent;
NSArray *viewcontrollers = self.viewControllers;
if (viewcontrollers.count > 1) {
if ([viewcontrollers objectAtIndex:viewcontrollers.count - 1] == self) {
isPresent = NO; //push方式
}
}
else{
isPresent = YES; // modal方式
}
return isPresent;
}
8.2 第二種情況,全屏滑動(dòng)返回
自定義導(dǎo)航控制器
- (void)viewDidLoad {
[super viewDidLoad];
id target = self.interactivePopGestureRecognizer.delegate;
self.interactivePopGestureRecognizer.enabled = NO;
// 全屏滑動(dòng)返回手勢(shì)
UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:target action:@selector(handleNavigationTransition:)];
[self.view addGestureRecognizer:pan];
pan.delegate = self;
self.interactivePopGestureRecognizer.enabled = NO;
}
- (void)pushViewController:(XYProfileBaseController *)viewController animated:(BOOL)animated {
if ([viewController isKindOfClass:[XYProfileBaseController class]]) {
if (viewController.isHiddenLeftButton) {
viewController.hiddenLeftButton = self.childViewControllers.count < 1;
}
if (self.childViewControllers.count) {
viewController.hidesBottomBarWhenPushed = YES;
viewController.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"" style:UIBarButtonItemStylePlain target:viewController action:@selector(leftBtnClick:)];
}
}
[super pushViewController:viewController animated:animated];
}
#pragma mark - <UIGestureRecognizerDelegate>
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
return self.viewControllers.count > 1;
}
9 項(xiàng)目中app賬號(hào)與環(huán)信賬號(hào)的管理 - 登錄
第一種方法:只需要iOS與環(huán)信交互:用戶在我們的app注冊(cè)會(huì)員的時(shí)候,注冊(cè)成功獲得返回值,正確的返回值內(nèi)去注冊(cè)環(huán)信賬號(hào),而環(huán)信賬號(hào)就是用戶注冊(cè)app的賬號(hào)的uid,密碼是寫死的,例如
wiox8YvKZd23bbIYw
,任何用戶注冊(cè)時(shí),傳給環(huán)信的密碼都是相同的,這樣方便登錄。如果環(huán)信返回給你是注冊(cè)成功,此時(shí)需要在成功里創(chuàng)建NSUserDeafults存儲(chǔ)你的環(huán)信賬號(hào),密碼就不用存了,并且調(diào)用環(huán)信登錄方法。每次登錄時(shí)公司在環(huán)信的賬號(hào)會(huì)返回access_token、user信息及expires_in。登錄時(shí),公司服務(wù)器也會(huì)返回一個(gè)登錄信息的json,登錄成功時(shí)其中就有imUser即時(shí)通訊賬號(hào),使用imUser登錄環(huán)信用戶賬號(hào)密碼即可。
如果不在AppDelegate里寫登錄,你的APP如果退出了,下次打開就沒用了,所以必須時(shí)時(shí)刻刻登錄。所以你需要在AppDelegate登錄,賬號(hào)就是你本地存儲(chǔ)的賬號(hào)。密碼還是死的。如果正常流程來說就是:
1.注冊(cè)自己APP賬號(hào)-成功-注冊(cè)環(huán)信賬號(hào),密碼為死的-成功-登錄環(huán)信賬號(hào)。
2.登錄自己APP賬號(hào)-成功-登錄環(huán)信
3.AppDelegate存儲(chǔ)賬號(hào)。
第二種方法:讓iOS,服務(wù)器,環(huán)信交互:通過上面的那種方式,跟服務(wù)器唯一交互的就是密碼,你需要在用戶注冊(cè)你自己產(chǎn)品的時(shí)候,密碼也注冊(cè)環(huán)信。注冊(cè)成功,將密碼post給服務(wù)器,登錄的時(shí)候成功,服務(wù)器不光返回error,msg,還要加一個(gè)環(huán)信的password,這樣你拿到password 可以再進(jìn)行登錄。當(dāng)然注冊(cè)的時(shí)候Phone和Password需都需要存儲(chǔ),方便在AppDelegate入口類登錄。
1.注冊(cè)自己APP賬號(hào)-成功-注冊(cè)環(huán)信賬號(hào),密碼為注冊(cè)APP的密碼-成功-Post密碼給服務(wù)器-成功-登錄環(huán)信賬號(hào)。
2.登錄自己APP賬號(hào)-成功-拿到服務(wù)器返回的Password,登錄環(huán)信賬號(hào)-成功。
3.AppDelegate存儲(chǔ)賬號(hào)和密碼
// 在app啟動(dòng)后調(diào)用登錄IM
- (void)loginImUserAccount {
// 讀取用戶登錄后存儲(chǔ)的登錄信息
NSDictionary *loginInfo = [NSDictionary dictionaryWithContentsOfFile:kLoginInfoPath];
XYLoginInfoItem *item = [XYLoginInfoItem loginInfoItemWithDict:loginInfo];
// EMOptions設(shè)置配置信息 AppKey:注冊(cè)環(huán)信的AppKey。
EMOptions *options = [EMOptions optionsWithAppkey:@"wuwo#ziwo"];
//apnsCertName:推送證書名(不需要加后綴)
options.apnsCertName = @"MeSelf_APNS_DistriBution";
// 初始化SDK
EMError *error = [[EMClient sharedClient] initializeSDKWithOptions:options];
if (!error) {
NSLog(@"初始化成功");
}
// 使用用戶登錄成功后,使用公司服務(wù)端返回imUser賬號(hào)登錄環(huán)信
error = [[EMClient sharedClient] loginWithUsername:item.iyidamUser.username password:item.imUser.password];
if (!error) {
NSLog(@"登錄成功");
} else {
NSLog(@"登錄失敗-%@", error.errorDescription);
}
}
10 集成環(huán)信 3.2.3 相關(guān)問題
10.1 使用EaseUI 報(bào)錯(cuò)問題解決:
當(dāng)把EaseUI拖入到項(xiàng)目后進(jìn)行編譯,后報(bào)很多錯(cuò)誤: 比如連UIKit及NSString都找不到, 這是因?yàn)镋aseUI中加入了.c文件,屬于混編報(bào)錯(cuò),等于把PCH中的代碼都拷貝一份到.c文件中了,需要給導(dǎo)入到OC的文件加OBJC
解決方法:
- 在pch文件中在所有代碼的頭部加入
#ifdef __OBJC__
尾部加入#endif
如下:
#ifdef __OBJC__
// 中間放 之前所有的 代碼
#endif```
2.環(huán)信內(nèi)部集成的MBProgressHUD SDWebImage MJRefresh 與我們工程中集成的這幾個(gè)第三方庫發(fā)生沖突!刪掉工程中自己集成的這些第三方庫,或者刪除環(huán)信EaseUI 里面的這些第三方庫!
需要注意的是:如果刪除的是環(huán)信集成的第三方庫!由于環(huán)信在集成的第三方庫中加了EM前綴! 記得刪掉EaseUI 中使用方法的前綴,不然會(huì)報(bào)錯(cuò)!
[官方集成視頻地址](http://www.imgeek.org/video/23)
10.2 聊天會(huì)話頁面更換用戶頭像和昵稱

經(jīng)查看環(huán)信官網(wǎng)文檔:
解決方法:在EaseMessageViewController或其子類方法中設(shè)置其數(shù)據(jù)源EaseMessageViewControllerDataSource,在以下數(shù)據(jù)源方法中 將EMMessage類型轉(zhuǎn)換為符合<IMessageModel>協(xié)議的類型,設(shè)置用戶信息,消息顯示用戶昵稱和頭像。
pragma mark - EaseMessageViewControllerDataSource
/*!
@method
@brief 將EMMessage類型轉(zhuǎn)換為符合<IMessageModel>協(xié)議的類型
@discussion 將EMMessage類型轉(zhuǎn)換為符合<IMessageModel>協(xié)議的類型,設(shè)置用戶信息,消息顯示用戶昵稱和頭像
@param viewController 當(dāng)前消息視圖
@param EMMessage 聊天消息對(duì)象類型
@result 返回<IMessageModel>協(xié)議的類型
*/
-
(id<IMessageModel>)messageViewController:(EaseMessageViewController *)viewController
modelForMessage:(EMMessage *)message
{
//用戶可以根據(jù)自己的用戶體系,根據(jù)message設(shè)置用戶昵稱和頭像
id<IMessageModel> model = nil;
model = [[EaseMessageModel alloc] initWithMessage:message];
// 根據(jù)頭像所在的用戶是否為發(fā)送方,設(shè)置對(duì)應(yīng)的模型數(shù)據(jù)
if (model.isSender) { // 發(fā)送方
model.avatarImage = [UIImage imageNamed:@"EaseUIResource.bundle/user"];//默認(rèn)頭像
// 設(shè)置消息消息發(fā)送方的頭像和昵稱
AppDelegate *appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate ;model.avatarURLPath = [appDelegate.currentloginInfo.basePath stringByAppendingString:appDelegate.currentloginInfo.userInfo.head]; //頭像網(wǎng)絡(luò)地址 model.nickname = appDelegate.currentloginInfo.userInfo.name;//用戶昵稱
} else {
// 設(shè)置消息接收方的頭像和昵稱
model.avatarImage = [UIImage imageNamed:@"EaseUIResource.bundle/user"];//默認(rèn)頭像
model.avatarURLPath = self.user.headFullURL.absoluteString;//頭像網(wǎng)絡(luò)地址
model.nickname = self.user.name;//用戶昵稱
}return model;
}
10 集成友盟第三方登錄
當(dāng)?shù)谌绞跈?quán)成功后,使用第三方平臺(tái)獲取的相關(guān)字段,再給服務(wù)器發(fā)送登錄(一般需傳入deviceToken、head、name、openPlatform、openPlatformId、os、osVersion、phoneModel、versionCode ),獲取用戶的loginInfo信息,服務(wù)器返回的code碼為success為,就可以切換跟控制器了,再將loginInfo寫入到本地保存,每次進(jìn)入app后取出loginInfo進(jìn)行判斷用戶是否登錄,然后切換正確的跟控制器。
11 點(diǎn)贊、關(guān)注等接口的實(shí)現(xiàn)
當(dāng)用戶點(diǎn)贊時(shí)給服務(wù)器發(fā)送請(qǐng)求,傳入相應(yīng)的字段,當(dāng)服務(wù)器響應(yīng)成功時(shí),根據(jù)code碼判斷是否點(diǎn)贊成功;當(dāng)服務(wù)器返回的code為0時(shí),點(diǎn)贊成功,此時(shí)應(yīng)該修改對(duì)應(yīng)的模型數(shù)據(jù)(比如把模型的isPraise修改為YES,點(diǎn)贊數(shù)據(jù)+1), 再調(diào)用reloadData刷新表格,在cell的模型的set方法中進(jìn)行設(shè)置按鈕的選中狀態(tài)和按鈕是否可以響應(yīng)事件.
11 當(dāng)界面需要按照服務(wù)端返回的前十個(gè)模型進(jìn)行暫時(shí)排行榜單時(shí),并且服務(wù)端并未返回排名
解決方法:首先給模型添加一個(gè)擴(kuò)展屬性ranking,用于作為榜單的id,在請(qǐng)求服務(wù)器數(shù)據(jù)完成時(shí),開啟子線程對(duì)數(shù)據(jù)進(jìn)行處理,給前10個(gè)數(shù)據(jù)在模型中給ranking賦值,這里需要對(duì)數(shù)據(jù)源進(jìn)行遍歷,所以最好開啟子線程處理,當(dāng)處理到第10個(gè)數(shù)據(jù)時(shí),停止遍歷,并回到主線程中,刷新數(shù)據(jù)
代碼如下:
/// 對(duì)模型進(jìn)行處理 -- 為榜單前10個(gè)模型擴(kuò)展排名屬性
-
(void)processingModel:(void(^)())block {
dispatch_async(dispatch_get_global_queue(0, 0), ^{
// 榜單數(shù)據(jù) if (self.currentType == XYTopicTypeNewRanklist) { NSInteger i = 0; BOOL flag = YES; while (flag) { if (i>_dataList[@(self.currentType)].count-1 || _dataList[@(self.currentType)].count == 0) { flag = NO; break; } else { XYTopicViewModel *viewModel = _dataList[@(self.currentType)][i]; viewModel.item.ranking = [NSString stringWithFormat:@" NO.%ld", i+1]; if (i == 9) { flag = NO; break; } i++; } } // 要回到主線程中刷新數(shù)據(jù)源,不然會(huì)引發(fā)莫名其妙的更新榜單不顯示的問題 [[NSOperationQueue mainQueue] addOperationWithBlock:^{ if (block) { block(); } }]; // 其他請(qǐng)求,也要回到主線程中 } else { [[NSOperationQueue mainQueue] addOperationWithBlock:^{ if (block) { block(); } }]; }
});
}
12 OC項(xiàng)目中怎么創(chuàng)建Swift文件及OC與Swift代碼之間互相調(diào)用
首先在OC項(xiàng)目中創(chuàng)建一個(gè)類,Language選擇為Swift,創(chuàng)建后會(huì)彈出一個(gè)橋接文件,點(diǎn)擊創(chuàng)建即可,此時(shí)會(huì)產(chǎn)生一個(gè)```項(xiàng)目名-Bridging-Header.h```,此文件是為了swift代碼中使用oc代碼準(zhǔn)備的橋接文件,如果swift想要使用oc的某個(gè)類,直接在這個(gè)橋接文件中導(dǎo)入oc頭文件即可。
在OC需要使用到Swift類的類中導(dǎo)入```項(xiàng)目名-Swift.h```,然后就可以互相調(diào)用了,
13 Swift中獲取String 字符串的長(zhǎng)度
String結(jié)構(gòu)體中沒有Length的方法,但是可以通過Sting的擴(kuò)展屬性成員characters的count屬性來獲取
let title : String = "title"
let count = title.characters.count //獲取String字符串的長(zhǎng)度
print(count)
13 當(dāng)導(dǎo)航控制器下的tableView的偏移量出現(xiàn)了問題時(shí):
我設(shè)置了tableView的contentInset但是并未觸發(fā)scrollViewDidScroll事件,雖然contentInset沒有問題,但是導(dǎo)致初次進(jìn)入界面時(shí)tableView的偏移量不對(duì)
self.automaticallyAdjustsScrollViewInsets = false
tableView.contentInset = UIEdgeInsetsMake(64, 0, 0, 0)
所以手動(dòng)設(shè)置tableView.contentOffset
tableView.setContentOffset(CGPoint.init(x: 0, y: -64), animated: true)
14 Swift中使用Masonry布局的代碼格式:
headerLine.mas_makeConstraints { (make) in
make?.left.right().equalTo()(self)?.setOffset(0)
make?.bottom.equalTo()(self)?.setOffset(-margin)
make?.height.equalTo()(44)
}
figureSpecialView.mas_makeConstraints { (make) in
make?.top.left().right().equalTo()(self)?.setOffset(0)
make?.bottom.equalTo()(self.headerLine.mas_top)?.setOffset(-margin)
}