Gowhich

Durban's Blog

写程序遇到 Bug 并不可怕,大部分的问题,通过简单的 Log 或者 代码分析并不难找到原因所在。但是在 Objective-C 编程中遇到 EXC_BAD_ACCESS 问题的时候,通过简单常规的手段很难发现问题。
写程序遇到 Bug 并不可怕,大部分的问题,通过简单的 Log 或者 代码分析并不难找到原因所在。但是在 Objective-C 编程中遇到 EXC_BAD_ACCESS 问题的时候,通过简单常规的手段很难发现问题。这篇文章,给大家介绍一个常用的查找 EXC_BAD_ACCESS 问题根源的方法。
首先说一下 EXC_BAD_ACCESS 这个错误,可以这么说,90%的错误来源在于对一个已经释放的对象进行release操作。
Objective-C 这段代码有三个致命问题:1、内存泄露;2、错误释放;3、造成 EXC_BAD_ACCESS 错误。

1, NSString* s = [[NSString alloc]initWithString:@”This is a test string”]; 创建了一个 NSString Object,随后的 s = [s substringFromIndex:[s rangeOfString:@”a”].location]; 执行后,导致创建的对象引用消失,直接造成内存泄露。

2,错误释放。[s release]; 这个问题,原因之一是一个逻辑错误,以为 s 还是我们最初创建的那个 NSString 对象。第二是因为从 substringFromIndex:(NSUInteger i) 这个方法返回的 NSString 对象,并不需要

我们来释放,它其实是一个被 substringFromIndex 方法标记为 autorelease 的对象。如果我们强行的释放了它,那么会造成 EXC_BAD_ACCESS 问题。

3, EXC_BAD_ACCESS。由于 s 指向的 NSString 对象被标记为 autorelease, 则在 NSAutoreleasePool 中已有记录。但是由于我们在前面错误的释放了该对象,则当 [pool drain] 的时候,NSAutoreleasePool

又一次的对它记录的 s 对象调用了 release 方法,但这个时候 s 已经被释放不复存在,则直接导致了 EXC_BAD_ACCESS问题。

查看更多的Console信息

工作区->Excuteables->双击其分组下的文件->Arguments设置运行参数

1: 为工程运行时加入 NSZombieEnabled 环境变量,则在 EXC_BAD_ACCESS 发生时,XCode 的 Console 会打印出问题描述。

2:加入 MallocStackLogging 来启用malloc记录

做如下设置:

Project -> Edit active executable ->Argument

添加如下四个参数

NSDebugEnabled

NSZombieEnabled

MallocStackLogging

MallocStackLoggingNoCompact

来源:http://blog.csdn.net/sjzsp/article/details/6386987

做iOS 程序开发时经常用遇到 EXC_BAD_ACCESS 错误导致 Crash,出现这种错误时一般 Xcode 不会给我们太多的信息来定位错误来源,只是在应用 Delegate 上留下像Thread 1: Program received signal:”EXC_BAD_ACCESS”,让问题无从找起。

比如你对已释放的对象发送消息时就会出现,EXC_BAD_ACCESS,再如release 的对象再 release,release 那些autorelease 的对象等也会报这样的错。默认设置下 Xcode 不会给你定位具体是哪一行代码,不该去使用已释放的对象,或者release 用错了。

