天天看點

總結iOS開發當中一些特别注意的問題

1. mutable的資料類型,不能聲明為copy的屬性,如@property(nonatomic, copy) NSMutableArray *array;  @property(nonatomic, copy)  NSMutableDictionary *dict;這樣的聲明,然後再初始化的時候會有問題,self.array = [[NSMutableArray alloc] init];  其實它在記憶體中是NSArray的執行個體。是以一定得是mutablecopy.

2.如果用下面代碼出現一個模态ui,這個模态ui中有UITextField或UITextView的成員,那麼會出現keyboard, 如果發送resignFirstrRsponder鍵盤是不會消失的。

UINavigationController *nv = [[UINavigationController alloc] initWithRootViewController:searchVC];
    nv.modalPresentationStyle = UIModalPresentationFormSheet;
    [self presentModalViewController:nv animated:YES];
           

UINavigationController必須用Category的方法實作如下方法,才可以讓鍵盤消失

@interface UINavigationController (DismissKeyboard)
- (BOOL)disablesAutomaticKeyboardDismissal;
@end

@implementation UINavigationController (DismissKeyboard)

- (BOOL)disablesAutomaticKeyboardDismissal
{
    return NO;
}
@end
           

3.關于NSURLConnection中的delegate,下面是官網的說明:

Note: During a download the connection maintains a strong reference to the delegate. It releases that strong reference when the connection finishes loading, fails, or is canceled.
           

也就是說,delegate會被NSURLConnection擁有,在非arc情況下,下面的代碼也可以

//creates the handler object
MyHandlerClass *handler = [[MyHandlerClass alloc] init];
 
//creates the connection with handler as an autorelease object
[[NSURLConnection alloc] initWithRequest:request delegate:[handler autorelease]];

或

//creates the handler object
MyHandlerClass *handler = [[MyHandlerClass alloc] init];
 
//creates the connection with handler
[[NSURLConnection alloc] initWithRequest:request delegate:handler];
 
//releases handler object
[handler release];
           

MyHandlerClass中NSURLConnection的回調方法也會解發。

在arc情況下代碼如下:

//creates the handler object
MyHandlerClass *handler = [[MyHandlerClass alloc] init];
 
//creates the connection with handler
[[NSURLConnection alloc] initWithRequest:request delegate:handler];
           

4. static library中如果用了category, 那麼在引用庫的時候在other Link中加入-ObjC,-all_load,-force_load參考, 不過在xcode4.2後隻需要-Objc,參考

5. 如果項目工程中有c/c++的源碼,那麼在編寫項目Prefix.pch的時候一定得注意,如果下面這樣寫,編譯會出錯:

#ifdef __OBJC__
    #import <UIKit/UIKit.h>
    #import <Foundation/Foundation.h>
#endif
#import "AppDelegate.h"
           

修改方法為如下就正确了:

#ifdef __OBJC__
    #import <UIKit/UIKit.h>
    #import <Foundation/Foundation.h>
#import "AppDelegate.h"
#endif
           

因為這是一個預編譯頭檔案,是全局的,所有源檔案對其都是可見的,是以在c/c++源碼中也會引入,在c/c++源碼中引用objective_c的源碼就會出錯。

6. UIView 的addSubview:b方法,如果參數b是同一個指針,那麼無論調用多少次,它的subview中隻有一個b對象。 測試環境是iOS6, 記得iOS3好像沒有這個限制。

7. NSNumber能表示的數字整數部份精度隻有15位,其實是double的精度。如果需要更高的精度,請用NSDecimalNumber。

8. UITableView相關:

a.不要在- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath方法中調用

- (NSIndexPath *)indexPathForCell:(UITableViewCell *)cell,會引起循環調用。

9. 發送crash log 到郵箱

void uncaughtExceptionHandler(NSException *exception) {
    NSLog(@"CRASH: %@", exception);
    NSLog(@"Stack Trace: %@", [exception callStackSymbols]);
    // Internal or email error reporting
}

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    NSSetUncaughtExceptionHandler(&uncaughtExceptionHandler);
    // Normal launch stuff
}
           

10.加MKAnnotation到MKMapView的時候,MKAnnotation的coord取值範圍應是(-180, 180),  如果超出這個範圍, 将不能加成功。将不影響MKMapView中數組annotations的個數。

11.用數組的時候一定要先check index是否超出數組大小,否則很容易crash.

12. 聲明delegate請用weak類型,否則很容易memory leak.

13. 不要用NSManagedObject對像做為Model數庫,即使資料結構一樣的,也不要這樣做。比如UI A顯示查詢出來的結果, UI B裡delete了資料庫,那回到UI A就悲劇了。

14. CFTypeRef是沒有ARC的概念,是以需要自己管理記憶體。在一個方法中傳回一個CFTypeRef一定要注意在外面釋放記憶體,不然有記憶體leak.解決方法有兩種,一是在方法面面release傳回的CFTypeRef, 二是将方法傳回的值改為ObjC的類型,這樣就可以支援auto release.

15.在category方法中實作私有方法如- (void)viewDidAppear:(BOOL)animated,  然後在pushViewController

做動畫的時候會出現Unbalanced calls to begin/end appearance transitions的錯誤

16.系統在做動畫的時候盡量不要對UIWindow的subview進行操作。本人在pushViewController:vc的時候,在vc的viewDidLoad中對HUD進行了show/hide/show 操作,結果HUD不顯示。

17.在UITableViewController這類開發中,UITableView的UITableViewDelegate與UITableViewDataSource要用單獨的類來實作,這樣可以減輕viewController的負擔。UIViewController中是處理消息事件。在UITableView的UITableViewDataSource中千萬不要指定第一行顯示什麼,第二行顯示什麼,要用資料源控制該顯示什麼,也就是說應跟據資料源的類型來顯示。

18.重用機制一定要小心,比如UITableViewCell就可能是重用機制,是以在用UITableViewCell的時候,一定要恢複初始化再用。

19.不用的代碼應毫不猶豫的删掉。

20.如果項目依賴兩個庫,一個需要在Other Link Flags加-ObjC, 别一個是C/C++的庫,則不需要加,那麼就需要加一個-licucore來解決問題, 加-Objc是由于你的庫裡用到了Objc的文法如Category。

21.資料注意安全,無論存在NSUserDefault或SQLite中,都需要加密,否則就是明文。NSUserDefault其實就是一個plist檔案,如果在模拟器上運作則路徑是:~/Library/Application Support/iPhone Simulator/4.2/Applications/<APP_ID>/Library/Preferences 如果是真機運作,用itunes備份後則路徑是:~/Library/Application Support/MobileSync/Backup/<DEVICE_ID> where <DEVICE_ID>   SQLite則在Document目錄下.

22. UIView的UIViewAnimationWithBlocks方法,如果value沒有發生變化,那麼馬上就會回調finish block。

23. Category中不能添加屬性,如要添加,隻有通過Objc運作時加入變量的方法實作,這一點我以前的博文objc擴充機制有介紹。

24. 去掉duplicate symbol,在Other Link flag中加入-dead_strip

25. UITableView update在異步方法裡一點要注意,期間如果有改變tableData的條數的時候,有可能會crash

26. viewDidLoad中addObserver,  dealloc中removeObserver一定要注意,有可能viewDidLoad還未調用就調用了dealloc的情況會crash,所有最好加一個變量控制一下

27. coreData多線程操作的時候,一定要用多NSManagedObjectContext