杂谈集

[NSOperationQueue mainQueue] //这个是主队列
[NSThread mainThread]; //这个是主线程

他俩是什么关系呢,确切的说队列和线程之间是什么关系呢??
好像有点傻傻分不清😂😂

首先
主线程和主队列都是多线程的一种方式,关于多线程苹果有三种实现方法:

    1. NSThread
  • 2.NSOperation/NSOperationQueue
  • 3.GCD

三种方式的抽象程度不同,越后面越容易使用,所以你可以理解为队列是对线程的一个包装,让用户更容易使用,所以队列的底层也是通过线程来实现的
至于主线程和主队列非要说有什么关系的话,根据我上面说的就很清楚了,主队列里的任务一定是在主线程中执行的,就这样而已.

异步和多线程的关系的理解##

异步和多线程并不是一个同等关系,异步是最终目的,多线程只是我们实现异步的一种手段。异步是当一个调用请求发送给被调用者,而调用者不用等待其结果的返回而可以做其它的事情。

  • 1.异步通信的意思是,当A发送完消息之后,不等待B的回应,继续执行之后的程序.在将来的某个时刻,A再来检查是否收到B的回应。
    异步就是彼此独立,在等待某事件的过程中继续做自己的事,不需要等待这一事件完成后再工作。

  • 2.多线程是程序设计的逻辑层概念,它是进程中并发运行的一段代码。多线程可以实现线程间的切换执行。

  • 3.异步和同步是相对的,同步就是顺序执行,执行完一个再执行下一个,需要等待、协调运行。线程就是实现异步的一个方式。异步是让调用方法的主线程不需要同步等待另一线程的完成,从而可以让主线程干其它的事情。

异步和多线程并不是一个同等关系,异步是最终目的,多线程只是我们实现异步的一种手段。异步是当一个调用请求发送给被调用者,而调用者不用等待其结果的返回而可以做其它的事情。实现异步可以采用多线程技术或则交给另外的进程来处理。


@import VS #import
在xcode 5 下,为了更易于开发,增加了modules和 auto-linking 这两个新特性。用 @import 来增加框架 到项目中比用 #import会更有效. 我们来看看为什么:

"Modules for system frameworks speed build time and provide an alternate means to import APIs from the SDK instead of using the C preprocessor. Modules provide many of the build-time improvements of precompiled headers with less maintenance or need for optimization. They are designed for easy adoption with little or no source changes. Beyond build-time improvements, modules provide a cleaner API model that enables many great features in the tools, such as Auto Linking."

Modules and auto-linking 默认情况下是enabled的。 如果是旧的项目,你可以通过设置"Language - Modules." 来设置Enable Modules 和Link Frameworks Automatically 为Yes。

另外一个使用moudules的好处是你再也不用去链接你的framework到你的项目了。例如,在以前,如果你要使用MapKit这个框架,你要这样做:

  • 使用语句 #import <MapKit/MapKit.h> 导入框架
  • 去到项目的build phases 设置项,找到MapKit.framework.并加入到Link Binary With Libraries里面。

如果使用modules的话,只需要加入语句 "@import MapKit;" 你就可以开始使用了,根本不需要链接到你的项目。
详细解答

C 指针复习
&x是对x变量取地址,也就是返回的是x的地址。
int i;这里面的说明变量i是一个指针,存的是一个地址。
而printf("%d\n",i);这里面的的作用是返回指针i所指的变量。

&是取地址符号,既取得某一个变量的地址;如:&a,而 * 是指针运算符(乘号就不说了),可以表示一个变量是指针类型;也可以表示一个指针变量的所指向的存储单元,可以获取某个地址存储的值。
*p就是p所指对象的数值

**1、const **

const :被const修饰符修饰过的变量,真个变量就会变成一个常量。他的值在代码其他部分不能再修改,这对于函数调用时候,防止错误的修改原本不应修改的变量起到很大作用

