iOS学习笔记总结一(持续更新)

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:

一个View有GestureRecognizer又有按钮(或其它需要处理action event的控件)时,有时按钮不灵敏,解决办法:

-(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的动画

CALayer有默认动画效果,如果想完全用自已的,先要removeAllAnimations,再加上自设的animation。如果UIView上有一个CALayer,UIView的的内容没有更新,只有CALayer,则只重绘CALayer就可以,调用[layer setNeedsDisplay]。之前CALayer的内容会自动清除。比VC++高级,对于要更新的区域,不用手动擦除旧的

24、NSPredicate

1).从数组1中过滤出数组2中没有的对象
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的用法
A、简单比较
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、大小写比较
[c]表示忽略大小写,[d]表示忽略重音,可以在一起使用,如下:
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的背景

针对较旧的IOS,大概是IOS 4.3及以下:
@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

addSubView和removeFromSuperview是不支持animation的。要实现动画效果,可以利用alpha 这个变量。
// 显示:
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、

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值