Posts Tagged "iOS"

所谓,引用计数

简介 在大部分关于Objective-C的书中,一般对于引用计数的讲解基本类似于下面(以 Objective-C基础教程 为例): Cocoa采用了一种称为引用计数的技术。每个对象有一个与之相关联的整数,称作它的引用计数器。当某段代码需要访问一个对象时,该代码将该对象的引用计数器值加1。当该代码结束访问时,将该对象的引用计数器值减1。当引用计数器值为0时,表示不再有代码访问该对象,因此对象将被销毁,其占用的内存被系统回收以便重用。 概括一下就是,每个对象都会有个引用计数器,当且仅当引用计数器的值大于0时,该对象才可能是存活的。 引用计数的内存回收是分布于整个运行期的,基本类似于下图。图中红色表示引用计数的活动。(图片来自于https://github.com/kenfox/gc-viz) 从图中我们可以很直接的看出一些优点,比如: 不需要等到内存不够才回收。 不需要挂起应用程序才回收,回收分布于整个运行期。 当然,引用计数也有一些缺点: 无法完全解决循环引用导致的内存泄露问题。 即使只读操作,也会引起内存写操作(引用计数的修改)。 引用计数读写操作要原子化。 retain release 在苹果开源的 runtime 中,在objc-object.h中有部分关于retain和release的实现代码,具体如下: Retain…

iOS并发编程Tips(二)

在iOS并发编程Tips(一)中,我们提到了三点,分别是线程、原子属性和并发同步。在本文中,你将会看到以下几点: 线程安全 锁 使用主线程 GCD 还是 NSOperationQueue 线程安全 线程安全是编程中的术语,指某个函数、函数库在多线程环境中被调用时,能够正确地处理多个线程之间的共享变量,使程序功能正确完成。 — 维基百科 举个例子。 我们定义一个NSInteger型的全局变量count,我们使用三个异步线程将它自增100000,那么,我们希望的输出结果是300000。但是,它的真实结果是多少呢? #import "ViewController.h" @interface ViewController () @property (assign, nonatomic) NSInteger count; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; for (int i = 0;…

Article in: iOS

FBMemoryProfiler 基础教程

FBMemoryProfiler是Facebook开源的一款用于分析iOS内存使用和检测循环引用的工具库。 在上一篇[译文]在iOS上自动检测内存泄露中,Facebook讲解了FBMemoryProfiler的核心原理。鉴于有人在评论里问怎么使用,我这里就简单介绍一下。 安装 CocoaPods 建议使用Cocoapods安装,只需要在pod文件中,添加这么一句就行: pod 'FBMemoryProfiler' FBMemoryProfiler最低支持iOS8,所以如果你的pod文件上最低要求是6或者7的话,是无法直接安装的。所以,建议在开发分支或者如果你有多个target的话,在开发的target上添加FBMemoryProfiler,在生产的target上不需要添加FBMemoryProfiler。 我一般习惯于有两个target,一个用于开发,里面可能会包含Reveal、蒲公英等的库,而这在生产包中是不必要的,另一个用于生产,只用于打生产包。 所以我的pod文件可能是这样的: # Uncomment this line to define a global platform for your project platform :ios, '8.0' # Uncomment this line if you're using…

Article in: iOS

[译文]在iOS上自动检测内存泄露

原文链接:https://code.facebook.com/posts/583946315094347/automatic-memory-leak-detection-on-ios/ 手机设备的内存是一个共享资源。应用程序可能会不当的耗尽内存、崩溃,或者遭遇大幅度的性能降低。 Facebook iOS客户端有很多功能,并且它们共享同一块内存空间。如果任何特定的功能消耗过多的内存,就会影响到整个应用程序。这是可能发生的,比如,这个功能导致了内存泄露。 当我们分配了一块内存,并设置了对象之后,如果在使用完了之后忘记释放,这就会发生内存泄露。这意味着系统是无法回收内存并交予他人使用,这也最终意味着我们的内存将会逐渐耗尽。 在Facebook,我们有很多工程师在代码库的不同部分上工作。这不可避免的会发生内存泄露。当发生内存泄露之后,我们需要尽快找到并修复它们。 一些工具已经可以找到内存泄露,但是它们需要大量的人工干预: 打开Xcode,给性能分析(profiling)编译。 载入Instruments。 使用应用程序,尝试尽可能多的重现场景和行为。 查看内存和泄露。 追踪内存泄露的根源。 修复这个问题。 这意味着每次都需要重复大量的手动操作。为此,在我们的开发周期上,我们可能无法尽可能早的定位和修复内存泄露问题。 自动化可以在不需要更多开发者的情况下,更快的找到内存泄露。为了解决这个问题,…

iOS并发编程Tips(一)

关于iOS并发编程,雷纯锋有篇博客做了很完整的介绍,大家可以移步学习一下。 我们在这里并不探究NSThread、GCD、NSOperation、NSOperationQueue的具体用法,只探讨一些容易被遗忘的小点。 线程成本 首先,什么是线程,维基百科上是这么说的: A thread of execution is the smallest sequence of programmed instructions that can be managed independently by a scheduler. 按照雷纯锋的博客上的说法就是: 线程(thread),指的是一个独立的代码执行路径,也就是说线程是代码执行路径的最小分支。在 iOS 中,线程的底层实现是基于 POSIX threads API 的,也就是我们常说的 pthreads。 在iOS中,进程启动之后,一个最主要的线程我们称为主线程。主线程会创建和管理所有的UI元素。…

Article in: iOS

iOS 常用Timer 盘点

在iOS的开发过程中,Timer是一个很常见的功能。苹果提供给了我们好几种可以达到Timer效果的方法,我尝试在这里盘点一下。 NSTimer NSTimer是我们最常见的一种Timer,我们从NSTimer开始说起。 用法 NSTimer的用法很简单,个人比较常用的是下面这个方法: [NSTimer scheduledTimerWithTimeInterval:1.0f target:self selector:@selector(test) userInfo:nil repeats:nil]; Tips 为何停止? 有这么一道面试题,题目是这样的: UITableViewCell上有个UILabel,显示NSTimer实现的秒表时间,手指滚动cell过程中,label是否刷新,为什么? 我们来试验一下: 通过试验,我们发现,在手拖拽或者滑动的过程中,label并没有更新,NSTimer也没有循环。 那这是为什么呢?这与RunLoop有关。在NSTimer的官方文档上,苹果是这么说的: A timer is not a real-time mechanism; it…

Article in: iOS

Xcode ToolChain 常用功能

一般来说,我们都是使用Xcode去开发我们的原生iOS App,当然,你也可以选择AppCode,或者一些我不了解的诡异方法。 Xcode是一款强大的GUI IDE,它提供了各种复杂功能,而这背后,是一些命令行工具在支撑着这个强大的IDE。 xcodebuild 顾名思义,这就是一个命令行的Xcode编译工具。 我在Github上放了一个我以前使用的iOS多渠道打包脚本,里面使用到了xcodebuild。这是我在脚本里面的用法: xcodebuild clean xcodebuild -sdk iphoneos -configuration Release xcodebuild -sdk iphonesimulator8.3 -configuration Debug xcodebuild包含大量功能,在终端输入xcodebuild --help可以查看。 我们这只说几种常见的: 指定编译粒度 xcodebuild允许指定编译粒度。现在的工程有一个workspace、多个project、多个target、多个scheme是很正常的一件事情。那么在持续集成,或者批量打包的情况下,我们会使用xcodebuild去编译。一般来说,我们会指定编译粒度,比如: xcodebuild -workspace TuniuNB.xcworkspace…

Article in: iOS

使用Python开发iOS程序

对,你没有看错,就是使用Python开发iOS程序! 我们见过使用JS、Lua、Ruby开发iOS程序的,但是基本没有见过使用Python开发iOS程序(软件)的,这是为什么?关于这个问题,我后面会回答。 那么,怎么用Python开发iOS程序呢?其实我们最主要解决的就是下面几件事情: 在iOS App中安装Python解释器。 搭建Python和objc通信的桥梁。 如何配置工程并开发。 如果不使用UIKit这些,那么就要使用OpenGL ES这些了,这种方式,主要是用于开发游戏的,我们这里不涉及这些。 当然,以下所有内容都是在一台已经安装了Xcode的Mac上进行的。 在iOS App中安装Python解释器 Python-iOS-support pybee开源了一个可以嵌入到iOS工程中的Python编译脚本,具体位置在这: https://github.com/pybee/Python-iOS-support 默认是使用Python 3.4.2,编译x86_64、i386、ARMv7、ARMv7s、ARM64共5个版本,然后打成一个臃肿包,可选framework或者.a。…

开发NB-App中使用的脚本们

在开发NB-App的过程中,为了方便,写了一些小脚本,这里一一列举一下。 脚本地址:https://github.com/Forkong/app-scripts jsonserver脚本 在后端开发人员只给出接口但并未开发完全的时候,这个脚本会充当返回静态json的角色。 基于web.py框架实现,web.py是天才Aaron Swartz开发的一款小型web框架,对于我们来说,入门简单,功能够用。 中文抽离脚本 - 多语言功能 NB-App在2.0版本时期开始支持英文,主要原因是我们的App是给途牛的供应商使用的,而从统计工具上可以看出,我们现在的供应商已经遍及亚洲、欧洲、非洲、北美洲、南美洲、大洋洲,30+的国家和地区,英文版本的支持还是很有需求的。 但是前期在开发过程中并没有料到这种需求,所以并没有留口,中文内容并未抽离,所以我们写了一个抽离脚本。 抽离脚本比较简单,这就不贴出来了。 excel->strings脚本 在产品翻译好我们要求的词条之后,产品会把这些汇总在excel上,类似于下面: 而我们想要的是这样的: 这种工作如果人工来的话,…

注释的魔力

为什么要写注释? 有个笑话是这么说的,说程序员最讨厌两件事情,一件是别人催他写注释,一件是别人的代码没写注释。 我觉得注释主要来源于以下几种情况: 记录开发者当时的思路、想法 例如: //这种做法很独特,但是依然可以达到效果 提醒自己或者后续开发 //TODO:这里可以替换为更快的算法 //这里有一个Bug,但是并不会影响xx系统,修复起来代价很大,原因出在xx上面,建议不要修复此bug 诠释具体代码 /** Sorts the elements of a sequence in descending order by using a specified keySelector. @param keySelector A selector that provides the 'key' which the array should by sorted by. @return…

Article in: iOS