const char *pchar const *pchar * const p 三者共同点是定义了一个char类型 p指针
const char *pchar const *p效果一样,都是不允许修改指针指向的地址空间的值,即把值作为常量
char * const p则是不允许修改指针自身,不能再指向其他地方,把指针自己当作常量使用,需要注意的是,使用char * const p定一个常量指针的时候一定记得赋初始值,否则再其他地方就没法赋值了

  • *前const 值为常量 (const了*p),
  • *后const 指针为常量 (const 了 p)

2.== 和 = 纠结

BOOL start = status == noErr; //noErr = 0

==是判等运算符,优先级高于 = 赋值运算符,上面表达式先判等再赋值

沙盒文件夹

    //Documents, 文档文件夹, 存放重要的文件(用户的配置信息, 存档等), 并且手机连电脑同步时, 会同步此文件夹;文件夹中存的文件夹体积不能过大
    NSString *documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
    NSLog(@"%@", documentsPath);
    //YES打印:  /Users/laouhn/Library/Developer/CoreSimulator/Devices/97C763A0-424B-4002-8BBF-9D3FD189CFB0/data/Containers/Data/Application/1AF468D6-6A64-49AB-9F84-CD23885CBEDB/Documents
    //NO打印:  ~/Documents

    
    //Library, 资源文件夹, 存放资源文件(图片, 音频, ship)
    NSString *libraryPath = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) firstObject];
    NSLog(@"%@", libraryPath);

    
    //tmp, 临时文件, 存过度文件(压缩包)
    NSLog(@"%@", NSTemporaryDirectory());

    
    //*.app, 应用程序包(文件夹), 存放编译过后的文件(可执行文件, nib)和工程资源, 这个文件夹是只读文件夹
    NSLog(@"%@", [[NSBundle mainBundle] bundlePath]);

3.应用间的跳转
跳转App Store下载应用/更新应用
id444934666为QQ的应用id,换成自己的就行

[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"itms-apps://itunes.apple.com/app/id444934666"]];

跳转到App Store评分

[[UIApplication sharedApplication]openURL:[NSURL URLWithString:@"http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewContentsUserReviews?id=APPID&pageNumber=0&sortOrdering=2&type=Purple+Software&mt=8"]];

跳转到手机的设置界面
亲测iOS 11可以跳转到当前APP的授权界面,比链接介绍的方法更好使,但是更改权限后APP会重启,这个是系统行为,能接受就用

NSURL *url = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
if ([[UIApplication sharedApplication] canOpenURL:url]) {
    [[UIApplication sharedApplication] openURL:url];
}
# 但是控制台一直会打印
# Application tried to push a nil view controller on target <UINavigationController: 0x13751e4d0>.

4.cell原生分割线 不在底部
场景:在tableView初始化的时候设置了setSeparatorInset:UIEdgeInsetsZero,重写了cell 的layoutSubViews方法

# 检查发现 漏掉了 
[super layoutSubviews];

5.cell原生分割线 不能从头开始
场景:在tableView初始化的时候设置了setSeparatorInset:UIEdgeInsetsZero,发现用系统的cell 可以从头开始,自定义的cell不能。最终在tableView所属的控制器里面,如下操作才得以解决。

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath{
   if ([cell respondsToSelector:@selector(setSeparatorInset:)]) {
       [self.myTable setSeparatorInset:UIEdgeInsetsMake(0, 0, 0, 0)]; 
   }
   if ([cell respondsToSelector:@selector(setLayoutMargins:)]) { 
       [cell setLayoutMargins:UIEdgeInsetsZero];
   }
}
# 作用貌似不大,可有可无
- (void)viewDidLayoutSubviews{
    [super viewDidLayoutSubviews];
    
    if ([self.myTable respondsToSelector:@selector(setSeparatorInset:)]) {
        [self.myTable setSeparatorInset:UIEdgeInsetsMake(0, 10, 0, 10)];
    } if ([self.myTable respondsToSelector:@selector(setLayoutMargins:)]) {
        [self.myTable setLayoutMargins:UIEdgeInsetsZero];
    }
}

