iOS日常问题总结

作者: 最后还是个农 | 来源:发表于2017-03-15 16:55 被阅读238次

    在外包公司成长中,遇到各种各样项目,总结一些遇到的问题。
    日常工作中用到的一些方法总结,有很简单介绍,可能也有错误,如果您看到了希望可以告诉我,会不间断更新。

    一、iOS 10以后拨打电话

    iOS 10以后,原来拨打电话的几种方式都不太好用,反应特别慢,苹果更新的新的API,使用openURL:options:completionHandler:替代了openURL,具体讲解请点击,谢谢大神的分享。

    示例代码:
    if (@available(iOS 10.0, *)) {
            // 拨打电话 iOS 10以后
            NSMutableString *str=[[NSMutableString alloc] initWithFormat:@"tel://%@",@"132****0983"];
            [[UIApplication sharedApplication] openURL:[NSURL URLWithString:str] options:@{} completionHandler:nil];
        } else {
            // 拨打电话 iOS 10以前
            NSMutableString *str=[[NSMutableString alloc] initWithFormat:@"tel://%@",@"132****0983"];
            UIWebView *callWebview = [[UIWebView alloc] init];
            [callWebview loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:str]]];
            [self.view addSubview:callWebview];
        }
    

    二、UIWebVIew加载网页时,让网页适应屏幕大小

    self.webView.scalesPageToFit = YES;
    

    三、更改UILabel中字距边框的距离

    要更改 Label 距离边框的距离就需要自定义 Label,需要重写drawTextInRect方法,重新绘制文本的位置;
    代码示例:

    -(void)drawTextInRect:(CGRect)rect{
        // 上下左右各距5
        [super drawTextInRect:CGRectMake(rect.origin.x + 5, rect.origin.y + 5, rect.size.width - 10, rect.size.height -10)];
    }
    

    三、解决“当子视图超出父视图范围,子视图点击事件无反应”问题

    需要重写父视图的-hitTest:withEvent:

    // self.backButton在父视图frame以外
    - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
        UIView *view = [super hitTest:point withEvent:event];
        if (view == nil) {
            // 转换坐标系
            CGPoint newPoint = [self.backButton convertPoint:point fromView:self];
            // 判断触摸点是否在button上
            if (CGRectContainsPoint(self.backButton.bounds, newPoint)) {
                view = self.backButton;
            }
        }
        return view;
    }
    

    四、获取某个View所在控制器

    写代码时,经常去封装一些视图,有时候在视图中去处理一些事件,难免会用到view所在的控制器,可以通过这个方法获取view所在控制器。

    // 获取当前控制器
    - (UIViewController *)findViewController:(UIView *)sourceView
    {
        id target = sourceView;
        while (target) {
            target = ((UIResponder *)target).nextResponder;
            if ([target isKindOfClass:[UIViewController class]]) {
                break;
            }
        }
        return target;
    }
    

    五、UILabel显示html标签(字体的颜色和大小)

    今天被这个问题问懵逼了,所以查查资料,学习下,经测试很好用。感谢sunboygpz的分享。
    可以使用富文本来实现, 代码如下:

    UILabel *label  = [[UILabel alloc] initWithFrame:CGRectMake(20, 100, 300, 200)];
    NSAttributedString *attributedString = [[NSAttributedString alloc] initWithData:[@"<font  style='font-size:20px;color:red'  >666666666666666</font> asdasd " dataUsingEncoding:NSUnicodeStringEncoding] options:@{ NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType } documentAttributes:nil error:nil];
        label.attributedText = attributedString;
        [self.view addSubview:label];
    

    六、解决UITextField设置为密文输入时,再次输入会清空原有内容问题

    在UITextField的代理方法中操作,实测好用,代码如下:

    // self.passwordTF为密码输入框
    -(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
        if (textField == self.passwordTF) {
            /// 解决密文输入时,再次输入清空问题
            NSString *updatedString = [textField.text stringByReplacingCharactersInRange:range withString:string];
            textField.text = updatedString;
            return NO;
        }
        return YES;
    }
    

    七、解决UIScrollView上添加UISlider时,滑动slider出现的问题

    在UIScrollView横向排了3个UIView,其中一个UIView中有UISlider。在左右滑动slider的时候,如果快速滑动slider不会动,scrollview会左右滑动。
    可以通过重写UIScrollView 的-(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event;方法解决这个问题,事例代码如下:

    /// 解决scrollView上滑动UISlider问题
    -(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event{
        UIView *result = [super hitTest:point withEvent:event];
        if ([result isKindOfClass:[UISlider class]]) {
            self.scrollEnabled = NO;
        }else {
            self.scrollEnabled = YES;
        }
        return result;
    }
    

    八、对URL中的中文进行转码

    事例代码
    NSString *url1 = [url stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
    

    九、关于存储下载文件路径问题

    最近项目中需要下载文件,保存到本地,然后把文件路径和一些信息存到数据库,再次读取的时候根据数据库中文件路径去获取文件,发现一个问题,就是iOS8以后苹果公司为了安全每次重启APP的时候,沙盒中唯一编码路径都会发生改变,所以如果直接存会出现获取不到文件的问题,解决办法很简单,就是存储地址的时候只存你放文件的地址(口拙,不知如何描述),不存沙盒地址,再次取地址的时候再重新吧沙盒地址拼接上。示例如下:

    // 存地址 filePath为文件路径 :/Users/hao/Library/Developer/CoreSimulator/Devices/7314558F-CF6E-486F-B83D-E39B3189C1E8/data/Containers/Data/Application/BD297778-550D-4888-B301-1ACC70C59BAA/Library/Caches/ListenFile/我害怕.mp3
    NSArray *pathArr = [filePath componentsSeparatedByString:@"/"];
    // 取后两位保存
    model.savePath = [NSString stringWithFormat:@"%@/%@",pathArr[pathArr.count-2],pathArr.lastObject];
    
    // 取地址
    NSString *path = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:"本地存储路径"];
    

    十、定时器的创建、暂停、继续、终止

    1、创建:简单的举一种,有很多种创建方式,可以自行百度。
    [NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(updatePlaybackProgress) userInfo:nil repeats:YES];
    2、暂停
    [self.progressUpdateTimer setFireDate:[NSDate distantFuture]];
    3、继续
    [self.progressUpdateTimer setFireDate:[NSDate date]];
    4、终止:
    [_progressUpdateTimer invalidate]; _progressUpdateTimer = nil;

    十一、Xib布局后代码修改约束的值

    具体请看Xib布局后代码修改约束的值

    十二、修改UITableView头视图的高度

    有些情况下需要更新头视图的内容,难免会改变高度,其实只要设置好头视图的frame,然后重新设置为头视图就可以,代码如下:

    [self.tableView beginUpdates];// 动画效果
    [self.tableView setTableHeaderView:self.headerView(头视图)];
    [self.tableView endUpdates];// 动画// 动画
    
    修改UITableView头视图的高度.gif

    十三、iOS中获取各种文件的目录路径的方法

    记录下 IOS中获取各种文件的目录路径的方法很不错。

    十四、外包公司的感受

    很累,貌似很充实,但是自己成长的太慢,每天都是重复的工作内容,简单无趣,再下去要废掉了,决定逃离。

    十五、音乐的后台播放、控制、信息的展示和处理中断事件

    1、打开后台设置
    TARGETS —> Capabilities —> Background Modes —> 勾选 Audio,AirPlay。。。这项。如图:

    后台设置.png
    2、AppDelegate中代码
    在方法-application:didFinishLaunchingWithOptions:中设置并激活音频会话类别,这样就可以在后台播放了。代码如下
    @interface AppDelegate ()
    /// 后台任务的UIBackgroundTaskIdentifier
    @property(assign,nonatomic)UIBackgroundTaskIdentifier bgTaskId;
    @end
    
    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
        // 设置并激活音频会话类别
        _bgTaskId=[AppDelegate backgroundPlayerID:_bgTaskId];
    return YES;
    }
    /// 设置并激活音频会话类别
    +(UIBackgroundTaskIdentifier)backgroundPlayerID:(UIBackgroundTaskIdentifier)backTaskId
    {
        //设置并激活音频会话类别
        NSError* error;
        [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:&error];
        [[AVAudioSession sharedInstance] setActive:YES error:&error];
        //允许应用程序接收远程控制
        [[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
        //设置后台任务ID
        UIBackgroundTaskIdentifier newTaskId=UIBackgroundTaskInvalid;
        newTaskId=[[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:nil];
        if(newTaskId!=UIBackgroundTaskInvalid&&backTaskId!=UIBackgroundTaskInvalid)
        {
            [[UIApplication sharedApplication] endBackgroundTask:backTaskId];
        }
        return newTaskId;
    }
    

    3、接收到远程控制事件
    在上一步中允许了应用程序接收远程控制[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];,接着实现-remoteControlReceivedWithEvent:方法。

    #pragma mark - 接收到远程控制事件
    -(void)remoteControlReceivedWithEvent:(UIEvent *)event {
        if(event.type==UIEventTypeRemoteControl){
           
            switch (event.subtype)
            {
                case UIEventSubtypeRemoteControlPause:
                    /// 暂停 (自行处理)
                    if ([VLCMusicManage defaultPlayer].currentPlaylistItem && [VLCMusicManage defaultPlayer].isPlaying) {
                        [[VLCMusicManage defaultPlayer] pause];
                    }
                    break;
                case UIEventSubtypeRemoteControlPlay:
                    /// 播放 (自行处理)
                    if ([VLCMusicManage defaultPlayer].currentPlaylistItem && ![VLCMusicManage defaultPlayer].isPlaying) {
                        [[VLCMusicManage defaultPlayer] pause];
                    }
                    break;
                case UIEventSubtypeRemoteControlNextTrack:
                    /// 下一曲 (自行处理)
                    if ([VLCMusicManage defaultPlayer].musicPlayList.count != 0) {
                        
                        [[VLCMusicManage defaultPlayer] playNextItem];
                    }
                    
                    break;
                case UIEventSubtypeRemoteControlPreviousTrack:
                    /// 上一曲 (自行处理)
                    if ([VLCMusicManage defaultPlayer].musicPlayList.count != 0) {
                        
                        [[VLCMusicManage defaultPlayer] playPreviousItem];
                    }
                    break;
                case UIEventSubtypeRemoteControlTogglePlayPause:
                    break;
                default:
                    break;
            }
        }
    }
    

    4、锁屏时,歌曲信息的展示 借鉴源,写的很清楚
    设置锁屏界面显示信息的原理是通过设置一个系统的字典,当音频开始播放时,系统会自动从这个字典中读取要显示的信息,如果需要动态显示,我们只需要不断更新这个字典即可。首先需要添加<MediaPlayer/MediaPlayer.h>这个头文件。

    NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
        //设置歌曲题目
        [dict setObject:@"题目" forKey:MPMediaItemPropertyTitle];
        //设置歌手名
        [dict setObject:@"歌手" forKey:MPMediaItemPropertyArtist];
        //设置专辑名
        [dict setObject:@"专辑" forKey:MPMediaItemPropertyAlbumTitle];
        //设置显示的图片
        UIImage *newImage = [UIImage imageNamed:@"43.png"];
        [dict setObject:[[MPMediaItemArtwork alloc] initWithImage:newImage] forKey:MPMediaItemPropertyArtwork];
        //设置歌曲时长
        [dict setObject:[NSNumber numberWithDouble:300] forKey:MPMediaItemPropertyPlaybackDuration];
        //设置已经播放时长
        [dict setObject:[NSNumber numberWithDouble:150] forKey:MPNowPlayingInfoPropertyElapsedPlaybackTime]; 
        //更新字典
        [[MPNowPlayingInfoCenter defaultCenter] setNowPlayingInfo:dict];
    

    5、处理中断事件
    我是在APPDelegate中处理的,代码如下:

      // 处理中断事件的通知
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleInterreption:) name:AVAudioSessionInterruptionNotification object:[AVAudioSession sharedInstance]];
    /// 实现方法
    //处理中断事件
    -(void)handleInterreption:(NSNotification *)sender
    {
        NSDictionary *info = sender.userInfo;
        AVAudioSessionInterruptionType type = (AVAudioSessionInterruptionType)[info[AVAudioSessionInterruptionTypeKey] unsignedIntegerValue];
        if (type == AVAudioSessionInterruptionTypeBegan) {
            //中断开始  自行处理暂停或者播放
            [[VLCMusicManage defaultPlayer] pause];
        }else{
            AVAudioSessionInterruptionOptions options = [info[AVAudioSessionInterruptionOptionKey] unsignedIntegerValue];
            if (options == AVAudioSessionInterruptionOptionShouldResume) {
                //中断恢复
                [[VLCMusicManage defaultPlayer] pause];
            }
        }
    }
    

    打完收工

    十六、关于webView加载html时,图片的自适应问题(2017.9.27修改)

    (旧,不懂web前端,看不太懂,但是今天用的时候发现在图片小于屏幕的时候,不起效果)
    #pragma mark - 修改html代码字符串,适应webview  
    - (NSString *)adaptWebViewForHtml:(NSString *) htmlStr  {  
            NSMutableString *headHtml = [[NSMutableString alloc] initWithCapacity:0];  
            [headHtml appendString : @"<html>" ];            
            [headHtml appendString : @"<head>" ];            
            [headHtml appendString : @"<meta charset=\"utf-8\">" ];          
            [headHtml appendString : @"<meta id=\"viewport\" name=\"viewport\" content=\"width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=false\" />" ];            
            [headHtml appendString : @"<meta name=\"apple-mobile-web-app-capable\" content=\"yes\" />" ];           
            [headHtml appendString : @"<meta name=\"apple-mobile-web-app-status-bar-style\" content=\"black\" />" ];            
            [headHtml appendString : @"<meta name=\"black\" name=\"apple-mobile-web-app-status-bar-style\" />" ];  
            [headHtml appendString : @"<style>img{width:100%;}</style>" ];  
            [headHtml appendString : @"<style>table{width:100%;}</style>" ];  
            [headHtml appendString : @"<title>webview</title>" ];  
            NSString *bodyHtml;  
            bodyHtml = [NSString stringWithString:headHtml];  
            bodyHtml = [bodyHtml stringByAppendingString:htmlStr];  
            return bodyHtml;  
    }  
    

    最新的 写在这里方便查找

    处理HTMLString的方法:
    NSString *htmls = [NSString stringWithFormat:@"<header><meta name='viewport' content='width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no'></header> <html> \n" "<head> \n" "</style> \n" "</head> \n" "<body>" "<script type='text/javascript'>" "window.onload = function(){\n" "var $img = document.getElementsByTagName('img');\n" "for(var p in $img){\n" " $img[p].style.width = '100%%';\n" "$img[p].style.height ='auto'\n" "}\n" "}" "</script>%@" "</body>" "</html>",htmlStr];
    
     [self.webView loadHTMLString:htmlString baseURL:nil];
    处理HTMLString的原理:
    原理就是用一个for循环,拿到所有的图片,对每个图片都处理一次,让图片的宽为100%,就是按照屏幕宽度自适应;让图片的高atuo,自动适应。
    

    十七、UINavigationBar透明渐变情况下,tableView分区区头停留在顶部。

    动图不太好看,实际效果还可以。


    gif5新文件.gif

    十八、 获取cell或者cell中的控件在屏幕中的位置

    借鉴下,原文地址
    主要使用方法:

    -(CGRect)convertRect:(CGRect)rect  toView:(UIView *)view;
    -(CGRect)convertRect:(CGRect)rect  fromView:(UIView *)view;
    

    这个两个方法的傻瓜式讲解
    1、获取cell在屏幕中的位置

    CGRect rectInTableView = [tableView rectForRowAtIndexPath:indexPath];//获取cell在tableView中的位置
    CGRect rectInSuperview = [tableView convertRect:rectInTableView toView:[tableView superview]];
    

    2、cell中的控件(比如按钮)在屏幕中的位置

    UIWindow* window = [UIApplication sharedApplication].keyWindow;
    CGRect rect1 = [sender convertRect:sender.frame fromView:self.contentView];//获取button在contentView的位置
    CGRect rect2 = [sender convertRect:rect1 toView:window];
    

    十九、 修改UINavigationController的子视图控制器数组viewControllers

    在开发过程中会有这种情况:从vc1push到vc2,再从vc2push到vc3,在vc3中想要直接返回vc1有很多种处理方法,但是在有系统侧滑手势时,侧滑返回就不好处理,这样就可以通过这种方法来修改。

    VC3 *vc3 = [VC3 new];
    [self.navigationController pushViewController:vc animated:YES];
    // 控制器跳转完成后,修改viewControllers,移除中间控制器
    NSMutableArray * controllers = [NSMutableArray arrayWithArray:self.navigationController.viewControllers];
    [controllers removeObjectsInRange:NSMakeRange(1, 1)];
    self.navigationController.viewControllers = controllers;
    

    大概就是这样,可以根据实际情况来修改,自测很好用。

    二十、NSDateFormatter转换时间各种格式总结

    年份
    1、yyyy 表示四位年份,例如2017;
    2、yy 表示年份的后两位,例如”2017“会显示“17”;
    月份
    1、MM 表示两位月份,例如:”十二月“显示为”12“、“4月”显示为“04”;
    2、M 在两位月份时,依旧为两位,但是对于一位的月份,则去除前面的0,只显示一位,例如:”十二月“显示为”12“、“4月”显示为“4”。同理,天、小时、分钟、秒一样。
    天
    1、dd 表示当前月份的哪一天;
    2、DD 表示是今年的第*天。
    上下午
    1、a 表示上下午。
    小时
    1、hh 表示12小时制;
    2、HH 表示24小时制。
    分钟
    1、mm 表示分钟。
    秒
    1、s 表示秒。
    星期
    1、EEEE 表示“星期几”;
    2、EEE 表示“周几”。
    

    二十一、使用NSUserdefaults存储数据容易出现Bug

    翻看以前的总结记录发现的这问题,复制过来
    NSUserDefaults 存储的对象全是不可变的,例如不能存储NSMutableArray,需要先转为不可变数组,否则会发生崩溃。

    二十二、iPhone X适配之状态栏和导航栏高度

    iPhone X的状态栏的长高了,这给我这个做外包的👨‍💻‍造成了致命的打击,前期写代码的时候,受培训的时候老师影响,死板的认为状态栏的高度就是20,一直是写死,现在前前后后写了十几个项目,基本都需要售后日常维护,这是一个惨痛教训,请大家引以为戒,下面留下获取状态栏高度的方法。

    /// 状态栏高度
    [[UIApplication sharedApplication] statusBarFrame].size.height
    /// navigationbar高度
    self.navigationController.navigationBar.frame.size.height
    /// 我写的高度宏
    /// 状态栏高度
    #define StatusBarHeight [[UIApplication sharedApplication] statusBarFrame].size.height
    /// 导航栏高度
    #define NavigationBarHeight self.navigationController.navigationBar.frame.size.height
    /// 状态栏+导航栏高度
    #define JWTopBarHeight ([[UIApplication sharedApplication] statusBarFrame].size.height+self.navigationController.navigationBar.frame.size.height)
    
    

    二十三、CocoaPods的基本操作

    记录下CocoaPods的一些基本操作,我脑子有坑,记不住,每次都要百度很烦。

    // 搜索三方
    pod search
    // 创建或打开Podfile文件
    vim Podfile
    // Podfile文件内容格式,'Test'为你的target的名字
    platform :ios,'8.0'
    target 'Test' do
    #      三方的名字  和     版本号  不填则安装最新的
    pod 'MJExtension', '~> 3.0.13'
    end
    // 添加新的三方,先修改Podfile文件,然后
    pod install
    // 跟新三方库
    pod update
    // 删除添加过的三方库,直接修改Podfile文件,删掉 “pod '需要删除三方'  ” 一行,然后 pod instal 或者 pod update
    
    

    二十四、UITableView刷新cell高度,且不重新加载cell

    方法很简单,只需要UITableView调用以下两个方法:

    - (void)beginUpdates;
    - (void)endUpdates;
    

    这两个方法是必须是成对出现的,调用后会UITableView的代理会重新走- (CGFloat)tableView:(UITableView*)tableView heightForRowAtIndexPath:(NSIndexPath*)indexPath;方法,加载cell高度,且不会走- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;方法。
    关于这两个方法,这里有介绍

    二十五、在 石家庄三秒软件科技有限公司 的感受

    在这我也努力过、拼搏过、奋斗过,但是看不到希望。
    1、重复的、机械式的工作让人颓废和反感,完全得不到技术上的成长;
    2、我不反感加班,我也愿意加班,但是强制加班、把上班时间的工作强行挪到下班时间,不参加就扣100,这就过分了;
    3、多次无故晚发工资,没有任何解释,问财务,财务说质量人员没有出绩效表,发不了;问质量,说上个月绩效没有核对出来,马上就出来了,在等一天,每次问都是这样,结果从15号等到了30号,我想问问你把员工当傻子吗?上个月的绩效,从月初就应该开始核对,我不知道公司的业务是多么复杂,需要一个月来核对,领导的解释是这是在李总考验员工,能不能经住金钱的考验,这样才能保证公司壮大了员工不会被金钱购买,心里有句***不知当讲不当讲,这或许是压倒骆驼的最后一根稻草;
    4、唯一让我留恋的就是有些领导,他们很好,很喜欢在他们手下干活。
    5、感谢公司让我成长,也非常抱歉不能和公司继续成长,江湖甚远,有缘再见。

    二十六、人走向前

    新公司入职以两周了,越发的感觉辞职的决定是明确的,感悟颇深。

    二十七、UIButton文字内容太长,修改省略号位置

    只需要修改button的titleLabel的lineBreakMode属性

     button.titleLabel.lineBreakMode =  NSLineBreakByTruncatingTail;
    

    二十八、UINavigationItem上的titleView位置问题

    先记录下,改天总结
    主要是translatesAutoresizingMaskIntoConstraints属性,

    // 不使用AutoLayout机制
    self.titleView.translatesAutoresizingMaskIntoConstraints = NO;
    

    二十九、关于Masonry

    这篇文章记录的很全,iOS自动布局框架-Masonry详解,学习下。

    三十、关于通讯录权限判断

    看到一篇文章很好,分析了应该使用那种方式。
    AddressBook权限的判断

    ABAuthorizationStatus authorizationStatus = ABAddressBookGetAuthorizationStatus();
    // 判断授权状态
    if (authorizationStatus == kABAuthorizationStatusNotDetermined) {
        // 首次访问通讯录
        // 请求授权
        ABAddressBookRef addressBookRef =  ABAddressBookCreate();
        __weak typeof(self) weakSelf = self;
        ABAddressBookRequestAccessWithCompletion(addressBookRef, ^(bool granted, CFErrorRef error) {
            if (granted) {
                    // 授权成功 获取通讯数据
            } else {
                    // 授权失败
            }
        });
    }else if (authorizationStatus == kABAuthorizationStatusDenied || authorizationStatus == kABAuthorizationStatusRestricted) {
        // 拒绝授权   或者  未授权,且用户无法更新,如家长控制情况下
    }else if (authorizationStatus == kABAuthorizationStatusAuthorized) {
        // 同意授权 获取通讯数据
    }
    

    三十一、UILAbel设置了attributedText后省略号不显示问题

    2018-04-27总结
    因为设置了attributedText后,UIlabellineBreakMode = NSLineBreakByTruncatingTail就会失效。参考如下:

    self.contentLabel.attributedText = attributedString;
    // 重新设置
    self.contentLabel.lineBreakMode = NSLineBreakByTruncatingTail;
    

    亲测有效,同理一些其他因为设置属性字符串导致的问题,也可以如此解决,例如文字居中等。

    三十二、iOS开发学习路线

    2018-05-15
    今天逛简书看到的,感觉很发人深省,记录下。

    三十三、用NSLayoutConstrain给控件做了约束以后,如何执行一定的UIView动画呢?

    2018-05-15 原文地址

    // 在修改了约束以后,只要执行下边的代码,就能做动画效果   
    [UIView animateWithDuration:2.0 animations:^{
         [修改了约束的View    layoutIfNeeded];   
    }];
    

    三十四、淡入淡出切换rootViewController

    原文地址 亲测有效,无脑搬运记载

    // 登陆后淡入淡出更换rootViewController
    - (void)restoreRootViewController:(UIViewController *)rootViewController { 
        typedef void (^Animation)(void); 
        UIWindow* window = [UIApplication sharedApplication].keyWindow; 
        rootViewController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve; 
        Animation animation = ^{ 
            BOOL oldState = [UIView areAnimationsEnabled];
            [UIView setAnimationsEnabled:NO]; 
            [UIApplication sharedApplication].keyWindow.rootViewController = rootViewController; 
            [UIView setAnimationsEnabled:oldState]; 
        }; 
        [UIView transitionWithView:window duration:0.5f options:UIViewAnimationOptionTransitionCrossDissolve animations:animation completion:nil]; 
    }
    

    未完待续。。。

    相关文章

      网友评论

        本文标题:iOS日常问题总结

        本文链接:https://www.haomeiwen.com/subject/lltrnttx.html