天天看点

总结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