6.去掉系统返回按钮标题

#要写在 push 之前
UIBarButtonItem *back = [[UIBarButtonItem alloc] init];
back.title = @"";
self.navigationItem.backBarButtonItem = back;

7. iOS9 提醒框

    UIAlertController *alertCon = [UIAlertController alertControllerWithTitle:@"重要提示" message:@"删除将无法恢复" preferredStyle:UIAlertControllerStyleAlert];
    
    UIAlertAction *cancleAction = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDestructive handler:^(UIAlertAction * _Nonnull action) {
        NSLog(@"点击确定");
    }];
    
    UIAlertAction *otherAction = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        NSLog(@"点击取消");
    }];
    
    [alertCon addAction:cancleAction];
    [alertCon addAction:otherAction];
    
    [self presentViewController:alertCon animated:YES completion:nil];
普通标题

改变 UIAlertController 标题颜色

    NSString *title = @"重要提示❗️";
    //改变 UIAlertController 标题颜色
    NSMutableAttributedString *str = [[NSMutableAttributedString alloc]initWithString:title];
    [str addAttribute:NSForegroundColorAttributeName value:[UIColor colorwithHexString:@"#00A0E9"] range:NSMakeRange(0, 6)];
    NSString *message = [NSString stringWithFormat:@"删除之后不可恢复\n哈哈哈"];
    NSString *cancelButtonTitle = NSLocalizedString(@"确定", nil);
    NSString *otherButtonTitle = NSLocalizedString(@"取消", nil);
    
    UIAlertController *alertController = [UIAlertController alertControllerWithTitle:title message:message preferredStyle:UIAlertControllerStyleAlert];
    //改变 UIAlertController 按钮颜色
    ##整个应用层级修改,即修改了整个应用的渲染色,一定要用的话,结束时要改回原来的值
    [UIView appearance].tintColor = [UIColor colorwithHexString:@"#00A0E9"];
    //点击事件
    UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:cancelButtonTitle style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {
        NSLog(@"234");
    }];
    
    UIAlertAction *otherAction = [UIAlertAction actionWithTitle:otherButtonTitle style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
        
    }];
    
    [alertController setValue:str forKey:@"attributedTitle"];
    
    // Add the actions.
    [alertController addAction:cancelAction];
    [alertController addAction:otherAction];
    
    [self presentViewController:alertController animated:YES completion:nil];
蓝色标题

8.删除storyBoard 的正确姿势
一般情况下,我们有时候不想用storyboard,但是直接删除的话,Xcode就会报错。那我今天就来讲一下,正确删除storyboard的方法。

  • 第一步,直接将工程中的storyboard直接删除掉,这样你觉得就OK了?你错了,我们还需要第二步。

  • 第二步,找到plist文件,将plist文件中的Main storyboard file base name删除掉,OK

9. _ _ block 使用

BOOL result;
UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:cancelButtonTitle style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {
            result = YES;
    }];

error:Variable is not Assignable (missing _block type specifier)
修改为下面

__block BOOL result;
UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:cancelButtonTitle style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {
            result = YES;
    }];

10.layoutSubviews何时调用
layoutSubviews在以下情况下会被调用:

  • 1、init初始化不会触发layoutSubviews
  • 2、addSubview会触发layoutSubviews
  • 3、设置view的Frame会触发layoutSubviews,当然前提是frame的值设置前后发生了变化
  • 4、滚动一个UIScrollView会触发layoutSubviews
  • 5、旋转Screen会触发父UIView上的layoutSubviews事件
  • 6、改变一个UIView大小的时候也会触发父UIView上的layoutSubviews事件
    11.UILabel 加载HTML文本
