很多东西不作系统整理记录就很容易遗忘,准备在这里对iPhone开发学习过程作一个回顾整理。
计划从以下几个内容展开:
1. objective c 语法
2. 常用控件
3. 一些传值方法分析,如通知
4. 疑难汇总
……
-----
9-21初步整理
回顾objective c
Objective c是运行时动态语言。
不同于C++的类
1. C++中可以直接使用 . 操作来访问public成员变量,objective c 中在外部进行访问的时候,只能够使用get set 方法
2. objective c 中的类对象在定义的时候,必须使用指针方式
即不能够直接采用这样的方式去定义 classC c ;
属性
可以用来设置自动生成get set方法
如果设置了属性,在dealloc方法中,使用self.xx = nil; 要好于[xx release];
1. 保持了alloc 和 release的平衡
2. 更加健壮,可以不用去关注成员变量的属性(retain 还是assign)
self.xx = nil 等效语句
xx 为retain [xx release]; xx = nil;
xx 为assign xx = nil;
在需要多次定义数据结构的时候,可以用一个程序来生成代码,减小工作量
如
cout << "- (void)dealloc\n{" << endl;
for (int i = 0; i < row; i++)
{
cout << " self." << fields[i] << " = nil;" << endl;
}
cout << "\n [super dealloc];\n}" << endl;
加锁
@synchronized (A) {} 的本质就是根据一个标志A对一段代码进行加锁,开始处lock(sign), 结束时 unlock(sign)
而不是对A进行加锁, A 如同Linux中称谓的互斥量
@synchronized (@”00”)
@synchronized (2222)
都是可以的
一般情况下,为了使这个互斥量的值更加的独特,常使用self, 等效于[ClassName class];
数据的传递
通知机制
典型的观察者模式
根据消息的原理,消息必须释放
// remove
[[NSNotificationCenter defaultCenter]removeObserver:self name:ANOTIFNAME object:nil];
发送消息 call
[[NSNotificationCenter defaultCenter] postNotificationName: ANOTIFNAME object:theValue];
//add
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(atestFun:) name: ANOTIFNAME object:nil];
通知的原理
通知中心 Menger 中根据通知名称创建数组或者树,字典等结构,这里以数组为例来说明
数组中存放对象的指针,当对象进行设置
[[NSNotificationCenter defaultCenter] postNotificationName: ANOTIFNAME object:theValue];
的时候添加到对应的数组中
<array name: ANOTIFNAME>
P1
P2
P3
</array>
<array name: ANOTIFNAME2>
</array>
调用的时候,找到对应的数组,对里面的指针(对象)执行其对应的方法,顺序或者多线程执行
如果对象已经释放了,如P1 已经是个野指针,call 的时候,进行方法调用,就会出现崩溃
全局变量
可以通过访问一个全局变量来实现数据的传递
其他方法
写文件,数据库
调试
Gdb的调试方法可以使用
打印查看变量的值
如
(gdb) p *((UIButton*)0x6d98ce0)
$1 = {
<UIControl> = {
<UIView> = {
<UIResponder> = {
<NSO
_backgroundView = 0x6dc0210,
_imageView = 0x0,
_titleView = 0x6dc00c0,
_initialized = 1 '\001',
(gdb) po 0x6dc00c0
<UIButtonLabel: 0x6dc00c0; frame = (15 6; 58 22); text = ' OK'; clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x6dc02d0>>
(gdb)
po vName 打印一个对象 po means print object
指针
对应指针,只需要记住,指针本身是一个变量,占据4或8个字节(机器位数/8),指针的值,即指针存放的内容,是另外一个变量的地址,可以通过这个地址对该变量进行访问操作
野指针
一个野指针错误提示
2012-06-08 17:09:14.418 appTest[64158:fe03] -[UITableViewCell atestFun:]: unrecognized selector sent to instance 0x6bceb20
2012-06-08 17:09:14.813 appTest[64158:fe03] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UITableViewCell atestFun:]: unrecognized selector sent to instance 0x6bceb20'
*** Call stack at first throw:
(
0 CoreFoundation 0x028bcbe9 __exceptionPreprocess + 185
1 libobjc.A.dylib 0x02a115c2 objc_exception_throw + 47
2 CoreFoundation 0x028be6fb -[NSObject(NSObject) doesNotRecognizeSelector:] + 187
3 CoreFoundation 0x0282e366 ___forwarding___ + 966
4 CoreFoundation 0x0282df22 _CF_forwarding_prep_0 + 50
5 Foundation 0x00d996c1 _nsnote_callback + 145
6 CoreFoundation 0x02894f99 __CFXNotificationPost_old + 745
7 CoreFoundation 0x0281433a _CFXNotificationPostNotification + 186
8 Foundation 0x00d8f266 -[NSNotificationCenter postNotificationName:object:userInfo:] + 134
9 Foundation 0x00d9b5a9 -[NSNotificationCenter postNotificationName:object:] + 56
10 appTest 0x003514d2 -[SelectCityViewController back] + 130
11 appTest 0x0035210c -[SelectCityViewController tableView:didSelectRowAtIndexPath:] + 236
12 UIKit 0x010a5794 -[UITableView _selectRowAtIndexPath:animated:scrollPosition:notifyDelegate:] + 1140
13 UIKit 0x0109bd50 -[UITableView _userSelectRowAtPendingSelectionIndexPath:] + 219
14 Foundation 0x00dae7f6 __NSFireDelayedPerform + 441
15 CoreFoundation 0x0289dfe3 __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ + 19
16 CoreFoundation 0x0289f594 __CFRunLoopDoTimer + 1220
17 CoreFoundation 0x027fbcc9 __CFRunLoopRun + 1817
18 CoreFoundation 0x027fb240 CFRunLoopRunSpecific + 208
19 CoreFoundation 0x027fb161 CFRunLoopRunInMode + 97
20 GraphicsServices 0x02d78268 GSEventRunModal + 217
21 GraphicsServices 0x02d7832d GSEventRun + 115
22 UIKit 0x0103e42e UIApplicationMain + 1160
23 appTest 0x00012919 main + 121
24 appTest 0x00012895 start + 53
)
terminate called throwing an exception
appTest[64158:fe03] -[UITableViewCell atestFun:]: unrecognized selector sent to instance 0x6bceb20
2012-06-08 17:09:14.813 appTest[64158:fe03] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UITableViewCell atestFun:]: unrecognized selector sent to instance 0x6bceb20'
*** Call stack at first throw:
(
0 CoreFoundation 0x028bcbe9 __exceptionPreprocess + 185
1 libobjc.A.dylib 0x02a115c2 objc_exception_throw + 47
2 CoreFoundation 0x028be6fb -[NSObject(NSObject) doesNotRecognizeSelector:] + 187
3 CoreFoundation 0x0282e366 ___forwarding___ + 966
4 CoreFoundation 0x0282df22 _CF_forwarding_prep_0 + 50
5 Foundation 0x00d996c1 _nsnote_callback + 145
6 CoreFoundation 0x02894f99 __CFXNotificationPost_old + 745
7 CoreFoundation 0x0281433a _CFXNotificationPostNotification + 186
8 Foundation 0x00d8f266 -[NSNotificationCenter postNotificationName:object:userInfo:] + 134
9 Foundation 0x00d9b5a9 -[NSNotificationCenter postNotificationName:object:] + 56
2012-06-09 10:14:39.823 appTest[65900:fe03] -[NSCFNumber atestFun:]: unrecognized selector sent to instance 0x6e639a0
2012-06-09 10:14:39.928 appTest[65900:fe03] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSCFNumber atestFun:]: unrecognized selector sent to instance 0x6e639a0'
*** Call stack at first throw:
典型的野指针问题
指针乱指
指针互指
委托,代理模式就是采用的这种方法进行的实现
关注下指针互指的情况
C
@property(nonatomic, assign) id p;
void dealloc
{
[p release];
...
}
----
A
C * c;
void dealloc
{
[c release];
…
}
--
C 的dealloc 方法中不应该写[p release];
写了后,调用A的dealloc, 执行到[c release] 又会调用C 的dealloc
又调用A的dealloc 。。。
这样会出现循环调用,直到stack空间不足,程序崩溃
在dealloc中测试发现 [p retainCount] [c retainCount] 的值都是1
(gdb) po [m_delegate retainCount]
0x1 does not appear to point to a valid object.
(gdb) po [self retainCount]
0x1 does not appear to point to a valid object.
从这里可以看出,对于互指的指针(代理),需要注意其使用
同时,可以看出 self.p = nil; 这种写法的好处,这样写不仅符合美学上对称(使用release的话,并没有与之对应的alloc),
而且不用关注变量的属性(retain还是assign),
写成 self.p = nil;是没有问题的,如果是assign, 就不会去调用release
内存泄露
多释放一个对象,可能会造成崩溃(其他地方再使用的时候出现野指针问题)
相对于这种夺命顽症,内存泄露则是一个慢性病,它会在内存泄露积累到一定程度的时候表现出来。少释放也是不可以的。
对于频繁调用的函数,需要格外注意其内存释放问题。
常用控件
UIButton
UIView
UIScrollView
UITableView
在使用tableView的时候,可以不使用其重用机制来实现特定的功能
XML与JSON解析
在对复杂的结构进行解析的时候,可以采用责任链模式,对特定模块进行封装,这样结构会清晰直观。