关于ios:iOS编译器调试工具包管理器系统框架漫谈

11次阅读

共计 17154 个字符,预计需要花费 43 分钟才能阅读完成。

本文次要介绍

1.Clang 与 LLVM

2.GDB 与 LLDB

3.homebrew 与 CocoaPods 等

4.iOS 零碎框架

1.Clang 与 LLVM

LLVM 我的项目的倒退起源于 2000 年伊利诺伊大学厄巴纳 - 香槟分校维克拉姆·艾夫(Vikram Adve)与克里斯·拉特纳(Chris Lattner)的钻研,他们想要为所有动态及动静语言发明出动静的编译技术。LLVM 是以 BSD 受权来倒退的开源软件。2005 年,苹果电脑雇用了克里斯·拉特纳及他的团队为苹果电脑开发应用程序零碎,LLVM 为现今 Mac OS X 及 iOS 开发工具的一部分。

LLVM 的命名最早源自于底层虚拟机(Low Level Virtual Machine)的首字母缩写,因为这个我的项目的范畴并不局限于创立一个虚拟机,这个缩写导致了宽泛的纳闷。LLVM 开始成长之后,成为泛滥编译工具及低级工具技术的统称,使得这个名字变得更不贴切,开发者因此决定放弃这个缩写的意涵,现今 LLVM 已单纯成为一个品牌,实用于 LLVM 下的所有我的项目,蕴含 LLVM 中介码(LLVM IR)、LLVM 除错工具、LLVM C++ 规范库等。

Xcode3 之前,用的是 GCC
Xcode3,GCC 依然保留,然而也推出了 LLVM,苹果举荐 LLVM-GCC 混合编译器,但还不是默认编译器
Xcode4,LLVM-GCC 成为默认编译器,但 GCC 仍保留
Xcode4.2,LLVM3.0 成为默认编译器, 纯用 GCC 不复可能
Xcode4.6,LLVM 降级到 4.2 版本
Xcode5,LLVM-GCC 被遗弃,新的编译器是 LLVM5.0,从 GCC 过渡到 LLVM 的时代正式实现

Clang – a C language family frontend for LLVM

Clang(发音为 /ˈklæŋ/)是一个 C、C++、Objective- C 和 Objective-C++ 编程语言的编译器前端。它采纳了底层虚拟机(LLVM)作为其后端。它的指标是提供一个 GNU 编译器套装(GCC)的替代品。作者是克里斯·拉特纳,在苹果公司的资助反对下进行开发,而源代码受权是应用类 BSD 的伊利诺伊大学厄巴纳 - 香槟分校开源码许可。
Clang 我的项目包含 Clang 前端和 Clang 动态分析器等。

Clang 的在出世之前就曾经明确了他的使命——干掉该死的 GCC。有了 LLVM+Clang,从此,苹果的开发风貌面目一新。从此解脱了 GCC 的限度。主观的说 GCC 是有很多的长处,例如反对多平台,很风行,基于 C 无需 C ++ 编译器即可编译。这些长处到苹果那就可能是毛病了,苹果须要的是——快。这正是 Clang 的长处,除了快,它还有与 GCC 兼容,内存占用小,诊断信息可读性强,易扩大,易于 IDE 集成等等长处。有个测试数据:Clang 编译 Objective- C 代码时速度为 GCC 的 3 倍。

iOS 编译过程


Objective- C 与 swift 都采纳 Clang 作为编译器前端,编译器前端次要进行语法分析,语义剖析,生成中间代码,在这个过程中,会进行类型查看,如果发现错误或者正告会标注进去在哪一行。

编译器后端会进行机器无关的代码优化,生成机器语言,并且进行机器相干的代码优化,依据不同的零碎架构生成不同的机器码。

C++,Objective C 都是编译语言。编译语言在执行的时候,必须先通过编译器生成机器码。


如上图所示,在 xcode 按下 cmd+ B 之后的工作流程。