NSString * htmlString = @"<html><body> Some html string \n <font size=\"13\" color=\"red\">This is some text!</font> </body></html>";  
NSAttributedString * attrStr = [[NSAttributedString alloc] initWithData:[htmlString dataUsingEncoding:NSUnicodeStringEncoding] options:@{ NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType } documentAttributes:nil error:nil];  
UILabel * myLabel = [[UILabel alloc] initWithFrame:self.view.bounds];  
myLabel.attributedText = attrStr;  
[self.view addSubview:myLabel];  

第二中,还能显示图片


dataDic = @{@"content":@"<p>他在海外留学八年,回国后只等着接手亿万资产的家族企业,但他却天天开着跑车游手好闲;他决定自力更生,却在社会上屡屡受挫;2010年,他赌气走进大山,睡起草窝;搬进山里后,曾经在朋友面前很有钱的彭然,硬着头皮找朋友借钱;别人的挖苦,成了他前进的动力。80后的彭然,如何让人刮目相看,一年后实现年营业额三百万元?<br/>\r\n\t </p><p>\r\n\t 致富经养殖视频同步解说词:</p><p>\r\n\t这个正在抓鸡的人叫彭然。这里是重庆铜梁县最大的规模养鸡场。凌晨四点抓鸡,早上七点左右,这里的土鸡就会被销往整个铜梁县城和重庆市场。彭然的这家鸡场,一年的营业额达三百万元。而这些,他仅用了一年多就做到了。</p><p>\r\n\t记者:弄得满脸都是泥啊。</p><p>\r\n\t彭然:是,全部都是泥。</p><p>\r\n\t记者:手上也是。</p><p>\r\n\t彭然:对。晚上的时候,鸡是站着不动的,这样抓就好抓。白天到处跑,根本抓不了。</p><p>\r\n\t这个抓起鸡来已经驾轻就熟的年轻人,谁也想不到,他还有另外一个身份。</p><p>\r\n\t朋友朱坤:所谓的富二代,公子哥。</p><p>\r\n\t员工赵晓兰:我还一直都在想这个问题,为什么他妈要他做这个辛苦的活,不相信他家里面有钱。</p><p>\r\n\t彭然是重庆人,家境殷实,资产过亿,在澳大利亚留学八年。养鸡之前,彭然天天过着游手好闲的生活。</p><p>\r\n\t朋友朱坤:玩游戏啊,唱歌啊,酒吧,反正天天这么玩。</p><p>\r\n\t朋友陈毅平:觉得他更像一个小孩,喜欢花时间在游戏上面。</p><p>\r\n\t朋友朱坤:吊儿郎当的,经常比如说做这个事情做做,做到一半,没什么兴趣了,就不做了。</p><p>\r\n\t家里那么有钱,彭然为什么要跑到山里去吃苦,而且还干了养鸡的行当?而更让人觉得蹊跷的是,家里有钱的彭然本应该不为钱愁,可彭然有段时间却只能靠借钱度日,为了二十万元愁得夜不能寐。</p><p>\r\n\t彭然:哪怕我就不要面子,不要脸,也会找朋友借。</p><p>\r\n\t朋友朱坤:第一次,我们认识十几年来第一次向我借钱。</p><p>\r\n\t彭然:就算朋友们怎么说我,怎么挖苦我,先借钱给我再说吧。</p><p>\r\n\t彭然,父母家里资产过亿元,为何还要向朋友借钱?他一个对养鸡一窍不通的门外汉,为什么要跑到山里来吃苦养鸡?而从没做过生意的他,一年后,却硬是靠着自己,实现了年营业额三百万元。</p><p>\r\n\t<img src=\"http://www.nczfj.com/UploadFiles/2012-06/admin/2012689160711.jpg\"/>彭然父母在青海有家大型化工企业,家境殷实。由于父母忙于经营管理,彭然从小学三年级开始就一直上着寄宿学校,17岁时又只身去了澳大利亚留学,一待就是八年,2008年才回到中国。</p><p>\r\n\t母亲张俊秀:在国外那么多年,始终觉得跟我们在一起时间很少,总觉得还是有点亏欠他,我就给他买了一个奥迪TT,每个月给他五千块的工资,经常说,彭然,需不需要钱?</p><p>\r\n\t每月父母经常给的零用钱少则几千,多则上万,彭然的吃穿用度也都由父母的公司实报实销。然而,按照惯例理应接手家族企业的他,却让人大跌眼镜,天天开着跑车,过着游手好闲的生活。</p><p>\r\n\t同学李兴懿:时间完全是颠倒的,白天睡觉,晚上就是耍耍游戏,打牌,反正基本上都是通宵通宵地那种耍。</p><p>\r\n\t母亲张俊秀:我说,我其实很了解你,你是不觉得很空虚?</p><p>\r\n\t彭然:父母就说,你回来又不愿意找工作,那就上班,去自己公司上班。</p><p>\r\n\t彭然确实闲得很空虚,如果去公司上班,时间会过得快一些,还能应付父母,他便欣然同意。但是,朝九晚五的公司规定,对他而言却是一纸空文。</p><p>\r\n\t母亲张俊秀:十点多钟十一点了,有时候穿个睡衣。有时候我都要说他,我说,你还是每天到公司来看一下子。我说,你当个副总,哪个说你不得。</p><p>\r\n\t做母亲的虽然有些看不惯,但张俊秀总觉得亏欠儿子太多。可彭然并不理解父母的心意,除了白天偶尔去下公司,夜生活照常不误。这种生活方式,时间久了,在母亲张俊秀眼里变得格格不入。一天晚上,彭然很晚还没回家,张俊秀忍无可忍便打电话给彭然。</p><p>\r\n\t母亲张俊秀:我说,你出国也有七八年,我也花了起码一百多万。我说,早知道你这样,我一百多万养你吃一辈子你就够了。</p><p>\r\n\t彭然:一听感觉还是挺烦的,我就不做了吧,本来就不喜欢做。</p><p>\r\n\t彭然的回答,让张俊秀火冒三丈。</p><p>\r\n\t母亲张俊秀:你有本事自己养活自己,你不要依靠我。</p><p>\r\n\t彭然:我妈一下就火了,那行,你明天就别来上班了,你的工资全部给你停了。</p><p>\r\n\t母子俩的关系一下子变得僵硬起来,张俊秀痛下决心,果断地停掉了彭然所有的收入。母亲的做法,给了彭然极大的刺激。</p><p>\r\n\t彭然:你想,没钱了怎么办?什么东西都没了。我这个人的性格就是比较不愿意低头。</p><p>\r\n\t母亲把自己说得像寄生虫一般,彭然很不服气,他把这句话记到了心里,赌气要自力更生。</p><p><br/></p>",
                         @"title":@"如何让人刮目相看,一年后实现年营业额三百万元?",
                         @"imgUrl":@"http://36.111.32.33:10038/WebServer/images/67128531_3.jpg",
                         @"date":@"2016-12-09"};

