0%

定义如下两个类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14

@interface Person : NSObject
@property (nonatomic,assign) int age;
@end

@implementation Person
@end

@interface Student : Person
@property (nonatomic,assign) int no;
@end

@implementation Student
@end

将其转换为C++代码可见其底层实现如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
struct NSObject_IMPL {
Class isa;
};

struct Person_IMPL {
struct NSObject_IMPL NSObject_IVARS;
int _age;
};

struct Student_IMPL {
struct Person_IMPL Person_IVARS;
int _no;
};

可见子类实例对象的结构体中会包含父类的结构体,且父类的结构体存储在最前。

实时查看内存数据

在Xcode菜单栏中通过以下顺序可以查看对象的内存数据:

Debug -> Debug Workfllow -> View Memory

对一个NSObject实例对象来说,通过该方法观察到前8个字节为非0值,后8个字节为全为0,第17位开始为非0值。 由此可以推断,前8个字节代表isa指针,也从侧面验证了一个NSObject实例对象指针指向内存的大小为16个字节。

常用的lldb指令

print

print用于打印指针地址,可缩写为p.

po

po用于打印对象,即print object.

memory read

  • memory read用于读取内存,可以缩写为x。其使用方法为:
1
x/数量|格式|字节数  内存地址	

数量参数说明要打印多少个数据,格式参数和字节参数说明怎么样打印这些数据。这些参数都可以省略,即直接使用memory read 内存地址.

格式参数说明:

1
x是16进制,f是浮点,d是10进制

字节参数说明:

1
2
b:byte 1字节,h:half word 2字节
w:word 4字节,g:giant word 8字节

例如,x/3xg表示以16进制的形式打印3个字节串,每个字节串包含8个字节。

memory write

memory write用于修改内存中的值. 使用方法为:

1
memory  write  内存地址  新值

将Objective-C转换为C\C++代码

下面的命令可以将Objective-C代码转换为C\C++代码, 但是转换出来的代码仅供分析参考.

xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m -o mainarm64.cpp

如果需要链接其他框架,使用-framework参数。比如-framework UIKit.

使用上面的命令可以窥探出NSObject的底层实现如下:

1
2
3
4
5
6
7
8
9
10
//头文件定义
@interface NSObject <NSObject> {
Class isa;
}

//转换为C++代码后
struct NSObject_IMPL {
Class isa; //64位系统中指针占8个字节
};

可见,Objective-C的面向对象是基于C\C++的结构体实现的.

NSObject实例对象的内存分配

导入 objc/runtime.h 后可以使用函数class_getInstanceSize获得NSObject实例对象的成员变量所占用的大小为8个字节(内存对齐后的大小).

class_getInstanceSize([NSObject class])

导入 malloc/malloc.h后可以使用函数malloc_size获得NSObject实例对象指针指向内存的大小为16个字节.

malloc_size((__bridge const void *)(obj))

通过以下路径追踪NSObject对象的内存分配过程:

  1. allocWithZone:
  2. _objc_rootAllocWithZone()
  3. class_createInstance()
  4. _class_createInstanceFromZone
  5. instanceSize()

其中instanceSize()函数返回要为NSObject实例对象分配的内存大小, 其实现如下:

1
2
3
4
5
6
7
size_t instanceSize(size_t extraBytes) {
size_t size = alignedInstanceSize() + extraBytes;
// CF requires all objects be at least 16 bytes.
if (size < 16) size = 16;
return size;
}

可见NSObject实例对象占用的最小内存为16个字节.

xcode-select

This will install the Command Line Tools, which are necessary for compiling Objective-C code.

xcode-select install
    

xcrun

xcrun is the fundamental Xcode command line tool. With it, all other tools are invoked.

xcrun xcodebuild

In addition to running commands, xcrun can find binaries and show the path to an SDK:

xcrun --find clang
xcrun --sdk iphoneos --find pngcrush
xcrun --sdk macosx --show-sdk-path

Because xcrun executes in the context of the active Xcode version (as set by xcode-select), it is easy to have multiple versions of the Xcode toolchain co-exist on a single system.

Using xcrun in scripts and other external tools has the advantage of ensuring consistency across different environments. For example, Xcode ships with a custom distribution of Git. By invoking $ xcrun git rather than just $ git, a build system can guarantee that the correct distribution is run.

xcodebuild

Without passing any build settings, xcodebuild defaults to the scheme and configuration most recently used by Xcode.app:

However, everything from scheme, targets, configuration, destination, SDK, and derived data location can be configured:

xcodebuild -workspace NSHipster.xcworkspace -scheme "NSHipster"

There are six build actions that can be invoked in sequence:

build analyze archive archive installsrc install clean

genstrings

The genstrings utility generates a .strings file from the specified C or Objective-C source files. A .strings file is used for localizing an application in different locales, as described under “Internationalization” in Apple’s Cocoa Core Competencies.

genstrings -a \ /path/to/source/files/*.m

For each use of the NSLocalizedString macro in a source file, genstrings will append the key and comment into the target file. It’s up to the developer to then create a copy of that file for each targeted locale and have that file translated.

fr.lproj/Localizable.strings

1
2
3
4
5
6
/* No comment provided by engineer. */
"Username"="nom d'utilisateur";

/* {User First Name}'s Profile */
"%@'s Profile"="profil de %1$@";

ibtool

iprofiler

iprofiler measure an app’s performance without launching Instruments.app:

iprofiler -allocations -leaks -T 15s -o perf -a NSHipster

xed

This command simply opens Xcode.

xed NSHipster.xcworkspace

agvtool

agvtool can be used to version Xcode projects, by reading and writing the appropriate values in the Info.plist file.

摘录说明

摘录自《CFHipsterRef-Low-Level Programming on iOS & OS X》

中文参考: https://www.jianshu.com/p/2a351587f0ef

使用Core Animation可以提升动画帧率, 但不能保证动画性能. 特别是在OS X中, 需要考虑如何更高效的使用Core Animation. 要提升应用性能, 可以使用Instruments进行性能检测和问题追踪.

阅读全文 »

Core Animation使用操作对象实现图层的隐式动画. 操作对象遵循CAAction协议, 定义了在图层上执行时的相关行为. 所有的CAAnimation对象都实现了CAAction协议, 用于在图层属性发生变化时执行动画.

操作可以实现任意的自定义行为, 动画只是其中一种. 要实现自定义操作需要先创建操作对象, 并将其关联到图层.

阅读全文 »

Core Animation不仅支持基础动画和关键帧动画, 还提供了更高级的方式来控制多个动画同时或顺序执行. 除此之外, Core Animation还支持其他类型的动画, 比如视觉过渡动画或其他有趣的动画效果.

阅读全文 »

大部分情况下, 使用图层的最优方式都是将图层与视图进行关联. 但有时也可能会使用独立图层来优化性能, 或实现一些视图难以实现的功能. 在这些情况下, 就需要知道如何创建和管理图层树.

在OS X 10.8及更高版本中, 建议只使用图层支持视图, 并设置合适的图层重绘策略.

阅读全文 »

图层对象是Core Animation中所有操作的核心, 负责应用内容的可视化呈现. 在iOS中, 所有视图都是图层支持视图, 但在OS X中, 需要开发者为视图手动开启图层支持功能. 要使用图层支持视图, 就必须了解如何设置图层来实现想要的效果.

阅读全文 »