预处理(Pre-process):他的次要工作就是将宏替换,删除正文开展头文件,生成.i 文件。
词法剖析(Lexical Analysis):将代码切成一个个 token,比方大小括号,等于号还有字符串等。是计算机科学中将字符序列转换为标记序列的过程。
语法分析(Semantic Analysis):验证语法是否正确,而后将所有节点组成形象语法树 AST。由 Clang 中 Parser 和 Sema 配合实现
动态剖析(Static Analysis):应用它来示意用于剖析源代码以便主动发现错误。
两头代码生成(Code Generation):开始 IR 中间代码的生成了,CodeGen 会负责将语法树自顶向下遍历逐渐翻译成 LLVM IR,IR 是编译过程的前端的输入后端的输出。
优化(Optimize):LLVM 会去做些优化工作,在 Xcode 的编译设置里也能够设置优化级别 -01,-03,-0s,还能够写些本人的 Pass,官网有比拟残缺的 Pass 教程:Writing an LLVM Pass — LLVM 5 documentation。如果开启了 bitcode 苹果会做进一步的优化,有新的后端架构还是能够用这份优化过的 bitcode 去生成。

生成指标文件(Assemble):生成 Target 相干 Object(Mach-o)
链接(Link):生成 Executable 可执行文件

通过这一步步,咱们用各种高级语言编写的代码就转换成了机器能够看懂能够执行的指标代码了。


环境搭建

cd /opt
sudo mkdir llvm
sudo chown `whoami` llvm
cd llvm
export LLVM_HOME=`pwd`

git clone -b release_39 git@github.com:llvm-mirror/llvm.git llvm
git clone -b release_39 git@github.com:llvm-mirror/clang.git llvm/tools/clang
git clone -b release_39 git@github.com:llvm-mirror/clang-tools-extra.git llvm/tools/clang/tools/extra
git clone -b release_39 git@github.com:llvm-mirror/compiler-rt.git llvm/projects/compiler-rt

mkdir llvm_build
cd llvm_build
cmake ../llvm -DCMAKE_BUILD_TYPE:STRING=Release
make -j`sysctl -n hw.logicalcpu`

文件很多很大,须要下载一段时间


Clang Static Analyzer 动态代码剖析

clang 动态剖析是通过建设剖析引擎和 checkers 所组成的架构,这部分性能能够通过 clang —analyze 命令形式调用。

命令行执行

通过 clang -cc1 -analyzer-checker-help 能够列出能调用的 checker,但这些 checker 并不是所有都是默认开启的

这里应用一个默认敞开的 checker-alpha.security.ArrayBoundV2 作为例子进行操作
$ clang -cc1 -analyzer-checker-help
 alpha.core.BoolAssignment       Warn about assigning non-{0,1} values to Boolean variables
  alpha.core.CastSize             Check when casting a malloced type T, whether the size is a multiple of the size of T
  alpha.core.CastToStruct         Check for cast from non-struct pointer to struct pointer
  alpha.core.FixedAddr            Check for assignment of a fixed address to a pointer
  alpha.core.IdenticalExpr        Warn about unintended use of identical expressions in operators
  alpha.core.PointerArithm        Check for pointer arithmetic on locations other than array elements
  alpha.core.PointerSub           Check for pointer subtractions on two pointers pointing to different memory chunks
  alpha.core.SizeofPtr            Warn about unintended use of sizeof() on pointer expressions
  alpha.cplusplus.NewDeleteLeaks  Check for memory leaks. Traces memory managed by new/delete.
  alpha.cplusplus.VirtualCall     Check virtual function calls during construction or destruction
  ...
  alpha.security.ArrayBound       Warn about buffer overflows (older checker)
  alpha.security.ArrayBoundV2     Warn about buffer overflows (newer checker)
  alpha.security.MallocOverflow   Check for overflows in the arguments to malloc()
  alpha.security.ReturnPtrRange   Check for an out-of-bound pointer being returned to callers
  ...
  core.CallAndMessage             Check for logical errors for function calls and Objective-C message expressions (e.g., uninitialized arguments, null function pointers)
  core.DivideZero                 Check for division by zero
  core.DynamicTypePropagation     Generate dynamic type information
  core.NonNullParamChecker        Check for null pointers passed as arguments to a function whose arguments are references or marked with the 'nonnull' attribute
  core.NullDereference            Check for dereferences of null pointers
  core.StackAddressEscape         Check that addresses to stack memory do not escape the function
  ...
  unix.API                        Check calls to various UNIX/Posix functions
  unix.Malloc                     Check for memory leaks, double free, and use-after-free problems. Traces memory managed by malloc()/free().
  unix.MallocSizeof               Check for dubious malloc arguments involving sizeof
  unix.MismatchedDeallocator      Check for mismatched deallocators.
  unix.cstring.BadSizeArg         Check the size argument passed into C string functions for common erroneous patterns
  unix.cstring.NullArg            Check for null pointers being passed as arguments to C string functions