//detailLab
UILabel *detailLab =[UILabel alloc] initWithFrame:CGRectMake(10, NH(imgView)+AutoWHGetHeight(15), width, 10) ]
detailLab.text = dataDic[@"content"];

//    NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:detailLab.text];
NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithData:[detailLab.text dataUsingEncoding:NSUnicodeStringEncoding] options:@{ NSDocumentTypeDocumentAttribute:NSHTMLTextDocumentType} documentAttributes:nil error:nil];

NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];

[paragraphStyle setLineSpacing:10];//调整行间距

//    [attributedString addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:NSMakeRange(0, [detailLab.text length])];
[attributedString addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:NSMakeRange(0, [attributedString length])];
[attributedString addAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize:kSize16]} range:NSMakeRange(0, [attributedString length])];

detailLab.attributedText = attributedString;
[scrollView addSubview:detailLab];
[detailLab sizeToFit];

scrollView.contentSize = CGSizeMake(SCREEN_WIDTH, NH(detailLab)+30);
[self.view addSubview:scrollView];

12. “Discarding message for event 0 because of too many unprocessed messages” mean?
google翻译:
这是苹果技术支持说的这个(在支付49美元的开发人员技术支持事件后):

这些消息来自核心位置框架。 这些消息的最可能的原因是没有运行循环在创建CLLocationManager的线程上运行。 (这意味着CLLocationManager不是在主线程上创建的)。被丢弃的消息是位置消息:事件0是位置,事件24是例如授权状态更新。 因为消息被丢弃,所以您将看不到调用适当的委托回调。 你设置了地理围栏或其他回调,并且不能很快为其服务吗? 在开始转储事件和记录此消息之前,队列限制显示为10。 此信息尚未公开记录。 我正在与核心位置小组一起改进报告的消息,并看看这是否可以更好地记录。

