iOS开发200个tips总结(二)

工作了两年多,一直有个“坏习惯”,就是将工作中遇到的一些问题、技巧或心得记在印象笔记里面,按理来说,作为一个开发者,要拥抱开源精神,将这些美好的东西分享给大家,或许能够帮助别人解决问题或是引起少许的共鸣。

简书给我的第一印象是:风格清新,易用,同时也*是一个不错的交流技术,*交流心得的好平台,趁最近在找工作的空档,抽些时间将印象笔记里面的tips、轮子或技术解决方案移到这里来。

翻了一下印象笔记的笔记本,咋一看吓一跳,将近一千条笔记!!! 根据80 20 法则,怎么也有200条对一部分人是有参考意义的。这里抽取200条比较有价值的笔记分享出来,希望看完博客的看官能够有所收获。

PS:因为有些tips是在一个swift项目中收集下来的,所以下面放出的tip既有Objective-C 也有 Swift。由于有些笔记记录的是iOS 6.0时代的一些问题,因此可能存在一些错误的地方,欢迎指正。

tip 74 : UITextField leftView & rightView占位

UITextField *testField = [[UITextField  alloc] initWithFrame:CGRectMake(20, 100, 180, 30)];    testField.borderStyle = UITextBorderStyleRoundedRect;

//开启左边视图出现模式    testField.leftViewMode = UITextFieldViewModeAlways;

UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 40, 30)];    UIImage *image = [UIImage imageNamed:@"userName.png"];    imageView.image = image;

//设置TextField左边视图    testField.leftView = imageView;   

[self.view addSubview:testField];

rightView同理


tip 75 : Xcode 中输出你想要打印的信息的命令

在Xcode 打断点debug时控制台中输出面板中:

输入:

po NSHomeDirectory()  // 演示输出目录,您也可以试一试: po @“大家好”

输出:

/Users/qianfeng/Library/Application Support/iPhone Simulator/7.0/Applications/8E889658-4D95-4499-9708-AA76D056623A


tip 76 : label设置字距

UILabel*label = [[UILabel alloc] initWithFrame:CGRectMake(0,250,750,50)];

label.backgroundColor= [UIColor greenColor];

label.font= [UIFontfontWithName:@"AppleSDGothicNeo-UltraLight"size:50];

NSAttributedString*attributedString =[[NSAttributedString alloc] initWithString:@"中国xx11"attributes:@{NSForegroundColorAttributeName: [UIColorwhiteColor] ,NSKernAttributeName:@(-8.0f)}];

[label setAttributedText:attributedString];

[self.view addSubview:label];


tip 77 : 发布上传 Error ITMS-90046


解决办法:

1.前往https://developer.apple.com/account/ios/identifiers/bundle/bundleList.action

2.将Associated Moains 取消  

以下是测试应用的设置页面

3.重新制作证书,更新Xcode里面的证书配置

4.重新打包上传


tip 78 : layer的绘图是怎么执行的?

每个UIView内部都有一个Layer的属性

要具体使用CALayer,需要引入

CALayer中使用CGColorRef和CGImageRef的数据类型,而不用UIColor和UIImage

所有的非Root Layer都存在着隐式动画

创建一个CALayer的子类,然后覆盖drawInContext:方法,可以使用Quartz2D API在其中进行绘图

在实现核心动画时,本质上是将CALayer中的内容转换成位图,从而便于图形硬件的操纵


tip 79 :编译报错: CodeSign error: no provisioning profile at path '/Users/hz/Library/MobileDevice/Provisioning Pro

解决步骤:

1.找到文件包(先关闭项目)

2.右键显示包内容

3.复制provisioning码

4.用文本编辑器打开project.pbxproj

5.搜索码(有两个)

6.删除搜到的两个码

7.重新打开工程编译


tip 80 : Swift 引入的组件名称带 “+” 

如:组件名有+号: UITableView+FDTemplateLayoutCell

引入时:import UITableView_FDTemplateLayoutCell

将“+”好改为“_” 即可


