iOS項(xiàng)目筆記

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è)鏤空的圓形圖片


corner_circle@2x.png

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中展示九宮格布局的情況:
比如

屏幕快照 2017-01-12 下午6.44.17.png

由于,此界面是由一個(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

解決方法:

  1. 在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ì)話頁面更換用戶頭像和昵稱

![WechatIMG2.jpeg](http://upload-images.jianshu.io/upload_images/2135374-9f4e0d13aa7145d0.jpeg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
經(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)

    }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,182評(píng)論 6 543
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,489評(píng)論 3 429
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,290評(píng)論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,776評(píng)論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 72,510評(píng)論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,866評(píng)論 1 328
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,860評(píng)論 3 447
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 43,036評(píng)論 0 290
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,585評(píng)論 1 336
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 41,331評(píng)論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,536評(píng)論 1 374
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,058評(píng)論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,754評(píng)論 3 349
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,154評(píng)論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,469評(píng)論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 52,273評(píng)論 3 399
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,505評(píng)論 2 379

推薦閱讀更多精彩內(nèi)容