[[CLLocationManager alloc] init] 没有放在主线程

13.图片压缩处理

14.iOS Security

15. sizeThatFits:

    // 1154x434 pixels QQ20170110@2x.png
UIImageView *imgView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"QQ20170110"]];
    imgView.contentMode = UIViewContentModeScaleToFill; //默认显示模式
    imgView.frame = CGRectMake(0, 0, 300, 100);
    [self.view addSubview:imgView];
    
    CGSize size = [imgView sizeThatFits:CGSizeZero];
    imgView.backgroundColor = [UIColor cyanColor];
    NSLog(@"%@ -- %@", NSStringFromCGRect(imgView.frame), NSStringFromCGSize(size));

## --
计算的image大小为(1154x433) / 2 = 577x217

16.添加新的SDK工具包
找到路径 Finder -> 应用程序 -> 右键Xcode7.3 -> 显示包内容 -> Contents -> Developer -> Platforms -> iPhoneOS.platform -> DeviceSupport
17.AFN+cache
http://www.cnblogs.com/HJQ2016/p/5968327.html
http://code4app.com/thread-10071-1-1.html
http://www.jianshu.com/p/c695d20d95cb
https://github.com/sky00/SY8APP
https://github.com/yuantiku/YTKNetwork
18.边缘侧滑返回上一级失效

    UIBarButtonItem *backItem = [[UIBarButtonItem alloc] initWithTitle:@"返回" style:(UIBarButtonItemStyleDone) target:self action:@selector(backIfNeedSave)];
    self.navigationItem.leftBarButtonItem = backItem;

上面操作导致左侧边缘侧滑失效
18.TexrField.rightView
推测clearButton也是一个rightView,一旦设置了自定义的,再设置clearButton就不会显示,可以尝试 rightViewRectForBounds: 设置偏移,被遮盖的那个显露出来(未验证)

    _textField.rightViewMode = UITextFieldViewModeAlways;
    _textField.rightView = [UIView new];
    _textField.clearButtonMode = UITextFieldViewModeAlways;

19. coreDate实体属性类型 Integer16,32,64

  • Undefined: 默认值,参与编译会报错
  • Integer 16: 整数,表示范围 -32768 ~ 32767
  • Integer 32: 整数,表示范围 -2147483648 ~ 2147483647
  • Integer 64: 整数,表示范围 –9223372036854775808 ~ 9223372036854775807
  • Float: 小数,通过MAXFLOAT宏定义来看,最大值用科学计数法表示是 0x1.fffffep+127f
  • Double: 小数,小数位比Float更精确,表示范围更大
  • String: 字符串,用NSString表示
  • Boolean: 布尔值,用NSNumber表示
  • Date: 时间,用NSDate表示
  • Binary Data: 二进制,用NSData表示
  • Transformable: OC对象,用id表示。可以在创建托管对象类文件后,手动改为对应的OC类名。使用的前提是,这个OC对象必须遵守并实现NSCoding协议

在创建时间戳属性时,不放心测试如下