tip 81 : Swift操作加锁

let str ="a"

func operation(a:String){

     objc_sync_enter(a)   // 没有objc_asyn_xxxx

    print("做一些操作,在这个操作的过程中,a保持不被修改")

    objc_sync_exit(a)

}

// 封装

Lock.swift

func lock(object:AnyObject, callBack:()->()){

    print("开始执行,加锁!")

    objc_sync_enter(object)

    print("执行中...")

    callBack()

   objc_sync_exit(object)

   print("执行完毕,解锁")

}

//实例:

// let object = "aaa"

// lock(object) { () -> () in

//     print("锁住\(object)")

// }


tip 82 : Swift defer 函数完全退出时执行(常用于销毁数据)

func resizeImage(url:NSURL) ->UIImage?{

let dataSize:Int=1234

//分配内存

let desData =UnsafeMutablePointer.alloc(dataSize)

//释放内存程序执行完

    defer{  // 函数执行完毕才会调用

         desData.dealloc(dataSize)

    }

    returnnil

}



tip 83 :  Swift 必须是可选值的情况&不能是可选值的情况

可选:

weak修饰的是可选值

值绑定一定是可选值

聚合运算一定是可选值

不可选:

unowned修饰的不能是可选值


tip 84 :  Swift 集合类型方法 map、 flatMap、filter

map: 得到一个由闭包里面返回值组成的新序列

flatMap:与map类似,但会过滤掉返回值里面为nil值

filter:得到一个闭包返回值为true的值组成的新序列

var arr = [1,2,3,4,5]

//用法:返回序列里面对遍历的每一个元素操作的结果序列

//结果: [2, 4, 6, 8, 10]

let result = arr.map{ $0 *2}

print(result)

//用法:在工程目录下添加两种图片命名为1.png/3.png

//结果:将获取到的nil的值过滤掉,返回[xxx/1.png, yyy/3.png]

let result1 = arr.flatMap{NSBundle.mainBundle().pathForResource("\($0)", ofType:"png")}

print(result1)

//用法:对序列里面的每个元素进行判断返回满足bool值的元素

//结果: [3, 4, 5]

let result2 = arr.filter({ $0 >2})

print(result2)


tip 85 :  Swift Any & AnyObject

Any : class、struct、enum

AnyObject: class ,因为所有的类都实现了AnyObject的协议方法,Object-C中的id = AnyObject?


tip 86 : swift static & class 怎么选?

static, class 可以用来修饰计算属性和方法

适用static : enum, struct

适用class: Class, protocol


tip 87 : swift条件编译

let btn =UIButton(type:.Custom)

btn.frame=CGRect(x:100, y:100, width:100, height:100)

self.view.addSubview(btn)

//真机x86_64、arm64

//模拟器arm、i386

#if arch(arm64)// os(OSX或iOS)

btn.backgroundColor=UIColor.greenColor()

#elseif arch(i386)

btn.backgroundColor = UIColor.redColor()

#endif


tip 88 : Swift mark 方式

// MARK:非必须 

 // TODO:必须 

 // FIXME:必须


tip 89 : Swift 类名实例化一个对象

if let Class = NSClassFromString("AYIModel").self{

       if let BaseModel = Class as? NSObject.Type{

             let model = BaseModel.init()

             print(model)

       }

}


tip 90 : 怎么个相等法?

swift == 与 === 的区别

== : 值相等

=== : 完全相等


tip 91 :  NS 与 CF互转

OC :

NSURL*fileURL = [NSURL URLWithString:@"SomeURL"];

SystemSoundID theSoundID;

//OSStatus AudioServicesCreateSystemSoundID(CFURLRef inFileURL,

//                             SystemSoundID *outSystemSoundID);

OSStatus error = AudioServicesCreateSystemSoundID(

(__bridgeCFURLRef)fileURL,

&theSoundID);

swift:

import AudioToolboxletfileURL = NSURL(string:"SomeURL")

var theSoundID: SystemSoundID =0

//AudioServicesCreateSystemSoundID(inFileURL: CFURL,