比如下面这段代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
- (void)drawRect:(CGRect)rect
{
[self setClearsContextBeforeDrawing: YES];

CGContextRef context = UIGraphicsGetCurrentContext();

//画背景线条------------------
CGColorRef backColorRef = [UIColor blackColor].CGColor;
CGFloat backLineWidth = 2.f;
CGFloat backMiterLimit = 0.f;

CGContextSetLineWidth(context, backLineWidth);//主线宽度
CGContextSetMiterLimit(context, backMiterLimit);//投影角度

CGContextSetShadowWithColor(context, CGSizeMake(3, 5), 8, backColorRef);//设置双条线

CGContextSetLineJoin(context, kCGLineJoinRound);

CGContextSetLineCap(context, kCGLineCapRound );

CGContextSetBlendMode(context, kCGBlendModeNormal);

CGContextSetStrokeColorWithColor(context, [UIColor whiteColor].CGColor);

CGFloat x = self.charW;
CGFloat y = self.chartH;

//绘制纵向的坐标线 和 值
for (int i=0; i<vDesc.count; i++) {

CGPoint bPoint = CGPointMake(30, y);
CGPoint ePoint = CGPointMake(x, y);

UILabel *label = [[UILabel alloc]initWithFrame:CGRectMake(0, 0, 30, 30)];
//纵坐标起始点的y坐标
//纵坐标起始点的x坐标
int vX = 15;
int vY = 30;
[label setCenter:CGPointMake(bPoint.x-vX, bPoint.y-vY)];

[label setTextAlignment:NSTextAlignmentCenter];
[label setBackgroundColor:[UIColor clearColor]];
[label setTextColor:[UIColor whiteColor]];
[label setText:[vDesc objectAtIndex:i]];
[self addSubview:label];

CGContextMoveToPoint(context, bPoint.x, bPoint.y-30);
CGContextAddLineToPoint(context, ePoint.x, ePoint.y-30);

y -= 50;//间隔

}

//绘制横向的坐标线 和 值
for (int i=0; i<array.count-1; i++) {
//横向值的y坐标
CGFloat hY = chartH - 20;
UILabel *label = [[UILabel alloc]initWithFrame:CGRectMake(i*vInterval+10, hY, 60, 30)];
label.transform = CGAffineTransformMakeRotation(0.5);
[label setTextAlignment:NSTextAlignmentCenter];
[label setBackgroundColor:[UIColor clearColor]];
[label setTextColor:[UIColor whiteColor]];
label.numberOfLines = 1;
label.adjustsFontSizeToFitWidth = YES;
label.minimumScaleFactor = 1.0f;
[label setText:[hDesc objectAtIndex:i]];

[self addSubview:label];
}


//画点线条------------------
CGColorRef pointColorRef = [UIColor colorWithRed:24.0f/255.0f green:116.0f/255.0f blue:205.0f/255.0f alpha:1.0].CGColor;
CGFloat pointLineWidth = 1.5f;
CGFloat pointMiterLimit = 5.0f;

CGContextSetLineWidth(context, pointLineWidth);//主线宽度
CGContextSetMiterLimit(context, pointMiterLimit);//投影角度


CGContextSetShadowWithColor(context, CGSizeMake(3, 5), 8, pointColorRef);//设置双条线

CGContextSetLineJoin(context, kCGLineJoinRound);

CGContextSetLineCap(context, kCGLineCapRound );

CGContextSetBlendMode(context, kCGBlendModeNormal);

CGContextSetStrokeColorWithColor(context, [UIColor whiteColor].CGColor);

//绘图
CGPoint p1 = [[array objectAtIndex:0] CGPointValue];
//坐标的基础坐标 y值
int yBase = chartH - 30;
CGContextMoveToPoint(context, 30, yBase);
for (int i = 1; i<[array count]; i++)
{
p1 = [[array objectAtIndex:i] CGPointValue];
CGPoint goPoint = CGPointMake(p1.x-20, yBase-p1.y*vInterval/20);
CGContextAddLineToPoint(context, goPoint.x, goPoint.y);;

//添加触摸点
UIButton *bt = [UIButton buttonWithType:UIButtonTypeCustom];

[bt setBackgroundColor:[UIColor redColor]];

[bt setFrame:CGRectMake(0, 0, 10, 10)];

[bt setCenter:goPoint];

[bt addTarget:self
action:@selector(btAction:)
forControlEvents:UIControlEventTouchUpInside];

[self addSubview:bt];
}
CGContextStrokePath(context);

}