NSDate *date = [NSDate date];
NSTimeInterval interval = [[NSDate date] timeIntervalSince1970];
NSDate *date1970 = [NSDate dateWithTimeIntervalSince1970:2147483647];
# log:
dateNow:2017-12-09 03:49:59 +0000
1970Stamp:1512791399.194478
1970date:2038-01-19 03:14:07 +0000

Integer32 用到2038年就要溢出了,App能再活19年吗

20. 字符串过滤

NSString *string = @" \n sf fds  sdfs . .\n ";
    NSLog(@"0.=%@", string);
    NSLog(@"1.=%@", [string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]);
    NSLog(@"2.=%@", [string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]);
   NSLog(@"3.=%@", [self removeSpaceAndNewline:string]);


#log:
0.= _
 sf fds  sdfs . .
1.=
 sf fds  sdfs . .
2.=sf fds  sdfs . .
3.=sf fds  sdfs . .

图片裁剪
图片裁剪用到了core graphics框架 ,此框架下的图像处理坐标系是原点位于左下角,Y轴向上。由于和UIKit坐标系不一样,裁剪时需要考虑进去,并做相应的转换。

- (UIImage *)cropImage:(UIImage*)image toRect:(CGRect)rect {
    CGFloat (^rad)(CGFloat) = ^CGFloat(CGFloat deg) {
        return deg / 180.0f * (CGFloat) M_PI;
    };
    
    // determine the orientation of the image and apply a transformation to the crop rectangle to shift it to the correct position
    CGAffineTransform rectTransform;
    switch (image.imageOrientation) {
        case UIImageOrientationLeft:
            rectTransform = CGAffineTransformTranslate(CGAffineTransformMakeRotation(rad(90)), 0, -image.size.height);
            break;
        case UIImageOrientationRight:
            rectTransform = CGAffineTransformTranslate(CGAffineTransformMakeRotation(rad(-90)), -image.size.width, 0);
            break;
        case UIImageOrientationDown:
            rectTransform = CGAffineTransformTranslate(CGAffineTransformMakeRotation(rad(-180)), -image.size.width, -image.size.height);
            break;
        default:
            rectTransform = CGAffineTransformIdentity;
    };
    
    // adjust the transformation scale based on the image scale
    rectTransform = CGAffineTransformScale(rectTransform, image.scale, image.scale);
    
    // apply the transformation to the rect to create a new, shifted rect
    CGRect transformedCropSquare = CGRectApplyAffineTransform(rect, rectTransform);
    // use the rect to crop the image
    CGImageRef imageRef = CGImageCreateWithImageInRect(image.CGImage, transformedCropSquare);
    // create a new UIImage and set the scale and orientation appropriately
    UIImage *result = [UIImage imageWithCGImage:imageRef scale:image.scale orientation:image.imageOrientation];
    // memory cleanup
    CGImageRelease(imageRef);
    
    return result;
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 201,468评论 5 473
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,620评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 148,427评论 0 334
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,160评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,197评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,334评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,775评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,444评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,628评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,459评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,508评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,210评论 3 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,767评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,850评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,076评论 1 258
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,627评论 2 348
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,196评论 2 341

推荐阅读更多精彩内容

  • iOS面试小贴士 ———————————————回答好下面的足够了------------------------...
    不言不爱阅读 1,955评论 0 7
  • 史上最全的iOS面试题及答案 iOS面试小贴士———————————————回答好下面的足够了----------...
    Style_伟阅读 2,341评论 0 35
  • __block和__weak修饰符的区别其实是挺明显的:1.__block不管是ARC还是MRC模式下都可以使用,...
    LZM轮回阅读 3,277评论 0 6
  • ———————————————回答好下面的足够了---------------------------------...
    恒爱DE问候阅读 1,706评论 0 4
  • 傍晚在厨房做饭,听到开门的声音,知道姐姐回来了。还没听到关门声,就听姐姐咆哮“李响 你给我放下来”。紧接着弟...
    做自己命运的主宰阅读 411评论 0 0