1、在ARC项目中使用非ARC框架或者类库的解决方案
只需在TARGETS里的Build Phases中,找到 Compile Sources,把涉及到非ARC的类后面加上 -fno-objc-arc标志(添加:-fobjc-arc,就可以让旧项目支持arc)。如果使用了arc,在@property声明中,用strong和weak代替相应的retain, copy,和assign.如下图:
2、retain和copy的区别
- copy: 建立一个索引计数为1的对象,然后释放旧对象
- retain:释放旧的对象,将旧对象的值赋予输入对象,再提高输入对象的索引计数为1
那上面的是什么意思呢?
Copy其实是建立了一个相同的对象,而retain不是:
比如一个NSString对象,地址为0×1111,内容为@”STR”
Copy到另外一个NSString之 后,地址为0×2222,内容相同,新的对象retain为1, 旧有对象没有变化
retain到另外一个NSString之 后,地址相同(建立一个指针,指针拷贝),内容当然相同,这个对象的retain值+1
也就是说,retain是指针拷贝,copy是内容拷贝。
3、什么时候用assign、什么时候用retain和copy呢
推荐做法是NSString用copy,delegate用assign(且一定要用assign,不要问为什么,只管去用就是了,
以后你会明白的),非objc数据类型,比如int,float等基本数据类型用assign(默认就是assign),
而其它objc类型,比如NSArray,NSDate用retain。
4、对于不同的viewcontroller之间数据的共享和处理
1)采用代理模式子viewcontroller设计 代理协议,定义协议接口,父viewcontroller 实现协议接口,实现子viewcontroller 退出时将相关数据更新到父视图。
2)采用ios的消息机制 父viewcontroller注册消息 子viewcontroller 发送消息,触发父viewcontroller的消息处理。
3)采用database做为数据中间的存储媒介,子viewcontroller将状态数据存入DB,父viewcontroller从DB获取数据更新view。
4)采用ios的NSDefault 存储
5)通过AppDelegate 中定义全局变量实现中间数据的存储。
5、代码混编
1)obj-c的编译器处理后缀为m的文件时,可以识别obj-c和c的代码,处理mm文件可以识别obj-c,c,c++代码,但cpp文件必须只能用c/c++代码,而且cpp文件include的头文件中,也不能出现obj-c的代码,因为cpp只是cpp
2) 在mm文件中混用cpp直接使用即可,所以obj-c混cpp不是问题
3)在cpp中混用obj-c其实就是使用obj-c编写的模块是我们想要的。
如果模块以类实现,那么要按照cpp class的标准写类的定义,头文件中不能出现obj-c的东西,包括#import cocoa的。实现文件中,即类的实现代码中可以使用obj-c的东西,可以import,只是后缀是mm。
如果模块以函数实现,那么头文件要按c的格式声明函数,实现文件中,c++函数内部可以用obj-c,但后缀还是mm或m。
总结: 只要cpp文件和cpp include的文件中不包含obj-c的东西就可以用了 ,cpp混用obj-c的关键是使用接口,而不能直接使用实现代码,实际上cpp混用的是obj-c编译后的o文件,这个东西其实是无差别的,所以可以用。而obj-c混用cpp就简单了,直接用就可以,因为obj-c的编译器支持啊
6、代码中字符串换行
NSString *string =@"ABCDEFGHIJKL" \
"MNOPQRSTUVsWXYZ";
7、判断一个字符串是否包含另一个字符串
[str1 rangeOfString:str2].length != 0 ? @"包含" : @"不包含"
8、没有用到类的成员变量的,都写成类方法
9、让程序退出后台时继续运行10分钟
在XXAppDelegate中增加:UIBackgroundTaskIdentifier bgTask;
- (void)applicationDidEnterBackground:(UIApplication *)application
{
bgTask = [application beginBackgroundTaskWithExpirationHandler:^{
// 10分钟后执行这里,应该进行一些清理工作,如断开和服务器的连接等
// ...
// stopped or ending the task outright.
[application endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
}];
if (bgTask == UIBackgroundTaskInvalid) {
NSLog(@"failed to start background task!");
}
// Start the long-running task and return immediately.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// Do the work associated with the task, preferably in chunks.
NSTimeInterval timeRemain = 0;
do{
[NSThread sleepForTimeInterval:5];
if (bgTask!= UIBackgroundTaskInvalid) {
timeRemain = [application backgroundTimeRemaining];
NSLog(@"Time remaining: %f",timeRemain);
}
}while(bgTask!= UIBackgroundTaskInvalid && timeRemain > 0); // 如果改为timeRemain > 5*60,表示后台运行5分钟
// done!
// 如果没到10分钟,也可以主动关闭后台任务,但这需要在主线程中执行,否则会出错
dispatch_async(dispatch_get_main_queue(), ^{
if (bgTask != UIBackgroundTaskInvalid)
{
// 和上面10分钟后执行的代码一样
// ...
// if you don't call endBackgroundTask, the OS will exit your app.
[application endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
}
});
});
}
- (void)applicationWillEnterForeground:(UIApplication *)application
{
// 如果没到10分钟又打开了app,结束后台任务
if (bgTask!=UIBackgroundTaskInvalid) {
[application endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
}
}
后台时,如果某些代码你不希望执行,可以加以下条件:
UIApplication *application = [UIApplication sharedApplication];
if( application.applicationState == UIApplicationStateBackground) {
return;
}
有的app虽然我们不允许通知,但还是会弹出消息,应该是设置了定时器,到某一时间就让程序后台运行一会,从服务器更新数据,然后显示出来。
10、_cmd
在Apple的官方介绍里看到轻描淡写的说了一句:“The _cmd variable is a hidden argument passed to every method that is the current selector”,其实说的就是_cmd在Objective-C的方法中表示当前方法的selector,正如同self表示当前方法调用的对象实例一样。
表示该方法的selector,可以赋值给SEL类型的变量,可以做为参数传递。
例如一个显示消息的方法:
-(void)ShowNotifyWithString:(NSString*)notifyString fromMethod:(SEL) originalMethod;
originalMethod就是调用这个方法的selector。 调用如下:
NSString *stmp = @"test";
[self ShowNotifyWithString:stmp fromMethod:_cmd];
比如,我们要打印当前要调用的方法,可以这样来写:
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(@"Current method: %@ %@",[self class],NSStringFromSelector(_cmd));
}
输出结果如下:TestingProject[570:11303] Current method: FirstViewController viewDidLoad
11、一个不停震动的方法
// 定义一个回调函数,震动结束时再次发出震动
void MyAudioServicesSystemSoundCompletionProc (SystemSoundID ssID,void *clientData)
{
BOOL* iShouldKeepBuzzing = clientData;
if (*iShouldKeepBuzzing) { AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
} else {
//Unregister, so we don't get called again...
AudioServicesRemoveSystemSoundCompletion(kSystemSoundID_Vibrate);
}
}
//以下为调用的代码:
BOOL iShouldKeepBuzzing = YES;
AudioServicesAddSystemSoundCompletion (
kSystemSoundID_Vibrate,
NULL,
NULL,
MyAudioServicesSystemSoundCompletionProc,
&iShouldKeepBuzzing );
AudioServicesPlaySystemSound (kSystemSoundID_Vibrate);
12、去掉app图标的发光效果
info.plist里增加Icon already includes gloss effects,值设为YES
13、UIImage:stretchableImageWithLeftCapWidth:topCapHeight
这个函数是UIImage的一个实例函数,它的功能是创建一个内容可拉伸,而边角不拉伸的图片,需要两个参数,第一个是不拉伸区域和左边框的宽度,第二个参数是不拉伸区域和上边框的宽度
有时图片模糊(blur)的原因:像素没有和devicepixel对齐.使用instrument的Core Animation可以检测这个,勾选"color misaligned images",如果图片显示为红紫色,就是没有对齐
14、UIPopoverController
如果是用presentPopoverFromBarButtonItem显示的,设备旋转时,popover可以自动调整位置;如果是用presentPopoverFromRect显示的, 需要present again
-(void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
[aPopover presentPopoverFromRect:targetRect.frame inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}
15、禁止textField和textView的复制粘贴菜单
-(BOOL)canPerformAction:(SEL)action withSender:(id)sender
{
if ([UIMenuController sharedMenuController]) {
[UIMenuController sharedMenuController].menuVisible = NO;
}
return NO;
}
16、UIGestureRecognizer相关
UIGestureRecognizer 是一个具体手势的基类,提供了较为简单的手势实现方式
The concrete subclasses of UIGestureRecognizer
are the following:
-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
CGPoint pt = [touch locationInView:baseView];
UIView *btn = [baseView viewWithTag:TAG_MYBTN];
CGPoint ptInbtn = [baseView convertPoint:pt toView:btn];
return ![btn pointInside:ptInbtn withEvent:nil];
}
实现某个view点一下就移除时,要防止移除两次。(此方法适用于希望GestureRecognizer只执行一次的情况)
-(void)OnTapViewTobeRemoved:(UITapGestureRecognizer *)sender
{
if (!sender.enabled) {
return;
}
sender.enabled = NO;
[sender.view removeFromSuperview];
}
17、如何进入软件在app store 的页面
先用iTunes Link Maker找到软件在访问地址,格式为itms-apps://ax.itunes.apple.com/...,然后
#define ITUNESLINK @"itms-apps://ax.itunes.apple.com/..."
NSURL *url = [NSURL URLWithString:ITUNESLINK];
if([[UIApplication sharedApplication] canOpenURL:url]){
[[UIApplication sharedApplication] openURL:url];
}
如果把上述地址中itms-apps改为http就可以在浏览器中打开了。可以把这个地址放在自己的网站里,链接到app store。
iTunes Link Maker地址:http://itunes.apple.com/linkmaker
18、SOMEVIEW显示一段时间后消失
[self performSelector:@selector(dismissView:) withObject:someview afterDelay:2];
这么写比用NSTimer代码少,不过哪种都行的,这里只是提供一种不同的方法
19、禁止程序运行时自动锁屏
[[UIApplication sharedApplication] setIdleTimerDisabled:YES];
20、改变UIAlertView背景
//UIAlertView默认是半透明的,会透出背景的内容,有时看着有些混乱。可以写个改变背景的方法changeBackground。
@interface UIAlertView (changeBK)
- (void)changeBackground;
@end
@implementation UIAlertView (changeBK)
- (void)changeBackground
{
for(UIView * v in [self subviews]){
if ([v isKindOfClass:[UIImageView class]]) {
UIImage *theImage = [UIImage imageNamed:@"AlertView.png"];
((UIImageView*)v).image = theImage;
break;
}
}
}
@end
在[alertView show]之后或willPresentAlertView:中调用即可。
// UIAlertView *alertView = [UIAlertView alloc] init ...
...
[alertView show];
[alertView changeBackground];
21、浮动提示
有时需要显示一个视图,几秒后再消失的功能,这个功能也可以写成category
@interface UIView (AutoRemove)
- (void)removeAfterDelay:(NSTimeInterval)time;
- (void)removeImediatly;
@end
@implementation UIView (AutoRemove)
- (void)removeAfterDelay:(NSTimeInterval)time
{
[self performSelector:@selector(removeFromSuperview) withObject:nil afterDelay:time];
}
- (void)removeImediatly
{
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(removeFromSuperview) object:nil];
[self removeFromSuperview];
}
@end
22、改变UITextField的背景
@interface UITextField (changeBK)
-(void)orangeBackground;
@end
@implementation UITextField (changeBK)
-(void)orangeBackground
{
self.background = [[UIImage imageNamed:@"fieldBK.png"] stretchableImageWithLeftCapWidth:5 topCapHeight:5];
}
@end
23、用于CALayer的动画
24、NSPredicate
NSArray *arrayFilter = [NSArray arrayWithObjects:@"abc1", @"abc2", nil];
NSArray *arrayContent = [NSArray arrayWithObjects:@"a1", @"abc1", @"abc4", @"abc2", nil];
NSPredicate *thePredicate = [NSPredicate predicateWithFormat:@"NOT (SELF in %@)", arrayFilter];
[arrayContent filterUsingPredicate:thePredicate];
这样arrayContent过滤出来的就是不包含arrayFilter中的所有item了。
2)、match的用法
NSString *match = @"imagexyz-999.png";
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF == %@", match];
NSArray *results = [directoryContents filteredArrayUsingPredicate:predicate];
B、match里like的用法(类似Sql中的用法)
NSString *match = @"imagexyz*.png";
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF like %@", match];
NSArray *results = [directoryContents filteredArrayUsingPredicate:predicate];
C、大小写比较
NSString *match = @"imagexyz*.png";
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF like[cd] %@", match];
NSArray *results = [directoryContents filteredArrayUsingPredicate:predicate];
D、使用正则
NSString *match = @"imagexyz-\\d{3}\\.png"; //imagexyz-123.png
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF matches %@", match];
NSArray *results = [directoryContents filteredArrayUsingPredicate:predicate];
总结:
1) 当使用聚合类的操作符时是可以不需要循环的
2)当使用单个比较类的操作符时可以一个循环来搞定
PS,例子 一中尝试使用[@"SELF CONTAINS %@", arrayFilter] 来过滤会挂调,因为CONTAINS时字符串比较操作符,不是集合操作符。
25、NSDictionary转NSMutableArry
NSMutableArray *objects = [myDictionary objectsForKeys:myKeys notfoundMarker:[NSNull null]]; // 这里不能用nil
26、改变UINavigationBar的背景
@implementation UINavigationBar (CustomImage)
- (void)drawRect:(CGRect)rect
{
UIImage *image = [[UIImage imageNamed: @"navBar"] stretchableImageWithLeftCapWidth:5 topCapHeight:0];
[image drawInRect:CGRectMake(0, 0.5, self.frame.size.width, self.frame.size.height)];
}
@end
针对所有版本IOS:
@implementation UINavigationBar (selBackground)
-(void)setToCustomImage
{
if ([[UIDevice currentDevice] systemVersion].floatValue >= 5.0 ) {
[self setBackgroundImage:[UIImage imageNamed:@"navBar"] forBarMetrics:UIBarMetricsDefault];
}
else
{
self.layer.contents = (id)[UIImage imageNamed:@"navBar"].CGImage;
}
}
@end
27、自IOS6.0,为了控制旋转,要给UINavigationController写个categary
@interface UINavigationController (Rotate)
@end
@implementation UINavigationController (Rotate)
- (NSUInteger)supportedInterfaceOrientations
{
return [self.topViewController supportedInterfaceOrientations];
}
- (BOOL)shouldAutorotate
{
return [self.topViewController shouldAutorotate];
}
@end
//对程序里所有不希望旋转的viewController,
- (BOOL)shouldAutorotate
{
return NO;
}
28、allSubviews, allApplicationViews, pathToView
NSArray *allSubviews(UIView *aView)
{
NSArray *results = [aView subviews];
for (UIView *eachView in [aView subviews])
{
NSArray *riz = allSubviews(eachView);
if (riz) results = [results arrayByAddingObjectsFromArray:riz];
}
return results;
}
// Return all views throughout the application
NSArray *allApplicationViews()
{
NSArray *results = [[UIApplication sharedApplication] windows];
for (UIWindow *window in [[UIApplication sharedApplication] windows])
{
NSArray *riz = allSubviews(window);
if (riz) results = [results arrayByAddingObjectsFromArray: riz];
}
return results;
}
// Return an array of parent views from the window down to the view
NSArray *pathToView(UIView *aView)
{
NSMutableArray *array = [NSMutableArray arrayWithObject:aView];
UIView *view = aView;
UIWindow *window = aView.window;
while (view != window)
{
view = [view superview];
[array insertObject:view atIndex:0];
}
return array;
}
29、键盘是带按钮的pickerview
UIView *keyBoardView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, CGRectGetWidth(self.view.bounds), 220)];
//键盘上方加工具条
UIToolbar * keyToolBar = [[UIToolbar alloc]initWithFrame:CGRectMake(0, 0, CGRectGetWidth(self.view.bounds), 38)];
[keyToolBar setTranslucent:NO];
[keyToolBar setTintColor:RGB(212, 214, 218)];
UIButton *closeButton = [UIButton buttonWithType:UIButtonTypeCustom];
closeButton.frame = CGRectMake(260, 5.0, 50.0f, 28.0);
closeButton.titleLabel.font = [UIFont fontWithName:FONT_ARIAL size:14.0];
[closeButton addTarget:self action:@selector(closeKeyboard:) forControlEvents:UIControlEventTouchUpInside];
[closeButton setTitle:T_CONFIRM forState:UIControlStateNormal];
[closeButton setBackgroundImage:[[UIImage imageNamed:@"selBack"] stretchableImageWithLeftCapWidth:8 topCapHeight:13]
forState:UIControlStateNormal];
[keyToolBar addSubview:closeButton];
[keyBoardView addSubview:keyToolBar];
[keyToolBar release];
UIPickerView *picker = [[UIPickerView alloc] initWithFrame:CGRectMake(0, CGRectGetMaxY(keyToolBar.frame), 0, 200)];
picker.showsSelectionIndicator = YES;
picker.dataSource = self;
picker.delegate = self;
[keyBoardView addSubview:picker];
self.pickerView = picker;
[picker release];
companyTF.inputView = keyBoardView;
[keyBoardView release];
30、addSubview不支持Animation
// 显示:
floatView = [[FloatNotifyView alloc] initWithFrame:CGRectMake(35, 315, 250, 50)];
floatView.tag = TAG_FLOAT_NOTIFY;
floatView.alpha = 0;
[self.view addSubview:floatView];
[UIView animateWithDuration:0.2f
delay:0
options:UIViewAnimationOptionCurveEaseIn
animations:^{
floatView.alpha = 1;
}
completion:^(BOOL finished) {
}];
[floatView release];
// 消失:
-(void)hideInfo
{
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(hideInfo) object:nil];
[UIView animateWithDuration:0.4f
delay:0
options:UIViewAnimationOptionCurveEaseOut
animations:^{
self.alpha = 0;
}
completion:^(BOOL finished) {
[self removeFromSuperview];
}];
}
31、给keyboard增加删除按钮
数字键盘没有关闭键盘的按钮,以下代码把”Done”拆成两个按钮了。
(后来觉得这个办法太麻烦了,不如在键盘上加一行工具栏,工具栏上加关闭按钮)[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillShowOnDelay:)
name:UIKeyboardWillShowNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillHide:)
name:UIKeyboardWillHideNotification
object:nil];
- (void)keyboardWillShowOnDelay:(NSNotification *)notification
{
[self performSelector:@selector(keyboardWillShow:) withObject:nil afterDelay:0];
}
- (void)keyboardWillShow:(NSNotification *)notification
{
UIView *foundKeyboard = nil;
UIWindow *keyboardWindow = nil;
for (UIWindow *testWindow in [[UIApplication sharedApplication] windows])
{
if (![[testWindow class] isEqual:[UIWindow class]])
{
keyboardWindow = testWindow;
break;
}
}
if (!keyboardWindow) return;
for (UIView *possibleKeyboard in [keyboardWindow subviews])
{
//NSLog(@"%@",[possibleKeyboard description]);
//iOS3
if ([[possibleKeyboard description] hasPrefix:@"<UIKeyboard"])
{
foundKeyboard = possibleKeyboard;
break;
}
else
{
// iOS 4 sticks the UIKeyboard inside a UIPeripheralHostView.
if ([[possibleKeyboard description]hasPrefix:@"<UIPeripheralHostView"]) {
BOOL didFound = NO;
for (UIView *tmpView in [possibleKeyboard subviews]) {
if ([[tmpView description] hasPrefix:@"<UIKeyboard"]) {
foundKeyboard = tmpView;
didFound = YES;
break;
}
}
if (didFound) {
break;
}
}
}
}
if (foundKeyboard)
{
UIButton *backButton = [UIButton buttonWithType:UIButtonTypeCustom];
backButton.tag = 110;
backButton.frame = CGRectMake(215, 163, 52, 53);
backButton.adjustsImageWhenHighlighted = NO;
UIImage *darkImage = [[UIImage imageNamed:@"dark.png"] stretchableImageWithLeftCapWidth:5 topCapHeight:0];
UIImage *darkCornerImage = [[UIImage imageNamed:@"darkCorner.png"] stretchableImageWithLeftCapWidth:5 topCapHeight:0];
UIImage *brightImage = [[UIImage imageNamed:@"bright.png"] stretchableImageWithLeftCapWidth:5 topCapHeight:0];
UIImage *brightCornerImage = [[UIImage imageNamed:@"brightCorner.png"] stretchableImageWithLeftCapWidth:5 topCapHeight:0];
[backButton setBackgroundImage:darkImage forState:UIControlStateNormal];
[backButton setBackgroundImage:brightImage forState:UIControlStateHighlighted];
[backButton addTarget:self action:@selector(backButton:)forControlEvents:UIControlEventTouchUpInside];
[backButton setTitle:@"删除" forState:UIControlStateNormal];
[backButton setTitleColor:[UIColor blackColor] forState:UIControlStateHighlighted];
[foundKeyboard addSubview:backButton];
UIButton *doneButton = [UIButton buttonWithType:UIButtonTypeCustom];
doneButton.tag = 111;
doneButton.frame = CGRectMake(215+52, 163, 53, 53);
doneButton.adjustsImageWhenHighlighted = NO;
[doneButton setBackgroundImage:darkCornerImage forState:UIControlStateNormal];
[doneButton setBackgroundImage:brightCornerImage forState:UIControlStateHighlighted];
[doneButton addTarget:self action:@selector(doneButton:)forControlEvents:UIControlEventTouchUpInside];
[doneButton setTitle:@"隐藏" forState:UIControlStateNormal];
[doneButton setTitleColor:[UIColor blackColor] forState:UIControlStateHighlighted];
[foundKeyboard addSubview:doneButton];
}
}
- (void)keyboardWillHide:(NSNotification *)notification
{
UIView *foundKeyboard = nil;
UIWindow *keyboardWindow = nil;
for (UIWindow *testWindow in [[UIApplication sharedApplication] windows])
{
if (![[testWindow class] isEqual:[UIWindow class]])
{
keyboardWindow = testWindow;
break;
}
}
if (!keyboardWindow) return;
for (UIView *possibleKeyboard in [keyboardWindow subviews])
{
//NSLog(@"%@",[possibleKeyboard description]);
//iOS3
if ([[possibleKeyboard description] hasPrefix:@"<UIKeyboard"])
{
foundKeyboard = possibleKeyboard;
break;
}
else
{
// iOS 4 sticks the UIKeyboard inside a UIPeripheralHostView.
if ([[possibleKeyboard description]hasPrefix:@"<UIPeripheralHostView"]) {
BOOL didFound = NO;
for (UIView *tmpView in [possibleKeyboard subviews]) {
if ([[tmpView description] hasPrefix:@"<UIKeyboard"]) {
foundKeyboard = tmpView;
didFound = YES;
break;
}
}
if (didFound) {
break;
}
}
}
}
if (foundKeyboard)
{
UIView *back = [foundKeyboard viewWithTag:110];
[back removeFromSuperview];
UIView *done = [foundKeyboard viewWithTag:111];
[done removeFromSuperview];
}
}
32、设置线宽
如果是retina屏,lineWidth设为1,实际显示的宽度是2个像素,这里进行一下处理:
#define SETLINEWIDTH(ctx,w)CGContextSetLineWidth(ctx, w/[UIScreen mainScreen].scale)33、简化代码用的define
#define SETRGBSTROKECOLOR(ctx,R,G,B) CGContextSetRGBStrokeColor(context, R/255.0, G/255.0, B/255.0, 1.0)
#define SETRGBFILLCOLOR(ctx,R,G,B) CGContextSetRGBFillColor(context, R/255.0, G/255.0, B/255.0, 1.0)
#define _ADDOBSERVER(TITLE, SELECTOR) [[NSNotificationCenter defaultCenter] addObserver:self selector:SELECTOR name:TITLE object:nil]
#define _REMOVEOBSERVER(id) [[NSNotificationCenter defaultCenter] removeObserver:id]
#define _POSTNOTIFY(TITLE,OBJ,PARAM) [[NSNotificationCenter defaultCenter] postNotificationName:TITLE object:OBJ userInfo:PARAM]
34、比较版本号
NSString *currSysVer = [[UIDevice currentDevice] systemVersion];
if ([currSysVer compare:minRequirement options:NSNumericSearch] != NSOrderedAscending)
{
return YES;
}else{
return NO;
}
35、时间相关
NSDate需要设置calendar,使用不方便也因为服务器传过来的是time_t格式,所以我在客户端对时间的操作主要用的C语言的方法。
需要注意的是,有的函数不是线程安全的,也就是说在同一个范围内调用多次时,需要调用线程安全的版本,这样的函数有:
localtime_r
asctime_r
ctime_r
gmtime_r
localtime_r
另外,可以直接给struct tm各成员变量赋值,例如(注意顺序)
struct tm tmStart ={second,minute,hour,day, mon, year};
struct tm的各成员是不能的加减的,因为超过了各变量的范围,可能出错,需要先转成time_t,再加减相应的时间struct tm* tmp = localtime(&Time);
asctime(tmp)
time_t now;
time(&now);
struct tm * tmNow = localtime(&now);
struct tm tm = {0,nMinute,nHour,tmNow->tm_mday, tmNow->tm_mon, tmNow->tm_year};
time_t _time = mktime(&tm);
time_t tt1 = status.time;
time_t tt2 = status2.time;
struct tm tm1 = {0};
struct tm tm2 = {0};
localtime_r(&tt1, &tm1);
localtime_r(&tt2, &tm2);
36、用#ifdefined控制不同版本协议的使用
- (void)Req_Login_Wh_Proc:(id)reqMsg
{
#if defined(EDITION_0_009_)
[self Req_Login_Wh_0_009_Proc:reqMsg];
#elif defined (EDITION_0_010_) || defined(EDITION_0_011_)
[self Req_Login_Wh_0_011_Proc:reqMsg];
#else
[self Req_Login_Wh_0_012_Proc:reqMsg];
#endif
}
37、