iPhone開發筆記
很多東西不作系統整理記錄就很容易遺忘,準備在這裡對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解析
在對複雜的結構進行解析的時候,可以採用責任鏈模式,對特定模組進行封裝,這樣結構會清晰直觀。