1. 程式人生 > >iPhone開發筆記

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

 

 

指標

對應指標,只需要記住,指標本身是一個變數,佔據48個位元組(機器位數/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];

寫了後,呼叫Adealloc, 執行到[c release] 又會呼叫C dealloc

又呼叫Adealloc 。。。

這樣會出現迴圈呼叫,直到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的時候,可以不使用其重用機制來實現特定的功能

 

XMLJSON解析

在對複雜的結構進行解析的時候,可以採用責任鏈模式,對特定模組進行封裝,這樣結構會清晰直觀。