能够应用 -enable-checker 和 -disable-checker 开启和禁用具体的 checker 或者 某种类别的 checker。

$ scan-build -enable-checker alpha.security.ArrayBoundV2 ... # 启用数组边界查看

当然,应用 scan-build 启用的 checker 只实用于应用 scan-build 生成的 html 报告。
scan-build在编译装置 llvm/clang 之后能够在 /llvm/tools/clang/tools/scan-build 目录下找到

// 容许未被默认容许的 check 并进行代码剖析并将输入后果输入至网页
./scan-build  -enable-checker alpha.security.ArrayBoundV2 --use-analyzer=/opt/llvm/llvm_build/bin -V xcodebuild  -project /Users/yuhao/TestClang/TestClang.xcodeproj -sdk iphonesimulator10.3

咱们在 TestClang.xcodeproj 的 main.m 文件中插入一段 数组越界 的代码

int main(){
    @autoreleasepool {int a[2];
        int i;
        for (i = 0; i < 3; i++){a[i] = 0;
        }
    }
    return 0;
}

而后执行下面的命令,会导出这样的一个界面

查看报表
https://upload-images.jianshu…
报表中提醒了该代码有数组越界的问题。

Xcode 执行

Xcode 自身曾经自带了动态检测的性能,能够通过 Product-Analyze 来执行动态检测,这也只是用自带的 clang 去执行,如果想用其余的版本,比方本人编译 clang,就须要通过命令来设置。

在 Xcode 的 Product 选项卡下有 Analyze 的选项,Xcode 中默认提供了一些 checkers。

Usage: set-xcode-analyzer [options]

Options:
  -h, --help            show this help message and exit
  --use-checker-build=PATH
                        Use the Clang located at the provided absolute path,
                        e.g. /Users/foo/checker-1
  --use-xcode-clang     Use the Clang bundled with Xcode

能够看到,它有 2 个选项,

--use-checker-build:用于将 xcode 的 clang 版本切换成设定的版本
--use-xcode-clang:用于将 xcode 的 clang 版本切换回去

注:在执行下面命令的时候,须要退出 xcode 执行;且须要用 sudo 的形式运行。

仍然应用下面的 project 文件,在 Build Settings 增加参数,如图

-Xanalyzer -analyzer-checker=alpha.security.ArrayBoundV2

而后 cmd+shift+b

在 Xcode 中也呈现了和报表同样的提醒。
对于 checker 的开发能够看这里。
weak 的实现
runtime 是如何实现在 weak 润饰的变量的对象在被销毁时主动置为 nil 的呢?一个广泛的解释是:runtime对注册的类会进行布局,对于 weak 润饰的对象会放入一个 hash 表中。用 weak 指向的对象内存地址作为 key,当此对象的援用计数为0 的时候会 dealloc,如果weak 指向的对象内存地址是 a,那么就会以a 为键在这个 weak 表中搜寻,找到所有以 a 为键的 weak 对象,从而设置为nil

weak指针的实现借助 Objective-C 的运行时个性,runtime通过 objc_storeWeak, objc_destroyWeakobjc_moveWeak等办法,间接批改 __weak 对象,来实现弱援用。

objc_storeWeak函数,将附有 __weak 标识符的变量的地址注册到 weak 表中,weak表是一份与援用计数表类似的散列表。

而该变量会在开释的过程中清理 weak 表中的援用,变量开释调用以下函数:

dealloc
_objec_rootDealloc
object_dispose
objc_destructInstance
objc_clear_deallocating

在最初的 objc_clear_deallocating 函数中,从 weak 表中找到弱援用指针的地址,而后置为 nil, 并从weak 表删除记录。

对于 ARC 更多实现请参阅探索 ARC

2.GDB 与 LLDB