上面的代码就会出现EXC_BAD_ACCESS 错误:
错误提示是:

CoreGraphics`CGColorGetAlpha:
0x31c1d780: vmov.i32d0, #0x0
0x31c1d784: cmp r0, #0
0x31c1d786: itttt ne
0x31c1d788: ldrne r1, [r0, #28]
0x31c1d78a: addne.wr0, r0, r1, lsl #2
0x31c1d78e: ldrne r0, [r0, #28]<-
0x31c1d790: vmovne d0, r0, r0
0x31c1d794: vmov r0, s0
0x31c1d798: bx lr
0x31c1d79a: nop

会定位到红色的那一行,这个实在是让人头痛,不过还是有解决办法的。

NSZombieEnabled环境变量可以帮我们的忙,就是当 设置NSZombieEnabled环境变量后,一个对象销毁时会被转化为_NSZombie,设置NSZombieEnabled后,当你向一个已经释 放的对象发送消息,这个对象就不会向之前那样Crash或者产生一个难以理解的行为,而是放出一个错误消息,然后以一种可预测的可以产生debug断点的 方式消失, 因此我们就可以找到具体或者大概是哪个对象被错误的释放了。

对 Xcode 设置了NSZombieEnabled 之后,

错误提示是:

*** -[Not A Type retain]: message sent to deallocated instance 0x2009b480

应该是内存泄露的问题。

修改代码后,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
- (void)drawRect:(CGRect)rect
{
[self setClearsContextBeforeDrawing: YES];

CGContextRef context = UIGraphicsGetCurrentContext();

//画背景线条------------------
// CGColorRef backColorRef = [UIColor blackColor].CGColor;
CGColorRef backColorRef = (__bridge CGColorRef)([UIColor blackColor]);
CGFloat backLineWidth = 2.f;
CGFloat backMiterLimit = 0.f;

CGContextSetLineWidth(context, backLineWidth);//主线宽度
CGContextSetMiterLimit(context, backMiterLimit);//投影角度

CGContextSetShadowWithColor(context, CGSizeMake(3, 5), 8, backColorRef);//设置双条线

CGContextSetLineJoin(context, kCGLineJoinRound);

CGContextSetLineCap(context, kCGLineCapRound );

CGContextSetBlendMode(context, kCGBlendModeNormal);

CGContextSetStrokeColorWithColor(context, [UIColor whiteColor].CGColor);

CGFloat x = self.charW;
CGFloat y = self.chartH;

//绘制纵向的坐标线 和 值
for (int i=0; i<vDesc.count; i++) {

CGPoint bPoint = CGPointMake(30, y);
CGPoint ePoint = CGPointMake(x, y);

UILabel *label = [[UILabel alloc]initWithFrame:CGRectMake(0, 0, 30, 30)];
//纵坐标起始点的y坐标
//纵坐标起始点的x坐标
int vX = 15;
int vY = 30;
[label setCenter:CGPointMake(bPoint.x-vX, bPoint.y-vY)];

[label setTextAlignment:NSTextAlignmentCenter];
[label setBackgroundColor:[UIColor clearColor]];
[label setTextColor:[UIColor whiteColor]];
[label setText:[vDesc objectAtIndex:i]];
[self addSubview:label];

CGContextMoveToPoint(context, bPoint.x, bPoint.y-30);
CGContextAddLineToPoint(context, ePoint.x, ePoint.y-30);

y -= 50;//间隔

}

//绘制横向的坐标线 和 值
for (int i=0; i<array.count-1; i++) {
//横向值的y坐标
CGFloat hY = chartH - 20;
UILabel *label = [[UILabel alloc]initWithFrame:CGRectMake(i*vInterval+10, hY, 60, 30)];
label.transform = CGAffineTransformMakeRotation(0.5);
[label setTextAlignment:NSTextAlignmentCenter];
[label setBackgroundColor:[UIColor clearColor]];
[label setTextColor:[UIColor whiteColor]];
label.numberOfLines = 1;
label.adjustsFontSizeToFitWidth = YES;
label.minimumScaleFactor = 1.0f;
[label setText:[hDesc objectAtIndex:i]];

[self addSubview:label];
}


//画点线条------------------
// CGColorRef pointColorRef = [UIColor colorWithRed:24.0f/255.0f green:116.0f/255.0f blue:205.0f/255.0f alpha:1.0].CGColor;
CGColorRef pointColorRef = (__bridge CGColorRef)[UIColor colorWithRed:24.0f/255.0f green:116.0f/255.0f blue:205.0f/255.0f alpha:1.0];
CGFloat pointLineWidth = 1.5f;
CGFloat pointMiterLimit = 5.0f;

CGContextSetLineWidth(context, pointLineWidth);//主线宽度
CGContextSetMiterLimit(context, pointMiterLimit);//投影角度


CGContextSetShadowWithColor(context, CGSizeMake(3, 5), 8, pointColorRef);//设置双条线

CGContextSetLineJoin(context, kCGLineJoinRound);

CGContextSetLineCap(context, kCGLineCapRound );

CGContextSetBlendMode(context, kCGBlendModeNormal);

CGContextSetStrokeColorWithColor(context, [UIColor whiteColor].CGColor);

//绘图
CGPoint p1 = [[array objectAtIndex:0] CGPointValue];
//坐标的基础坐标 y值
int yBase = chartH - 30;
CGContextMoveToPoint(context, 30, yBase);
for (int i = 1; i<[array count]; i++)
{
p1 = [[array objectAtIndex:i] CGPointValue];
CGPoint goPoint = CGPointMake(p1.x-20, yBase-p1.y*vInterval/20);
CGContextAddLineToPoint(context, goPoint.x, goPoint.y);;

//添加触摸点
UIButton *bt = [UIButton buttonWithType:UIButtonTypeCustom];

[bt setBackgroundColor:[UIColor redColor]];

[bt setFrame:CGRectMake(0, 0, 10, 10)];

[bt setCenter:goPoint];

[bt addTarget:self
action:@selector(btAction:)
forControlEvents:UIControlEventTouchUpInside];

[self addSubview:bt];
}
CGContextStrokePath(context);

}

一切正常了。成功了!

如何设置 NSZombieEnabled 呢,在 Xcode3 和 Xcode4 下设置不一样,Xcode4 下设置很简单。

Xcode3 下 NSZombieEnabled 设置方法如下:

  • 在XCode左边那个Groups& Files栏中找到Executables,双击其中的一项,或者右键Get Info;
  • 切换到Arguments
  • 这里一共有两个框,在下面那个Variables to be set in theenvironment:点+号添加一项,Name里填NSZombieEnabled,Value填Yes,要保证前面的钩是选中的。
    Xcode4 下设置 NSZombieEnabled 的方法:
    你可以点击 Xcode4 菜单 Product -> Edit Scheme-> Arguments, 然后将点击”加号”, 将 NSZombieEnabled 参数加到Environment Variables 窗口中, 后面的数值写上 ”YES”.
    或者在 Xcode4 菜单 Product -> EditScheme -> Diagnostics 设置窗口中直接勾上Enable ZombieObjects 即可,Xcode 可用 cmd+shift+< 进到这个窗口。

讲Cocoa技术十分专业的网站之一,下面的链接详细讲了讲NSZombieEnable的原理。http://www.cocoadev.com/index.pl?NSZombieEnabled
苹果官方的Mac OS X Debugging Magic,详细讲述了最为一个高级苹果程序员应该具备的调试技巧 http://developer.apple.com/library/mac/#technotes/tn2004/tn2124.html
其实还可以在Instruments中开启NSZombie选项,这样就可以在Instruments中直接查看crash时候的callstack了:http://www.markj.net/iphone-memory-debug-nszombie/
最后提醒NSZombieEnabled只能在调试的时候使用,千万不要忘记在产品发布的时候去掉,因为NSZombieEnabled不会真正去释放dealloc对象的内存,一直开启后果可想而知,自重!

iOS开发中NSDateFormatter是一个很常用的类,用于格式化NSDate对象,支持本地化的信息。与时间相关的功能还可能会用到NSDateComponents类和NSCalendar类等。本文主要列出NSDateFormatter常见用法。

NSDate对象包含两个部分,日期(Date)和时间(Time)。格式化的时间字符串主要也是针对日期和时间的。[以下代码中开启了ARC,所以没有release。]

基础用法

1
2
3
4
5
6
7
NSDate* now = [NSDate date];
NSDateFormatter* fmt = [[NSDateFormatter alloc] init];
fmt.dateStyle = kCFDateFormatterShortStyle;
fmt.timeStyle = kCFDateFormatterShortStyle;
fmt.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US"];
NSString* dateString = [fmt stringFromDate:now];
NSLog(@"%@", dateString);

打印输出:10/29/12, 2:27 PM
这使用的系统提供的格式化字符串,通过 fmt.dateStyle 和 fmt.timeStyle 进行的设置。实例中使用的参数是 kCFDateFormatterShortStyle,此外还有:

1
2
3
4
5
6
7
typedef CF_ENUM(CFIndex, CFDateFormatterStyle) {    // date and time format styles
kCFDateFormatterNoStyle = 0, // 无输出
kCFDateFormatterShortStyle = 1, // 10/29/12, 2:27 PM
kCFDateFormatterMediumStyle = 2, // Oct 29, 2012, 2:36:59 PM
kCFDateFormatterLongStyle = 3, // October 29, 2012, 2:38:46 PM GMT+08:00
kCFDateFormatterFullStyle = 4 // Monday, October 29, 2012, 2:39:56 PM China Standard Time
};

自定义区域语言

如上实例中,我们使用的是区域语言是 en_US,指的是美国英语。如果我们换成简体中文,则代码是:

1
fmt.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"zh_CN"];

则对应的输出为:

1
2
3
4
5
6
7
typedef CF_ENUM(CFIndex, CFDateFormatterStyle) {    // date and time format styles
kCFDateFormatterNoStyle = 0, // 无输出
kCFDateFormatterShortStyle = 1, // 12-10-29 下午2:52
kCFDateFormatterMediumStyle = 2, // 2012-10-29 下午2:51:43
kCFDateFormatterLongStyle = 3, // 2012年10月29日 GMT+0800下午2时51分08秒
kCFDateFormatterFullStyle = 4 // 2012年10月29日星期一 中国标准时间下午2时46分49秒
};

世界通用的区域语言代码,详见 International Components for Unicode (ICU), http://userguide.icu-project.org/formatparse/datetime

自定义日期时间格式

NSDateFormatter提供了自定义日期时间的方法,主要是通过设置属性 dateFormat,常见的设置如下:

1
2
3
4
5
6
NSDate* now = [NSDate date];
NSDateFormatter* fmt = [[NSDateFormatter alloc] init];
fmt.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"zh_CN"];
fmt.dateFormat = @"yyyy-MM-dd'T'HH:mm:ss";
NSString* dateString = [fmt stringFromDate:now];
NSLog(@"%@", dateString);

打印输出:2012-10-29T16:08:40
除了上面列出的,还可以指定很多格式,详见http://userguide.icu-project.org/formatparse/datetime。
结合设置Locale,还可以打印出本地化的字符串信息。

1
2
3
4
5
6
NSDate* now = [NSDate date];
NSDateFormatter* fmt = [[NSDateFormatter alloc] init];
fmt.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"zh_CN"];
fmt.dateFormat = @"yyyy-MM-dd a HH:mm:ss EEEE";
NSString* dateString = [fmt stringFromDate:now];
NSLog(@"\n%@", dateString);

自定义月份星期等字符

NSDateFormatter中同样提供了相应的方式,去修改这些字符。一般情况下,使用相应区域语言下面的默认字符就OK了。但是你的确有这个需求,那么也是可以办到的。相应的方法非常多,如下:
Managing AM and PM Symbols
– AMSymbol
– setAMSymbol:
– PMSymbol
– setPMSymbol:

Managing Weekday Symbols
– weekdaySymbols
– setWeekdaySymbols:
– shortWeekdaySymbols
– setShortWeekdaySymbols:
– veryShortWeekdaySymbols
– setVeryShortWeekdaySymbols:
– standaloneWeekdaySymbols
– setStandaloneWeekdaySymbols:
– shortStandaloneWeekdaySymbols
– setShortStandaloneWeekdaySymbols:
– veryShortStandaloneWeekdaySymbols
– setVeryShortStandaloneWeekdaySymbols:

Managing Month Symbols
– monthSymbols
– setMonthSymbols:
– shortMonthSymbols
– setShortMonthSymbols:
– veryShortMonthSymbols
– setVeryShortMonthSymbols:
– standaloneMonthSymbols
– setStandaloneMonthSymbols:
– shortStandaloneMonthSymbols
– setShortStandaloneMonthSymbols:
– veryShortStandaloneMonthSymbols
– setVeryShortStandaloneMonthSymbols:

Managing Quarter Symbols
– quarterSymbols
– setQuarterSymbols:
– shortQuarterSymbols
– setShortQuarterSymbols:
– standaloneQuarterSymbols
– setStandaloneQuarterSymbols:
– shortStandaloneQuarterSymbols
– setShortStandaloneQuarterSymbols:

Managing Era Symbols
– eraSymbols
– setEraSymbols:
– longEraSymbols
– setLongEraSymbols:

iOS中心有图标的相关说明,地址为:https://developer.apple.com/library/ios/#documentation/UserExperience/Conceptual/ MobileHIG/IconsImages/IconsImages.html#//apple_ref/doc/uid/TP40006556-CH14-SW16

这里解释一下,方便自己查看:

iOS图标尺寸一览

iPhone专用程序:

图标名称 大小 圆角 用途 必需
Icon.png 57 X 57 10px 用于程序商店和在iPhone/iPod Touch中显示 必需
[email protected] 114 X 114 20px Icon.png的高清模式
Icon-Small.png 29 X 29 20px 用于设置和Spotlight搜索
[email protected] 58 X 58 8px Icon-Small.png的高清模式

ipad专用程序:

图标名称 大小 圆角 用途 必需
Icon-72.png 72 X 72 20px 用于在iPad桌面中显示 必需
Icon-50.png 50 X 50 ? 用于iPad中的Spotlight搜索
Icon-29.png 29 X 29 10px 设置页面

通用程序:

图标名称 大小 圆角 用途 必需
Icon-72.png 72 X 72 20px 用于在iPad桌面中显示 必需
Icon.png 57 X 57 10px 用于程序商店和在iPhone/iPod Touch中显示 必需
Icon-50.png 50 X 50 10px 用于iPad中的Spotlight搜索
Icon-29.png 29 X 29 20px 用于设置和Spotlight搜索

取消图标上的高光

系统会默认会在图标上自动加上半透明的高光半圆,如果我们不想要这个效果或者图标本身已经包含了这个高光效果,我们可以在项目配置里把系统的高光功能取消掉:
xcode3.2x建的项目:
在info plist里加一个配置项,key为“Icon already includes gloss and bevel effects”, 类型为bool,然后打上钩就,这样系统就不会自动加高光;
xcode4建的项目:
在项目target的summary标签页下找到App Icons项,在“Prerendered”打上钩
再找到“Icon files (iOS 5)”项目(如果有的话),展开,把里面的“Icon already includes gloss effects”也设置成“YES”:这样程序中的高光效果就取消了。

itunes connect上的图标

我们在itunes connect网站上创建应用时也要求上传图标,上传后 itunes connect也会给图标加上高光效果。这不用担心,如果我们的程序已经取消了高光效果,在程序上传后,网站上图标的高光效果也会自动取消掉的。

iOS设置真机上的应用程序名称:

步骤如下:

在工程文件下面的XXXX-Info.plist,修改 Bundle display name即可

哈哈,好简单

为iPad和iPhone程序增加启动画面非常简单,基本思路就是增加启动图片资源Default.png即可,只是要根据不同的分辨率和旋转方向需要有不同的图片尺寸。

目前的iOS设备有三种不同的分辨率:

iPad 768x1024
iPhone4 640x960
iPhone 320x480
如果一个程序,既要支持iPad又要支持iPhone,那么它需要包含下面几个图片:

Default-Portrait.png iPad专用竖向启动画面 768x1024或者768x1004
Default-Landscape.png iPad专用横向启动画面 1024x768或者1024x748
Default-PortraitUpsideDown.png iPad专用竖向启动画面(Home按钮在屏幕上面),可省略 768x1024或者768x1004
Default-LandscapeLeft.png iPad专用横向启动画面(可省略), 1024x768或者1024x748
Default-LandscapeRight.png iPad专用横向启动画面(可省略), 1024x768或者1024x748
Default.png iPhone默认启动图片,如果没有提供上面几个iPad专用启动图片,则在iPad上运行时也使用Default.png(不推荐) 320x480或者320x460
[email protected] iPhone4启动图片640x960或者640x920
为了在iPad上使用上述的启动画面,你还需要在xxxx_info.plist中加入key(根据下拉菜单中的可选项选择):

UISupportedInterfaceOrientationsSupported interface orientations
同时,为其加入值(根据下拉菜单中的可选项选择):

UIInterfaceOrientationPortrait 或 Portrait (bottom home button)
UIInterfacOrientationPortraitUpsideDown 或 Portrait (top home button)
UIInterfaceOrientationLandscapeLeft 或 Landscape (left home button)
UIInterfaceOrientationLandscapeRight 或 Landscape (right home button)

状态栏尺寸的获取方式:

1
2
3
4
CGRect statusFrame;
statusFrame = [[UIApplication sharedApplication] statusBarFrame];
CGFloat statusHeight = statusFrame.size.height;
CGFloat statusWidth = statusFrame.size.width;

先执行如下命令:

1
lsof -i:端口号

会有类似下面的结果:

1
2
3
COMMAND     PID       USER   FD   TYPE             DEVICE SIZE/OFF NODE NAME
WebProces 42624 davidzhang 5u IPv4 0x907152bbf7b2a875 0t0 TCP localhost:64438->localhost:radan-http (ESTABLISHED)
WebProces 42624 davidzhang 10u IPv4 0x907152bbf7b64a05 0t0 TCP localhost:64439->localhost:radan-http (ESTABLISHED)

然后执行:

1
kill -9 42624

结束进程就搞定了

实例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
/* glue.c -- 使用##运算符 */
#include <stdio.h>
#define XNAME(n) x ## n
#define PRINT_XN(n) printf("x" #n " = %d\n", x ## n)

int main(void)
{
int XNAME(1) = 14;
int XNAME(2) = 20;
PRINT_XN(1);
PRINT_XN(2);
return 0;
}

运行结果如下:

1
2
x1 = 14
x2 = 20

代码示例:

1
2
3
4
5
6
7
8
9
10
/* subst.c -- 在字符串中进行替换 */
#include <stdio.h>
#define PSOR(x) printf("The square of " #x " is %d\n", ((x)*(x)))

int main(void){
int y = 5;
PSOR(y);
PSOR(2 + 4);
return 0;
}

运行结果为:

1
2
The square of y is 25
The square of 2 + 4 is 36
0%