//        _ outSystemSoundID: UnsafeMutablePointer) -> OSStatus

AudioServicesCreateSystemSoundID(fileURL!, &theSoundID)


tip 92 :  pod install 还是 pod update ? (转)

一个哥们的文章:

详情请看:http://www.jianshu.com/p/a977c0a03bf4


tip 93 : 播放本地 m3u8流媒体

请移步CSDN :  http://blog.csdn.net/u010309384/article/details/49763419


tip 94 :  Masonry 三个Block函数理解

三种Block函数

//  (1).对view ( tag == 100)第一次约束使用该方法

- (NSArray *)mas_makeConstraints:(void(^)(MASConstraintMaker *make))block;

//(2).第二次对view(tag == 100)进行约束的时候不能再用方法一,否则会报错,要对之前添加的约束更,改的时候使用下面的方法。

特别注意,这个update是修改约束条件的值,不能修改约束对象。比如之前左边是与view1有一个约束,现在将左边修改为与view2约束,这样会报错。

- (NSArray *)mas_updateConstraints:(void(^)(MASConstraintMaker *make))block;

//(3).如果想重新对view(tag == 100)约束,但是又不想用方法二,可以用下面的方法

- (NSArray *)mas_remakeConstraints:(void(^)(MASConstraintMaker *make))block;


tip 95 : 破解Reveal 亲测可用

Reveal一个UI审查工具,配合SB 非常好用

破解教程:

http://www.jianshu.com/p/0cc7089143a3

reveal 一篇不错的介绍博客:

http://blog.sina.com.cn/s/blog_adb19b690102vk8m.html


tip 96 : 源码安装 使用makefile

下载 linux 工具源码放到指定目录

第一步: cd 到源码当前目录

第二步: $ configure

第三步: $ make

第四步: $ sudo make install

完毕!


tip 97 : iOS 监听电话状态

#import <CoreTelephony/CTCallCenter.h>

#import <CoreTelephony/CTCall.h>

@interfaceAppDelegate()

@property(strong,nonatomic)CTCallCenter*callCenter;

@end

@implementationAppDelegate