咱们在开发 iOS 程序的时候经常会用到调试跟踪,如何正确的应用调试器来 debug 非常重要。xcode 里有内置的 Debugger,老版应用的是 GDB,xcode 自 4.3 之后默认应用的就是 LLDB 了。

GDB:
UNIX 及 UNIX-like 下的调试工具。

LLDB:
LLDB 是个开源的内置于 XCode 的具备 REPL(read-eval-print-loop)特色的 Debugger,其能够装置 C ++ 或者 Python 插件。

所以他们两个都是调试用的 Debugger,只是 LLDB 是比拟高级的版本,或者在调试开发 iOS 利用时比拟好用,不然人家苹果为什么换成了 LLDB 了呢!

lldb 与 gdb 命令名的对照表:http://lldb.llvm.org/lldb-gdb.html

LLDB 的应用

在程序里你须要的中央设置断点。当断点断住的时候你就能看到咱们进入 LLDB 调试器了。


这时咱们就能够应用一些 LLDB 命令来进行一些调试了。

调试快捷键:(Xcode 罕用快捷键)

command+shift+Y 关上调试窗口
command+Y 调试运行程序
command+option+P 持续
command+shift+O 跳过
command+shift+I 进入
command+shift+T 跳出

help 命令

help 会列出所有命令列表,用户加载的插件一般来说列在最初。
执行 help 能够打印指定 command 的帮忙信息。
比方:help print 会打印内建命令 print 的应用帮忙。

print 命令

print 命令的简化形式有 prin pri p,唯独 pr 不能用来作为查看,因为会和 process 混同,侥幸的是 p 被 lldb 实现为特指 print。

实际上你会发现,lldb 对于命令的简称,是头部匹配形式,只有不混同,你能够随便简称某个命令。

例如:

最后面的(int)是类型。$ 是命令后果的援用名,应用 $0 能够进行 print $0 + 7 这样打印出 17。

输入 view 下 subview 的数量。

因为 subview 的数量是一个 int 类型的值,所以咱们应用命令 p:
(lldb)p (int)[[[self view] subviews] count]

间接调用办法扭转背景色彩之类
其实应用 p,po,call 都能够调用办法,只是 p 和 po 都是用于输入的有返回值的。call 个别只在不须要显示输入,或是办法无返回值时应用。
(lldb)p [self.view setBackgroundColor:[UIColor redColor]]
(lldb)p (void)[CATransaction flush]
上述的 p 个别应用 call 比拟好,因为办法是没有返回值的。

po 命令

命令 po 跟 p 很像。p 输入的是根本类型,po 输入的 Objective- C 对象。调试器会输入这个 object 的 description。

例如:

expression 命令

expression 的简写就是 e。能够用 expression 来申明新的变量,也能够扭转已有变量的值。咱们看到 e 申明的都是 $ 结尾的变量。咱们在应用时也须要加上 $ 符号。

例如:

创立新的变量

留神:如果下面这里输出以下命令,会产生谬误。阐明 lldb 无奈断定某一步的计算结果是什么数据类型,这时须要强制类型转换来通知 lldb。

(lldb) p [[$array objectAtIndex:0] characterAtIndex:0]
error: no known method '-characterAtIndex:'; cast the message send to the method's return type
error: 1 errors parsing expression

(lldb) p (char)[[$array objectAtIndex:0] characterAtIndex:0]
'o'

批改已有变量

image 命令

image 命令可用于寻址,有多个组合命令。比拟实用的用法是用于寻找栈地址对应的代码地位。上面我写了一段代码

NSArray *arr=[[NSArray alloc] initWithObjects:@"1",@"2", nil];
NSLog(@"%@",arr[2]);

这段代码有显著的谬误,程序运行这段代码后会抛出上面的异样:

 *** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayI objectAtIndex:]: index 2 beyond bounds [0 .. 1]'
*** First throw call stack:
(
 0   CoreFoundation                      0x0000000101951495 __exceptionPreprocess + 165
 1   libobjc.A.dylib                     0x00000001016b099e objc_exception_throw + 43
2   CoreFoundation                      0x0000000101909e3f -[__NSArrayI objectAtIndex:] + 175
3   ControlStyleDemo                    0x0000000100004af8 -[RootViewController viewDidLoad] + 312
4   UIKit                               0x000000010035359e -[UIViewController loadViewIfRequired] + 562
5   UIKit                               0x0000000100353777 -[UIViewController view] + 29
6   UIKit                               0x000000010029396b -[UIWindow addRootViewControllerViewIfPossible] + 58
7   UIKit                               0x0000000100293c70 -[UIWindow _setHidden:forced:] + 282
8   UIKit                               0x000000010029cffa -[UIWindow makeKeyAndVisible] + 51
9   ControlStyleDemo                    0x00000001000045e0 -[AppDelegate application:didFinishLaunchingWithOptions:] + 672
10  UIKit                               0x00000001002583d9 -[UIApplication _handleDelegateCallbacksWithOptions:isSuspended:restoreState:] + 264
11  UIKit                               0x0000000100258be1 -[UIApplication _callInitializationDelegatesForURL:payload:suspended:] + 1605
12  UIKit                               0x000000010025ca0c -[UIApplication _runWithURL:payload:launchOrientation:statusBarStyle:statusBarHidden:] + 660
13  UIKit                               0x000000010026dd4c -[UIApplication handleEvent:withNewEvent:] + 3189
14  UIKit                               0x000000010026e216 -[UIApplication sendEvent:] + 79
15  UIKit                               0x000000010025e086 _UIApplicationHandleEvent + 578
16  GraphicsServices                    0x0000000103aca71a _PurpleEventCallback + 762
17  GraphicsServices                    0x0000000103aca1e1 PurpleEventCallback + 35
18  CoreFoundation                      0x00000001018d3679 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 41
19  CoreFoundation                      0x00000001018d344e __CFRunLoopDoSource1 + 478
20  CoreFoundation                      0x00000001018fc903 __CFRunLoopRun + 1939
21  CoreFoundation                      0x00000001018fbd83 CFRunLoopRunSpecific + 467
22  UIKit                               0x000000010025c2e1 -[UIApplication _run] + 609
23  UIKit                               0x000000010025de33 UIApplicationMain + 1010
24  ControlStyleDemo                    0x0000000100006b73 main + 115
25  libdyld.dylib                       0x0000000101fe95fd start + 1
26  ???                                 0x0000000000000001 0x0 + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException

当初,咱们狐疑出错的地址是 0x0000000100004af8(能够依据执行文件名判断,或者最小的栈地址)。为了进一步精确定位,咱们能够输出以下的命令:

(lldb)image lookup --address 0x0000000100004af8(lldb)im loo -a 0x0000000100004af8

命令执行后返回:

Address: ControlStyleDemo[0x0000000100004af8] (ControlStyleDemo.__TEXT.__text + 13288)
Summary: ControlStyleDemo`-[RootViewController viewDidLoad] + 312 at RootViewController.m:53

咱们能够看到,出错的地位是 RootViewController.m 的第 53 行。

设置断点触发条件

LLDB 与 GDB 总结

原理

编译时输入带调试信息的程序,调试信息蕴含了指令地址、对应源代码及行号,指令实现后回调给调试器。

gdb/lldb 常用命令

  • b:设置断点 break。
  • r:运行 run。
  • n:单步调试 next。
  • s:跳入函数 step。
  • finish:跳出函数。
  • p a:打印 a 的内容 print。
  • c:持续,直到下一个断点 continue。

2.1 打包编译组件

xctoo 简介:facebook 那帮人,耐不住每天打包的懊恼,搞了一些自动化组件工具。基于 xcodebuild 封装了一层造成了 xctool。

xctool 有哪些益处呢?

1、它能够从命令行构建和运行单元测试,这和 Xcode.app 从图形化界面上达到一样的成果。如果你为 iOS 设置了继续集成系统,那么这就十分重要了。你想要可能自动化运行测试,那些测试与你的开发人员在本地计算机上运行的完全相同,而 xcodebuild 不会用和 Xcode.app 雷同的形式来构建和运行测试。在 Xcode 4 中,苹果把单元测试集成到了 Xcode 中——与“构建”和“运行”一起,有一个新的“测试”动作;应用 Xcode scheme,你能够抉择启用或者禁用哪些单元测试;如果你依赖于 iOS 模拟器(也就是应用程序测试)来编写测试,那么 Xcode 会主动载入模拟器并运行测试。这些都是很大的改良,但看起来苹果并没有把这些改良融入到 xcodebuild 中,那使得自动化构建和测试十分艰难。

         2、另一个重大的问题是构建和测试失败的报告。应用 xcodebuild,你会失去大量文本输入,其中蕴含编译命令、编译谬误和正告以及 OCUnit 的测试输入。如果你想要主动确定哪个组件编译失败,或者哪个单元测试失败,那么你就须要编写本人的正则表达式解析器,那也是咱们和其余 iOS 社区中的人始终在做的工作。那会有成果,但切实很麻烦。有了 xctool,咱们会让 xcodebuild 和 OCUnit 测试运行器把构建输入和测试后果作为 JSON 对象的结构化流输入。这让咱们能够很容易地以须要的模式来显示构建和测试后果。例如,咱们创立了一个报表,以吸引人的、带有色彩的输入模式来显示后果(https://fpotter_public.s3.amazonaws.com/xctool-uicatalog.gif)。还有人应用这来把测试后果输入为 JUnit XML,那在风行的 Jenkins 构建零碎中会显示得很好。>>>>

xctool 的应用:常用命令在他们工程的 readme 里有详细描述和例子:https://github.com/facebook/x… 

xctool 不反对指定 target 如 -target; 必须用 scheme 例如

  1. path/to/xctool.sh \
  2. -project YourProject.xcodeproj \
  3. -scheme YourScheme \
  4. build

xctool 指定打印报告

  1. path/to/xctool.sh \
  2. -workspace YourWorkspace.xcworkspace \
  3. -scheme YourScheme \
  4. -reporter plain:/path/to/plain-output.txt \
  5. build

能够指定的格局如下

  • pretty: a text-based reporter that uses ANSI colors and unicode symbols for pretty output (the default).
  • plain: like _pretty_, but with no colors or unicode.
  • phabricator: outputs a JSON array of build/test results which can be fed into the Phabricator code-review tool.
  • junit: produces a JUnit/xUnit compatible XML file with test results.
  • json-stream: a stream of build/test events as JSON dictionaries, one per line (example output).
  • json-compilation-database: outputs a JSON Compilation Database of build events which can be used by Clang Tooling based tools, e.g. OCLint.
  • user-notifications: sends notification to Notification Center when action is completed (example notifications).
  • teamcity: sends service messages to TeamCity Continuous Integration Server

上面用 xcodebuild 和 xctool 理论入手打几个包来练练手。

一:测试了半天 xcode8 当前不反对 xctool 了  汗!!!

二:咱们回到 xcodebuild 上

project_path=$(pwd)
echo “project_path:${project_path}”
schemeName=”FunnyProject”
outPutPath=”${project_path}/outputDir”
echo “outputPath:${outPutPath}”

xcodebuild clean -workspace ${schemeName}.workspace -scheme ${schemeName} -configuration Debug

xcodebuild  -project $schemeName.xcodeproj -scheme $schemeName clean

xcodebuild archive -project $schemeName.xcodeproj -scheme $schemeName -archivePath “${outPutPath}/${schemeName}.xcarchive” -configuration Debug

 

xcodebuild -archivePath “${outPutPath}/${schemeName}.xcarchive” -exportPath “${outPutPath}/${schemeName}.ipa” -exportOptionsPlist “${outPutPath}/ExportOptions.plist” -exportArchive 

// 这里有个参数 exportOptionsPlist 须要收到打包导出文件夹里有这个文件,相当于一个配置文件,用这个文件来导出包,把这个文件 copy 到当前目录即可

-exportOptionsPlist  “${outPutPath}/${schemeName}.plist”

xcodebuild -exportArchive   -exportSigningIdentity ‘Developer ID Application: My Team’

 #xcodebuild -exportArchive -archivePath <xcarchivepath> -exportPath <destinationpath> -exportOptionsPlist <plistpath>

xctool -workspace GWMovie.xcworkspace -scheme GWMovie -sdk iphonesimulator  run-tests 

echo “${SECONDS}s”

3. 包管理器

MacPorts

MacPorts 依赖于 BSD 的软件包管理工具(port),它的工作形式是从仓库中下载软件包以及其依赖库,而后在本机中编译装置。

MacPorts 的理念是尽量减少对系统现有库的依赖,因而它须要下载许多根底库,而后编译装置到零碎中。这样做最大的问题在于 下载工夫长,编译工夫长,最大的益处就是不会毁坏零碎原有软件包。

Homebrew

Homebrew 与 MacPorts 的工作形式相似,也是从仓库中下载软件包以及其依赖库,而后在本机中编译装置。

Homebrew 的理念是尽量应用零碎中存在的库,且软件包都装置到 /usr/local 目录里,最大的益处就是下载编译工夫短于 MacPorts,安装简单,且无需 root 用户权限来装置。
Homebrew简直快成为 Mac OSX 零碎下事实上的规范软件包管理工具了

CocoaPods

iOS 和 OS X 下的一个第三方库管理工具,相似的 iOS 工具还有 Carthage(比拟轻量级,须要手动配置,非侵入式),与 Java 里的 Maven 也比拟相似,然而没有 maven 的构建、运行程序、打包等性能,仅仅是库依赖配置和库版本管理工具。
作用:依赖库版本治理、库依赖主动配置;

零碎架构

一、iOS 零碎架构

用户体验层(The User Experience Layer)

应用软件开发框架层(The Application Frameworks Layer)

外围开发框架层(The Core Frameworks)

零碎内核核心层(Darwin)



概述:

1、Darwin

Darwin 是一种相似 unix 的操作系统,他的外围是 XNU。

XNU 是一种混合式内核。联合了 mach 与 BSD 两种内核。

Mach 是微内核实现。

BSD 实现在 Mach 的下层,这一层提供的 API 反对了 POSIX 规范模型。在 XNU 中次要实现了一些高级的 API 与模块。

1.1、Mach 微内核简介

在 XNU 中次要实现以下几个性能:

过程与线程的形象

虚拟内存治理

任务调度

过程间通信

1.2、BSD 内核简介

BSD 实现在 Mach 的下层,这一层提供的 API 反对了 POSIX 规范模型。在 XNU 中次要实现了一些高级的 API 与模块。

UNIX 过程模型。

POSIX 线程模型即 pthread,以及相干的同步性能。

UNIX 的用户与组治理。

网络协议栈(BSD Socket API),合乎 POSIX 模型。

文件系统 / 设施零碎。

1.3、libKern

实现了一个 C + + 的子集(以库的模式为反对 C + + 提供了运行时),为 I /O kit 提供基础设施

1.4、I/O kit

I/O kit 是 XNU 不同于其余操作系统的设施驱动框架。IOKit 是一个面向对象的驱动模型框架,它是晚期 DriverKit 的一个翻版,Driver Kit 是应用 Objective- C 写的,而 IOKit 是一个 C + + 的驱动架构,它在 DriverKit 的根底上做了很大的改良,比方 IOKit 能够写在用户空间跑的驱动(尽管大多仍是跑在内核空间上的),因此驱动挂了而零碎不会挂。另外 IOKit 思考到了计算机倒退的趋势,所以在电源治理、即插即用、动静加载上做得更好。

两个根底框架

iOS 应用程序基于 Foundation 和 UIKit 框架

1. Foundation

在你开发程序时,次要应用框架就是 Foundation 和 UIKit,因为它们蕴含了你须要的大部分货色。

  • Foundation 框架为所有的应用程序提供根本零碎服务
    你的应用程序,UIKit 和其它的框架都是建设在 Foundation 框架下面的。Foundation 框架是用 Object- C 对 CoreFoundation 框架里许多个性的封装。
  • 应用 Foundation 能够:
  1. 创立和治理汇合,比方数组和字典
  2. 拜访存储在应用程序里的图片和其它资源
  3. 创立和治理字符串
  4. 提交和接管告诉
  5. 创立日期和工夫对象
  6. 主动发现 IP 网络上的设施
  7. 操作 URL 流
  8. 执行异步代码

    你曾经在《Your First iOSApp》里应用到了 Foundation 框架。比方,你应用一个 NSString 类的实例存储用户输出的 userName。你还应用了 Foundation 框架的 initWithFormat 办法创立了一个字符串。
    UIKit 框架提供创立基于触摸用户界面的类

2. UIKit

所有的 iOS 应用程序都基于 UIKit,你不能是应用程序脱离这个框架。UIKit 提供了在屏幕上绘制的机制,捕捉事件,和创立通用用户界面元素。UIKit 也通过治理显示在屏幕上的组件来组织简单的我的项目。

  • 应用 UIKit 能够:
  1. 构建和治理你的用户界面
  2. 捕捉触摸和基于挪动的事件
  3. 出现文字和 web 内容
  4. 优化你的多任务程序
  5. 创立定制的用户界面元素

在《YouFirstiOS AppTutorial》里,你也应用到了 UIKit。当你认真查看程序是怎么运行起来的时候,你会看到 UIApplicationMain 函数创立一个 UIApplication 类的实例,这个实例会捕捉进来的用户事件。你实现 UITextFieldDelegate 协定,而后在用户按下 Done 时暗藏键盘。实际上,你是在应用 UIKit 创立用户界面上的 UITextField,UILabel,和 UIButton 类。

你须要晓得的其它重要的框架

Core Data , Core Graphics, CoreAnimation, 和 OpenGLES 框架都是高级的技术。所以这些框架对于你开发应用程序也是很重要的,它们都须要工夫去学习和把握。

1. CoreData 框架管着理应用程序数据模型

Core Data 提供对象的治理,应用 CoreData,你能够创立模型对象,并治理这些对象。你治理这这些对象间的分割并批改数据。CoreData 提供的内建 SQLlite 技术能够高效的治理数据。
应用 Core Data 能够:

  • 在库里存储和接管对象
  • 提供根本的 undo/redo
  • 主动验证属性值
  • 过滤、分组和优化内存中的数据
  • 用 [NSFetchedResultsController] 治理表视图中的后果
  • 反对基于文档的应用程序
2. CoreGraphics 框架帮忙你创立图形

高质量的图形对于所有的 iOS 应用程序都是很重要的。在 iOS 中最简略且最快捷的创立图形的形式是应用 UIKit 框架提供的基于预渲染图形的视图和控件,而后让 UIKit 和 iOS 实现绘制。然而当你须要创立简单的图形时,CoreGraphics 则提供了更底层的库来帮忙你。

应用 Core Graphics 能够:

  • 创立基于门路的绘图
  • 抗锯齿渲染
  • 增加梯度、图片和色彩
  • Use coordinate-spacetransformations.
  • 创立、显示和剖析 PDF 文档
3. CoreAnimation 容许你创立高级的动画和虚构成果

UIKit 提供建设在 Core Animation 之上的动画。如果你须要比 UIKit 能力更高级的性能,能够间接应用 CoreAnimation。Core Animation 接口蕴含在 Quartz Core 框架里。应用 CoreAnimation 能够创立嵌套的对象,并且能够对它们操作、旋转、缩放和转换。应用 Coreanimation,你能够创立动静的用户界面而不必应用更底层的图形 API,如 OpenGL ES。

应用 Core Animation 能够:

  • 创立定制动画
  • 增加定时函数和图形
  • 反对帧动画
  • Specify graphical layoutconstraints.
  • Group multiple-layerchanges into anatomic update.
4. OpenGL ES 框架提供 2D 和 3D 绘图工具

OpenGL ES 反对 2D 和 3D 绘图,Apple 的 OpenGL ES 实现通过硬件提供了高速的全屏游戏式的应用程序。

应用 OpenGL ES 能够:

  • 创立 2D 和 3D 图形
  • 创立更简单的图形,比方数据虚拟化、模仿航行,或者视频游戏
  • 拜访底层图形设施

依据须要向我的项目中增加其它框架

还有许多框架能够增加到你的程序里。当你决定应用一个框架但我的项目里却没有引入这个框架时,你就须要将它退出到你的我的项目里。

将别的框架增加到工程里

1 关上工程
2 点击我的项目名,显示 project editor
3 在 TARGETS 列表中选中要增加框架的工程
4 点击 project editor 顶部的 BuildPhases
5 点击 Link Binary WithLibraries 后面的三角形关上这个分组
6 通过点击增加 (+) 来增加一个框架
7 在列表中抉择一个框架,而后点击 Add 按钮

正文完
 0