- (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions {

// Override point for customization after application launch.

_callCenter= [[CTCallCenteralloc]init];

_callCenter.callEventHandler=^(CTCall* call)

{

               if(call.callState==CTCallStateDisconnected)

             {

                 NSLog(@"Call has been disconnected");//已经挂断

           }

             else if(call.callState==CTCallStateConnected)

          {

               NSLog(@"Call has just been connected");//已经接通

         }

        else if(call.callState==CTCallStateIncoming)//有电话接入

       {

            NSLog(@"Call is incoming”);

          //self.viewController.signalStatus=NO;

        }

        else if (call.callState==CTCallStateDialing)

      {

            NSLog(@"call is dialing");//正在呼叫

      }

      else

      {

             NSLog(@"Nothing is done");//中断?

      }

    };

return YES;

}


tip 98 :  使用线程能够解决什么问题 & 多线程应该注意什么

学习多线程之前需要理清的几个问题

1. 线程同步、异步

2.队列串行、并行

3.GCD保护资源

4.延后执行(时间可能更久)

5.锁死问题

6.线程任务优先级

7.为线程存、取数据

8.GCD中是否需要__weak

1.GCD中线程同步、异步

创建同步线程 # 也就是阻塞代码,等待执行完block后再继续往下走

1-1.void dispatch_sync(dispatch_queue_t queue, dispatch_block_t block);1-2.void dispatch_sync_f(dispatch_queue_t queue, void *context, dispatch_function_t work)

创建异步线程# 方法调用之后,block“下面”的代码继续执行。期间,block“里面”的任务会添加到queue中等待执行,执行完任务自动退出

1-1.void dispatch_async(dispatch_queue_t queue, dispatch_block_t block);

1-2.void dispatch_async_f(dispatch_queue_t queue, void *context, dispatch_function_t work);

2.GCD串行队列、并行队列、主队列

创建串行队列的方式 # DISPATCH_QUEUE_SERIAL:串行 ,加入到GCD 串行队列 里面的任务就会一个任务接着一个任务执行

# 串行队列可以是sync同步也可以是异步async

dispatch_queue_t queue = dispatch_queue_create("com.liancheng.serial_queue",DISPATCH_QUEUE_SERIAL);

dispatch_queue_t queue = dispatch_queue_create("com.liancheng.serial_queue",NULL);

创建并行队列的方式 # 自己创建 + 全局队列

dispatch_queue_t queue = dispatch_queue_create("com.liancheng.serial_queue",DISPATCH_QUEUE_CONCURRENT);

dispatch_queue_t dispatch_get_global_queue(long identifier, unsigned long flags);

#identifier 可以是qos_class(系统资源服务级别)枚举也可以是dispatch_queue_priority_t(优先级)枚举

#创建一个默认级别的全局队列dispatch_get_global_queue(NULL, NULL)

获取主队列的方式  #

dispatch_queue_t dispatch_get_main_queue(void)

3.GCD保护资源 dispatch_barrier

// 异步,而且队列里面的任务,也就是blcok里面的代码会被资源访问的时候会被保护,其他线程不可以访问这个资源

void dispatch_barrier_async(dispatch_queue_t queue, dispatch_block_t block); void dispatch_barrier_async_f(dispatch_queue_t queue, void *context, dispatch_function_t work);

// 异步,而且队列里面的任务,也就是blcok里面的代码会被资源访问的时候会被保护,其他线程不可以访问这个资源void dispatch_barrier_sync(dispatch_queue_t queue, dispatch_block_t block);void dispatch_barrier_sync_f(dispatch_queue_t queue, void *context, dispatch_function_t work);

例子:

- (void)setObject:(id)anObject forKey:(id

)aKey{    dispatch_barrier_async(self.concurrentQueue, ^{

// 写操作:开始保护,等执行完任务,其他线程才可以访问self.mutableDictionary        [self.mutableDictionary setObject:anObject forKey:aKey];    });}- (id)objectForKey:(id)aKey{    __block id object = nil;    dispatch_sync(self.concurrentQueue, ^{

// 读操作:可以被随时访问,这里被同步而已        object = [self.mutableDictionary objectForKey:aKey];    });    return  object;}

4.延后执行

dispatch_after(dispatch_time_t when, dispatch_queue_t queue, dispatch_block_t block);

void dispatch_after_f(dispatch_time_t when, dispatch_queue_t queue, void *context, dispatch_function_t work);

dispatch_time_t =》 秒 :int64(3*NSEC_PRESEC) 即为3秒

dispatch_time_t t= DISPATCH_TIME_NOW *int64(3*NSEC_PRE_SEC) // 从现在可是计时,4秒后执行

dispatch_time_t t= DISPATCH_TIME_NOW  // 表示等同于dispatch_async,注意不能等于DISPATCH_TIME_FOREVER否则永远死锁线程

5.锁死问题:造成程序出错

# 在串行队列中,同步执行任务,在同步任务中嵌套同步任务就会发生死锁

dispatch_queue_t queue = dispatch_queue_create("com.liancheng.serial_queue",DISPATCH_QUEUE_SERIAL);dispatch_async(queue, ^{    // 到达串行队列    dispatch_sync(queue, ^{    //发生死锁    });});

6.线程任务优先级

dispatch_queue_t dispatch_get_global_queue(long identifier, unsigned long flags);

#identifier 可以是qos_class(系统资源服务级别)枚举也可以是dispatch_queue_priority_t(优先级)枚举

#创建一个默认级别的全局队列dispatch_get_global_queue(NULL, NULL)

7.为线程存、取数据

存:

void dispatch_queue_set_specific(dispatch_queue_t queue, const void *key, void *context, dispatch_function_t destructor);

queue:需要关联的queue,不允许传入NULL

key:唯一的关键字

context:要关联的内容,可以为NULL

destructor:释放context的函数,当新的context被设置时,destructor会被调用

取:

void *dispatch_queue_get_specific(dispatch_queue_t queue, const void *key);void *dispatch_get_specific(const void *key);

dispatch_queue_get_specific: 根据queue和key取出context,queue参数不能传入全局队列

dispatch_get_specific: 根据唯一的key取出当前queue的context。如果当前queue没有key对应的context,则去queue的target queue取,取不着返回NULL,如果对全局队列取,也会返回NULL

8.GCD中是否需要__weak

不需要使用__weak , 因为GCD中的block属于系统的,而我们当前的类不会持有系统的属性,因此不会产生循环引用问题


tip 99 : MVVM的一些理解

1. MVVM 解释:

M:  model

V: view,viewController

VM: ViewModel

2. MVVM的理解:关系链

view controller : 持有 view

view : 持有 ViewModel

viewModel: 持有Model ,负责 view的逻辑实现

例子:网络请求,刷新tableView, 点击cell做跳转

理解:ViewController.tableView        // ViewController持有view

tableView.viewModel           // view 持有 viewModel

tableView.viewModel.target = self  // ViewModel 也持有 View

viewModel.models                             // viewModel 持有数据 model

viewModel.requestManage         // ViewModel 持有操作 model

在viewController里面添加tableView并显示

在viewController里面viewDidLoad里面_tableView.viewModel.requestManager.requestData()

在tableView初始化方法指定代理对象

self.delegate = viewModel, self.dataSource = viewModel

self.viewModel = self

在viewModel里面实现tableView的delegate和dataSource

在viewModel里面实现网络请求的回调,填充models,并让tableView刷新数据

特别注意:此例子中两个循环引用的问题

第一个:controller持有view, view持有controller

第二个:view持有viewMode, viewModel持有view

解决办法:将 View 的 target 设置为 __weak ViewController

将 ViewModel 的 target 设置为 __weak View


tip 100 : SB 添加约束&删除约束的三种方式

添加约束三种方法:

1.蓝色线+suggest constriant

2.右下角第二个布局按钮

3.control+拖拽(选中自己->父视图;选中自己->相邻视图;选中自己->自己 )

注意:多个控件同时分享水平空间时,注意挤压优先级+抗挤压优先级

删除约束三种方法:

1.在outlayout 大纲页面删除

2.点击约束线删除

3.在右边尺寸观察器下面的constraint选项删除

在autoLayout中,出现具体的数字是一个很糟糕的约束


tip 101 : 是使用png 还是 pdf 图片资源文件呢? (转)

http://www.zcool.com.cn/article/ZMzc3NjA4.html

http://www.th7.cn/Program/IOS/201507/500873.shtml

http://blog.csdn.net/jspandasp/article/details/49339403


先更新到 101 个tips , 以后有时间继续更新! 

PS : 有错的地方欢迎指正!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,839评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,543评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,116评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,371评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,384评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,111评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,416评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,053评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,558评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,007评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,117评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,756评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,324评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,315评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,539评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,578评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,877评论 2 345

推荐阅读更多精彩内容

  • 背景 担心了两周的我终于轮到去医院做胃镜检查了!去的时候我都想好了最坏的可能(胃癌),之前在网上查的症状都很相似。...
    Dely阅读 9,226评论 21 42
  • 在这篇文章中,我将为你整理一下 iOS 开发中几种多线程方案,以及其使用方法和注意事项。当然也会给出几种多线程的案...
    张战威ican阅读 601评论 0 0
  • 学习多线程,转载两篇大神的帖子,留着以后回顾!第一篇:关于iOS多线程,你看我就够了 第二篇:GCD使用经验与技巧...
    John_LS阅读 606评论 0 3
  • GCD (Grand Central Dispatch) :iOS4 开始引入,使用更加方便,程序员只需要将任务添...
    池鹏程阅读 1,323评论 0 2
  • NSThread 第一种:通过NSThread的对象方法 NSThread *thread = [[NSThrea...
    攻城狮GG阅读 789评论 0 3