iOS项目开发中的知识点与问题收集整理①

前言部分

注:本文并非绝对原创 大部分内容摘自 http://blog.csdn.net/hengshujiyi/article/details/20943045

文中有些方法可能已过时并不适用于现在的开发环境。

1、Search Bar 怎样去掉背景的颜色(storyboard里只能设置background颜色,可是发现clear Color无法使用)。

其实在代码里还是可以设置的,那就是删除背景view
 [[self.searchBar.subviews objectAtIndex:0] removeFromSuperview];

2、NSDate 详解: 

 1 字母  日期或时间元素    表示     示例
2 G Era 标志符 Text AD
3 y 年 Year 1996 96
4 M 年中的月份 Month July; Jul; 07
5 w 年中的周数 Number 27
6 W 月份中的周数 Number 2
7 D 年中的天数 Number 189
8 d 月份中的天数 Number 10
9 F 月份中的星期 Number 2
10 E 星期中的天数 Text Tuesday; Tue
11 a Am/pm 标记 Text PM
12 H 一天中的小时数(0-23) Number 0
13 k 一天中的小时数(1-24) Number 24
14 K am/pm 中的小时数(0-11) Number 0
15 h am/pm 中的小时数(1-12) Number 12
16 m 小时中的分钟数 Number 30
17 s 分钟中的秒数 Number 55
18 S 毫秒数 Number 978
19 z 时区 General time zone Pacific Standard Time; PST; GMT-08:00
20 Z 时区 RFC 822 time zone -0800

[注意]在开发中,如果使用年月日,用NSDateFormatter setFormat :@"yyyy-MM-dd",如果是使用小时和分钟,设置为:"HH:mm",切记不要设置“HH-mm”,这样会出错的。 
举例:

 1 //创建一个时间对象
2 NSData * date = [NSDate date];
3 //打印时间
4 NSLog(@"today is %@",date);
5
6 //再获取的时间date减去24小时的时间(昨天的这个时候)
7 NSDate *yesterday = [NSDate dateWithTimeIntervalSinceNow:-(24*60*60)];
8 NSLog(@"yesterday is %@",yesterday);//打印昨天的时间
9
10 /*字符串换成时间*/
11 //设置一个字符串的时间
12 NSString *datestring = [NSString stringWithFormat:@"1999-09-03"];
13 //想要设置自己想要的格式,可以用nsdateformatter这个类,这里是初始化
14 NSDateFormatter * dm = [[NSDateFormatter alloc]init];
15 //指定输出的格式 这里格式必须是和上面定义字符串的格式相同,否则输出空
16 [dm setDateFormat:@"yyyy-MM-dd"];
17 //把字符串的时间转换成Date对象,用dateFromString方法
18 NSDate * newdate = [dm dateFromString:datestring];
19 //输出
20 NSLog(@"newdate is %@",newdate);
21
22
23 /*把时间转换成字符串*/
24 //把Date对象转换成String对象 用stringFromDate方法
25 NSString * datestring2 = [dm stringFromDate:newdate];
26 //打印
27 NSLog(@"datestring2 is %@",datestring2);

3、 如果使用 UTTabviewCell,设置其accessory样式为:Detail Disclosure ,就是在每一个cell右边设置一个detail button。如果这样的操作是使用storyboard,进行的,它会要求你给每一个你cell设置indentifier,然后你会在以下方法内设置 重用indentfier,别忘记加上一句话,否则编译运行时可能会弹出: cell未实例化

iOS项目开发中的知识点与问题收集整理①

4、
在开发项目中,有时有这样的需求:运行程序,登陆界面是一个*的ViewController,只是摆放几个TextField和button,点击后
跳转到孩子选择或其它选择界面,点击选项后进入我们的主界面:这个时候,在登陆界面作跳转时,会有好多的方法,如果使用storyboard,就比较方便
了,设置一个segue,跳转代码中:

[self
PerformSegueWithIdentifier:@"targetViewController",self];
就可以了,可是我想实例化想要跳转的控制器,然后设置某一属性的值,这样跳转后控制器获取那个属性,就会得到值了,可是这样做会有一个问题: 

界面控制器如果使用了navigatorViewController,并且是其RootViewController,等到在主界面设置功能,点击某一
功能,想push到一个新页面时,问题就来了,你会发现毫无反应,没有报错,只是segue无法跳转。后来终于找到原因:就是我在登陆控制器跳转时没有使
用segue的方法,而是用代码self.storyboard,加载一个新类,具体原理目前还没有搞明白,先把出问题的代码记录下来,回头补之:
iOS项目开发中的知识点与问题收集整理①

代码这样做,会导致其后无法使用navigatorViewController做push跳转

5、
开发过程中,我们通过http请求,后台返回json数据,而有时数据里某一字段的值为null~,然后我们把此值赋值给
NSArray,NSdictionary,或是NSString,然后我们会判断此值为null时,所做的处理,而通常惯性思维判断时我们都会
写:if(dict == nil)或是if(dict == Nil)或是if(dict == NULL)再或是if(dict isEqual
nil),我们发现,都不好用,根本没有起到判断的作用~后来我才发现,原来不能这样来判断。   

简单点说,就是当字典,数组为null时,后台打印的输出结果是这样:
iOS项目开发中的知识点与问题收集整理①

然后,我们需要在代码判断时利用[NSNull null]来判断,具体如:
iOS项目开发中的知识点与问题收集整理①

isEqual:[NSNull null] 就搞定了,nsarray也是同样的道理。

控制台打印:str=(null) 代表着 字符串或数组或字典是一个空指针,(而非空字符串)判断的时候,直接用:

if(str == nil)就可以了。如下图所示:
iOS项目开发中的知识点与问题收集整理①

而控制台打印:str =  <null>,代表着这是一个空字符串,赋值为空,指针是存在的,只是内容为空,这种判断需要使用:

if(str is equal [NSNull null ]) ,因为在ios上,内容为空不能简单的判断str==null(null 在ios上得用[NSNull null])
iOS项目开发中的知识点与问题收集整理①

一般这种情况是,服务器那边是null,直接返回@"null"的字符串,这样在ios这边不好判断,最好跟后台沟通,如果遇到null值,返回@"",好做判断

6、给uiview设置圆角样式  

只需在加载时,添加这样的话就可以了:

testView.layer.cornerRadius = 6;
        testView.layer.masksToBounds = YES;
注意,需要 import <QuartzCore/QuartzCore.h> 导入,否则,不能识别cornerRadius和masksToBounds。 
uiview设置背景图片:

 [theMainView setBackgroundColor: [UIColor colorWithPatternImage: [UIImage imageNamed: @"bg.png"]]];  

imageName 缓存,下面方法不缓存

1 NSString *thePath = [[NSBundle mainBundle] pathForResource:@"default" ofType:@"jpeg"];
2 UIImage *prodImg = [[UIImage alloc] initWithContentsOfFile:thePath"];
3 controller.productImg.image = prodImg;
4 [prodImg release];

7、隐藏键盘的两种方法  

1-1Did End On Exit 调用下面事件当点击键盘return得时候就会隐藏键盘

 1 - (IBAction)textFieldShouldReturn:(UITextField *)textField {
2 //[sender resignFirstResponder];
3 if (textField == chi) {
4 [chi resignFirstResponder];
5 double m=[chi.textdoubleValue]/3.003;
6 double f=m *3.2808;
7 meter.text=[[NSStringalloc] initWithFormat:@"%.4f",m];
8 feet.text=[[NSStringalloc] initWithFormat:@"%.4f",f];
9 }
10 if (textField == meter) {
11 [meter resignFirstResponder];
13 }
14 if (textField == feet) {
15 [feet resignFirstResponder];
16 }
17 }

1-2 点击屏幕得时候隐藏键盘

1 -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
2 UITouch *touch=[[event allTouches] anyObject];
3 if (touch.tapCount >=1) {
4 [chi resignFirstResponder];
5 [meter resignFirstResponder];
6 [feet resignFirstResponder];
7 }
8 }

1-2 的方法相当于屏幕任何位置的点击事件(除了各组件的点击处)可以在这个方法里执行要隐藏或remove的view。

1-3 隐藏键盘 方法二

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
[self.view endEditing:YES];
}  

8、UITextField密文显示输入内容: 

iOS项目开发中的知识点与问题收集整理①

只需要在TextField属性中的Secure(安全的)勾选上或者设置 passWordTextField.secureTextEntry=YES; 就可以了。显示apple默认的密文显示方式。

9、通过系统自带的NSPredicate使用正则表达式。(在TextField中) 

1 NSString *regex =[NSString stringWithFormat:@"^1(3[4-9]|5[012789]|8[2378]|47)\\d{8}$"];
2 NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@",regex];
3 BOOL isMatch = [predicate evaluateWithObject:editPhoneField.text];

10、项目设置应用程序显示名称:  

1, 在项目的Supporting Files下寻找infoPlist.strings文件,打开后会看到一片空白(英文默认是跟随项目名称显示)。此时,可以就地添加一句代 码:CFBundleDisplayName="爱贝通";这样的话,无论手机设置英文语言还是中文语言,应用程序都会显示设置的名称。

2,为了国际化而言,我们最好创建一个chinese专有的infoPlist.strings文件。
iOS项目开发中的知识点与问题收集整理①

如上图所示,添加一个中文的plist

然后打开添加代码:
iOS项目开发中的知识点与问题收集整理①

这个时候,大功告成。部署在模拟器或真机中吧,你的手机设置(中/英)文语言,它就会调用相应的配置文件。

11、更改Xcode的缺省公司名 

1 //  testAppDelegate.m
2 // test
3 //
4 // Created by gaohf on 11-5-24.
5 // Copyright 2011 __MyCompanyName__. All rights reserved.

在终端中执行以下命令:

defaults write com.apple.Xcode PBXCustomTemplateMacroDefinitions '{"ORGANIZATIONNAME" = "COMPANY";}'  

执行后效果

1 //  testAppDelegate.m
2 // test
3 //
4 // Created by gaohf on 11-5-24.
5 // Copyright 2011 COMPANY. All rights reserved.

12、在有uinavigation,uitoolbar的情况下,如何添加一个全屏的 uiview (一般是作为显示一个进度框,任何区域无法触摸而使用)   

只需要在要添加view时侯这样写:
 [[UIApplication sharedApplication].keyWindow addSubview:waitingview];

这样,直接把waitingview添加到了uiWindow上,而不是self.view上。再次运行,会发现屏幕全部区域都已经遮挡住了。

13、
使用了storyboard,运行程序模拟器显示黑屏,这是由于,操作不当,获取点击了例如 
navigationViewController属性种的in init
ViewController选项,然后重置了当前进入程序后的首界面,解决办法就是选择入口界面,属性种重新勾选此选项。   

StoryboardApp[8593:207]
Failed to instantiate the default view controller for
UIMainStoryboardFile 'MainStoryboard' - perhaps the designated entry
point is not set?
StoryBoard中没有一个view controller设置了Initial Scene。您需要选择一个view conroller作为story board的第一个界面:
iOS项目开发中的知识点与问题收集整理①

14、如何给uiNavigationBar 设置背景颜色或是自定义图片?   

在项目中添加如下代码: 
//设置背景颜色:

1 UIColor *itemcolor = [UIColor colorWithRed:100.0f/255.0f green:176.0f/255.0f blue:0.0f/255.0f alpha:0.3f];
2 self.navigationController.navigationBar.tintColor = itemcolor;

//设置自定义的图片:

[self.navigationController.navigationBar setBackgroundImage:[UIImage imageNamed:@"navbg.png"] forBarMetrics:UIBarMetricsDefault];  

5.0以上,api有了上面setBackgroundImage的方法,可以直接设置,如果项目需要适配5.0以下版本的设备,最好加一个判读,是否有此函数,

有则设置,没有就通过drawRect方法设置。 另外:设置背景图片无法匹配backButton或rightButtonItem,所以返回按钮或右边自定义的

Bar button Item需要自行处理。

15、如何给uiview设置背景图片?    

在storyboard或xib中,添加一个uiview,属性设置栏一般都有设置背景颜色,样式,透明度alpha,但是没有提供设置image,只有在imageview中才有,

所以,要想设置背景图片,只能在代码中设置,如下:

[leftNaviView setBackgroundColor:[UIColor colorWithPatternImage:[UIImage imageNamed:@"pabb_leftnaviview_bg.png"]]];  

这样,背景就可以变成想要的图片了。另外,设置大小:
 [leftNaviView setFrame:CGRectMake(9, 60, 120, 250)];

效果图:
iOS项目开发中的知识点与问题收集整理①

16、如何在项目用代码打开AppStore软件(也就是访问appstore) 

1 //以下是通过id打开此软件的评价
2 //int m_appleID = 576337094;
3 //NSString *str = [NSString stringWithFormat:
4 //@"itms-apps://ax.itunes.apple.com/WebObjects/MZStore.woa/wa/viewContentsUserReviews?type=Purple+Software&id=%d",
5 //m_appleID ];
6
7 //以下是通过appstore链接到自己应用在商店的位置
8 NSString *url = [NSString stringWithFormat:@"http://itunes.apple.com/cn/app/huo-xing-she-xin-dian/id549425594?l=en&mt=8"];
9 [[UIApplication sharedApplication] openURL:[NSURL URLWithString:url]];

把以上代码直接拷贝到想要实现点击跳转的操作方法内就可以了,通过appID,随意可以通过appstore打开应用,直接用url就可以链接到了。

很简单,一般都用在检查更新的时候。

17、如何代码实现点击http://www.kaka.com或400-800-400或message实现跳转safari,phone或message?

只需要在相应的代码中写入:

1、调用 电话phone

[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"tel://4008008288"]];

2、调用自带 浏览器 safari

[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"http://www.abt.com"]];

3、调用 自带mail

[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"mailto://admin@abt.com"]];

4、调用 SMS

[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"sms://800888"]];

5,跳转到系统设置相关界面

1 [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"prefs:root=WIFI"]];

其中,发短信,发Email的功能只能填写要发送的地址或号码,无法初始化发送内容,如果想实现内容的话,还需要更复杂一些,

实现其各自的委托方法。

若需要传递内容可以做如下操作:

 1 //加入:MessageUI.framework
2 #import <MessageUI/MFMessageComposeViewController.h>
3
4 //实现代理:MFMessageComposeViewControllerDelegate
5
6 //调用sendSMS函数
7 //内容,收件人列表
8 - (void)sendSMS:(NSString *)bodyOfMessage recipientList:(NSArray *)recipients
9 {
11 MFMessageComposeViewController *controller = [[[MFMessageComposeViewController alloc] init] autorelease];
13 if([MFMessageComposeViewController canSendText])
15 {
17 controller.body = bodyOfMessage;
19 controller.recipients = recipients;
21 controller.messageComposeDelegate = self;
23 [self presentModalViewController:controller animated:YES];
25 }
27 }
28
29 // 处理发送完的响应结果
30 - (void)messageComposeViewController:(MFMessageComposeViewController *)controller didFinishWithResult:(MessageComposeResult)result
31 {
32 [self dismissModalViewControllerAnimated:YES];
34 if (result == MessageComposeResultCancelled)
35 NSLog(@"Message cancelled")
36 else if (result == MessageComposeResultSent)
37 NSLog(@"Message sent")
38 else
39 NSLog(@"Message failed")
40 }

发送邮件的为:

 1 //导入MFMailComposeViewController
2 #import <MessageUI/MFMailComposeViewController.h>
3 //实现代理:MFMailComposeViewControllerDelegate
4
5 //发送邮件
6 -(void)sendMail:(NSString *)subject content:(NSString *)content{
7 MFMailComposeViewController *controller = [[[MFMailComposeViewController alloc] init] autorelease];
9 if([MFMailComposeViewController canSendMail])
11 {
13 [controller setSubject:subject];
15 [controller setMessageBody:content isHTML:NO];
17 controller.mailComposeDelegate = self;
19 [self presentModalViewController:controller animated:YES];
21 }
22 }
23
24 //邮件完成处理
25 -(void)mailComposeController:(MFMailComposeViewController *)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError *)error{
27 [self dismissModalViewControllerAnimated:YES];
29 if (result == MessageComposeResultCancelled)
30 NSLog(@"Message cancelled");
31 else if (result == MessageComposeResultSent)
32 NSLog(@"Message sent");
33 else
34 NSLog(@"Message failed");
35
36 }
37

默认发送短信的界面为英文的,解决办法为:在.xib 中的Localization添加一組chinese

18、注册设置应用程序访问用户手机发送推送消息,(弹出Alertview)

1 [[UIApplication sharedApplication] registerForRemoteNotificationTypes:
2 (UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert)];

19、轻松自定义复选框按钮 

 1 -(void)checkboxClick:(UIButton *)btn
2 {
3 btn.selected = !btn.selected;
4 }
5
7 - (void)viewDidLoad {
8 UIButton *checkbox = [UIButton buttonWithType:UIButtonTypeCustom];
10 CGRect checkboxRect = CGRectMake(135,150,36,36);
11 [checkbox setFrame:checkboxRect];
12
13 [checkbox setImage:[UIImage imageNamed:@"checkbox_off.png"] forState:UIControlStateNormal];
14 [checkbox setImage:[UIImage imageNamed:@"checkbox_on.png"] forState:UIControlStateSelected];
15
16 [checkbox addTarget:self action:@selector(checkboxClick:) forControlEvents:UIControlEventTouchUpInside];
17 [self.view addSubview:checkbox];
18 }

20、程序中获取软件的版本号和app名称  

应用程序的名称和版本号等信息都保存在mainBundle的infoDictionary字典中,用下面代码可以取出来。

1 NSDictionary* infoDict =[[NSBundle mainBundle] infoDictionary];
2 NSString* versionNum =[infoDict objectForKey:@"CFBundleVersion"];//版本名称
3 NSString*appName =[infoDict objectForKey:@"CFBundleDisplayName"];//app名称
1 <p style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; font-family: Menlo;">
2 <span style="color: #703daa">NSString</span>
3 * versionShortString = [infoDict <span style="color: rgb(61, 29, 129);">objectForKey</span>:
4 <span style="color: #d12f1b">@"CFBundleShortVersionString"</span>];//标识应用程序发布版本号
5 </p>
6 NSString*text =[NSString stringWithFormat:@"%@ %@",appName,versionNum,
7 <span style="font-family: Menlo; font-size: 11px; white-space: pre; ">versionShortString</span>];

此version 为工程info下的Bundle version字段值:value可以随意定义。
CFBundleVersion,标识(发布或未发布)的内部版本号。这是一个单调增加的字符串,包括一个或多个时期分隔的整数。
CFBundleShortVersionString

标识应用程序的发布版本号。该版本的版本号是三个时期分隔的整数组成的字符串。第一个整数代表重大修改的版本,如实现新的功能或重大变化的修订。第二个整
数表示的修订,实现较突出的特点。第三个整数代表维护版本。该键的值不同于“CFBundleVersion”标识。
   图片里的 Version 对应的就是CFBundleShortVersionString (发布版本号 如当前上架版本为1.1.0  之后你更新的时候可以改为1.1.1)
   Build 对应的是 CFBundleVersion(内部标示,用以记录开发版本的,每次更新的时候都需要比上一次高 如:当前版本是11  下一次就要大于11 比如 12,13 ....10000)

21、如何使屏幕一直保持唤醒状态?(就是不自动黑屏) 

比如,如果我们做一个播放视频的功能时,想在播放的时候,不会自动进入屏保(黑屏)
只要在代码里加入这一行:
 [[UIApplication sharedApplication] setIdleTimerDisabled:YES];  
 
 当然,在想要黑屏的时候还需要把它设置为NO(比如视频播放完毕时),不然屏幕会在此软件运行下一直亮着。

22、一直以来的疑问:在Xcode中,有时候在类名称后边带有M或C等标示,不知道为何意。如下图所示: 

iOS项目开发中的知识点与问题收集整理①

表示在版本控制中,自上一次提交以来,文件做了修改。貌似只有在带有版本控制的项目代码中才会显示。

23、有关ios上屏幕旋转,view设置Frame的相关问题(ios5)。   

屏幕旋转一共有4个相关属性(旋转方向):

UIInterfaceOrientationLandscapeLeft

UIInterfaceOrientationLandscapeRight

UIInterfaceOrientationPortrait

UIInterfaceOrientationPortraitUpsideDown

前两个是横屏时的状态,后两个是正常状态(Portrait)和上下颠倒(UpsideDown)时的状态。

【注意:Left和Right两个左右模拟器旋转时移动的方向正好是相反的,但移动后Home的方向,就如下图所示】

具体见下图:
iOS项目开发中的知识点与问题收集整理①

其中涉及到两个方法,在ViewController中默认会实现这个方法:

1 - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
2 {
3 //除了不允许旋转屏幕后:上下颠倒,其余方向都运行旋转
4 //如果想都运行,可以直接返回YES,或都不允许NO
5 return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
6
7 }

这 个方法是声明此ViewController所运行屏幕旋转的方向,一共4种类型,全部允许返回YES,上图所示除了不允许上下颠倒,其余都可以。【注 意,项目设置Supported Device Orientations 所支持的屏幕旋转类型并不影响此方法的设置,也就是说,哪怕Support只支持Portrait,方法里设置UpsideDown,此 ViewController也会实现上下颠倒旋转的】

第二个方法,是我们比较常用的,也就是在设备即将以某个方向旋转之前,我们在其状态(方向)设置组件或view的Frame,bound,等需要改变的属性时所用到的方法。

 1 -(void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration{
2 //屏幕旋转到横屏时
4 if (UIInterfaceOrientationIsLandscape(toInterfaceOrientation)) {
5 myMapview.frame = CGRectMake(0,0,480, 300);
6 }
7 //屏幕旋转到竖屏时
8 else{//== else if(UIInterfaceOrientationIsPortrait(toInterfaceOrientation))
9 myMapview.frame = CGRectMake(0, 0, 320,460);
10 }
11
12 }

所有旋转屏幕后需要改变组件尺寸属性的设置都可以在这个方法里面实现。

【注意,以上两个方法,在最新的ios6貌似已经不提倡使用了,除非要适应旧设备,新的旋转屏幕的相关方法可以网络搜索一下】

http://blog.csdn.net/zzfsuiye/article/details/8251060  IOS6屏幕旋转详解(自动旋转、手动旋转、兼容IOS6之前系统)
http://blog.csdn.net/huifeidexin_1/article/details/7826159  ios旋转屏幕总结 详细教程
http://blog.csdn.net/xiaoyun8822/article/details/8213738 Ios5(三)屏幕的旋转和大小设置;
以上为参考教程

24、Xcode编译警告和错误解决方法:  

1
Application windows are expected to have a root view controller at the
end of application launch解决方法:在ios5以上版本,应用程序加载时,需要一个 root view
controller ,所以需要编写代码_rootViewController = [[RootViewController alloc]
init];self.window.rootViewController =
_rootViewController;此问题大多是在Xib或Storyboard下操作ViewController时不小心连接
RootViewController 的底层View所导致的,检查删除没有作用的view连接线,或是Clean
(Command+Shift+K),再运行。

25、如何设置视图(view)在最上层?或是view1和view2交换?

情景再现: 

们在storyboard的一个视图里添加了一个view1用作快捷功能导航;然后在对应的viewController里实例化了一个Mapview的
地图view2,大小是整个屏幕,这样一来,就把我们在storyboard中添加的view1覆盖了,这个时候,我们想把view1在地图view2的
上面,该怎么做?

简而言之就是window中subview的交换。

首先通过:NSLog(@"subviews:%@",self.view.subviews); 这个我们可以看到当前下所有的subview(NSArray类型)如下图所示:
iOS项目开发中的知识点与问题收集整理①

可以看到一共有3个view:UILabel 地图view2,添加的view1

我们现在要做的就是把后两者对调一下,所以在self.view 中寻找一下看有没有replace相关的方法
iOS项目开发中的知识点与问题收集整理①

就是这个方法,第一个参数是要进行调换的地图view2,第二个参数是调换后显示的view1。

[self.viewexchangeSubviewAtIndex:1 withSubviewAtIndex:2];

因为通过log打印,我们已经知道Mapview在第一个下标的位置,view1在第二个下标的位置。
iOS项目开发中的知识点与问题收集整理①

iOS项目开发中的知识点与问题收集整理①
大功告成。记住这个方法:self.view exchangeSubviewAtIndex:withSubviewAtIndex:];

26、如何隐藏UINavigationBar  

有的时候,我们的视图使用了Navigation Controller ,但是主界面(rootviewcontroller)或其它push进入的界面 想使用一个全屏的view,就是说,不显示顶部的navigationBar,这个时候,就需要我们来隐藏了。

 1 //隐藏NavigationBar
2 -(void) viewWillAppear:(BOOL)animated{
3 [self.navigationControllersetNavigationBarHidden:YES animated:YES]; //设置隐藏
4
5 [super viewWillAppear:animated];
6 }
7
8 -(void) viewWillDisappear:(BOOL)animated{
9 [self.navigationControllersetNavigationBarHidden:NO animated:YES];
10
11 [super viewWillDisappear:animated];
12 }

27、如何限制UITextField输入长度(监听textField文本变化的事件)  

1、实现UITextFieldDelegate协议;  
2、实现textField:shouldChangeCharactersInRange:replacementString:方法;

1  -(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string{
2 int kMaxLength = 11;
3
4 NSInteger strLength = textField.text.length - range.length + string.length;
5 //输入内容的长度 - textfield区域字符长度(一般=输入字符长度)+替换的字符长度(一般为0)
6 return (strLength <= kMaxLength);
7
8 }

如上代码,如果我们简单的这样写: if(range.location<=11) return  或是 if (textfield.text.length>=11) 这样虽然也能限制位数为11位,

但是如果通过放大镜把光标切换到之前的位数后,你照样可以输入,并且还会导致输入11位后,键盘上的退格(X键)无法使用,原因是:

我们在location到达11位后,返回了NO,键盘无法相应:添加,修改,删除。这是很严重的。所以照着我上面的。

方法解读: 
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
功能:

把textField中位置为range的字符串替换为string字符串;此函数在textField内容被修改时调用;

返回值:

  YES,表示修改生效;NO,表示不做修改,textField的内容不变。

参数说明:
  textField:响应UITextFieldDelegate协议的UITextField控件。
  range:    UITextField控件中光标选中的字符串,即被替换的字符串; 
          range.length为0时,表示在位置range.location插入string。

  string:    替换字符串; string.length为0时,表示删除。  

28、使用ios5.0以后的一个方法自定义table View Cell   

1 UINib *nib = [UINib nibWithNibName:@"TvWeiboCell" bundle:nil];
2 [tableView registerNib:nib forCellReuseIdentifier:CellIdentifier];

29、iOS和iPad各app图标和启动页尺寸。  

iphone APP图标尺寸:57X57    高清:114X114  单位:pixel   命名:无特殊要求,最好是,app_icon  高清的要加@2x

iphone 启动页尺寸:大小最好是320X460或320X480(相当于整个屏幕尺寸) 单位:pixel 命名:Default.png

iPad APP图标尺寸:72X72 高清:144X144  单位:pixel 命名:

ipad 启动页尺寸:大小最好是768X1004或768X1024  单位:pixel 命名:Default-Portrait~ipad.png   高清:Default-Portrait@2x~ipad.png

30、如何用NSLog输出NSRange,CGRect等结构体。   

NSString 中的方法: 
NSStringFromCGPoint   
NSStringFromCGSize  
NSStringFromCGRect  
NSStringFromCGAffineTransform   
NSStringFromUIEdgeInsets  
如:NSLog(@"rect1: %@", NSStringFromCGRect(rect1));

31、如何在navigationviewcontroller中,pop到之前不同的viewcontroller(push过的viewcontroller)?   iOS项目开发中的知识点与问题收集整理①

如上图所示,回退到界面2,很简单:  [self.navigationControllerpopViewControllerAnimated:YES];  直接就回退到界面2了,可是我们既不想回到rootviewcontroller,

也不想回到界面2,只想回到界面1,该如何做? 
笨方法:在界面1要跳转到界面2时,把自己self,set到界面2(前提界面2要设置一个id类型的属性,用来存放界面1self,以此类推,当在界面3想退到界面1时, 
[self.navigationControllerpopToViewController:controlleranimated:YES]; 
其实现在刚明白,一个很简单的方法:

1 NSArray *viewControllers=[self.navigationController viewControllers];
2 UIViewController *controller=[viewControllers objectAtIndex:1];

想起来navigation的机制了吧,每当我们push到一个viewcontroller时,就会把这个viewcontroller的实例保存到nsarray里,

通过array可以获取到任何一个viewcontroller,

这不就解决问题了么?
 [self.navigationController popToViewController:controller animated:YES];

【注意】千万不要在这个地方实例化 界面1 然后popToViewController,这种方法是不对的。

32、self.navigationItem.backBarButtonItem 的title设置   

新写的App中需要使用UINavigationController对各个页面进行导航,但由于第一级页面的title较长,在进入第二级页面后返回按钮

leftButtonItem的title就会变得很长,对NavigationBar空间占用很大,而且不美观,于是使用代码对leftButtonItem的title文本进行修改,

无论是设置self.navigationItem.leftBarButtonItem.title = @"返回";还是self.navigationItem.backBarButtonItem.title = @"返回";

都没有效果,title文本始终不会发生变化。到网上乱搜一通后,得到了以下解决方法,相对来说比较简单,特记录如下:
在第一级页面的viewDidLoad方法中加入以下代码:

1 UIBarButtonItem *temporaryBarButtonItem = [[UIBarButtonItem alloc] init];
2 temporaryBarButtonItem.title =@"返回";
3 self.navigationItem.backBarButtonItem = temporaryBarButtonItem;
4 [temporaryBarButtonItem release];
5 // 也就是用一个新的按钮在进行导航前将原来的返回按钮替换掉就可以了。

所以,通过这个我们可以明白,self.navigationItem.backBarButtonItem是在一级页面设置的(提前设置下一个页面的返回按钮),

而self.navigationItem.leftBarButtonItem/rightBarButton是在二级页面设置的,(随意设置本页面的左右按钮,左按钮将替代系统的返回按钮)
---------------------------------------------------------------------------------------------------------

一般一个程序中有一个UIWindow,一个UINavigationController,一个根UIViewController,多个子UIViewController。

UIWindow是整个可视界面的容器,里面放置我们看到的UIView。
UIView负责处理屏幕上一个矩形区域的绘制,UIView中还可包含子UIView。
UIWindow是UIView类的扩展,可以看作是整个屏幕的根UIView。
UIViewController负责管理UIView的层次结构。可以有多个UIViewController。

一个UIViewController中有一个顶部的UINavigationBar、一个根UIView,多个子UIView。
UINavigationBar中有一个UINavigationItem,UINavigationItem。

UINavigationController是用于构建分层应用程序的主要工具,它维护了一个UIViewController栈。
这个栈中必须有一个根UIViewController,其他的UIViewController都是子UIViewController。

UINavigationItem表示UINavigationBar中的控件,比如左按钮、中间标题、右按钮。
UINavigationController会自动在当前子UIViewController的UINavigationBar左边添加一个返回按钮。
按钮名称是上一个UIViewController的标题。

---------------------------------------------------------------------------------------------------------

33、self.navigationItem和self.navigationController.navigationItem的区别?  

/**********************************************/

self.navigationItem

self.navigationController.navigationItem

self.navigationController.navigationBar

/**********************************************/

1,  不要混淆 self.navigationItem  和 self.navigationController.navigationItem ,

UINavigationItem 本身是用来 定制 ViewController自己在被导航过程中的 appearence, navigationItem是UIViewController类

关于UINavigationControllerItem类别的扩展:

@interface UIViewController (UINavigationControllerItem)

@property(nonatomic,readonly,retain)UINavigationItem * navigationItem;

...

@end

所以后者 是调用 VC的所在的导航控制器导航控制器自己自己作为VC的 navigationItem,是导航的叠加。

2. UINavigationBar 继承于 UIView,隶属于整个 UINavigationController ,用来定义整个导航过程中的导航栏的颜色等其他数值,

(类似于 self.tabBarController.tabBar  UINavigationBar ,只需要一个设置通用的基本属性),只能通过self.navigationController.navigationBar来访问。

因此,定制于导航堆栈里某个VC 的时候,一般通过self.navigationItem,   比如常用的self.navigationItem.leftBarButtonItem,

self.navigationItem.rightButtonItem, 同时如果自己来定制导航栏的外观的话,就要用到self.navigationItem.titleView,

这个可以直接用一个 CustomView 赋值于self.navigationItem.titleView即可。此时,如果需要,就得自己画导航过程中的返回按钮了。

34、图片模糊化处理 

1  
2 +(UIImage *)scale:(UIImage *)image toSize:(CGSize)size
3 {
4 UIGraphicsBeginImageContext(size);
5 [image drawInRect:CGRectMake(0, 0, size.width, size.height)];
6 UIImage *scaledImage = UIGraphicsGetImageFromCurrentImageContext();
7 UIGraphicsEndImageContext();
8 return scaledImage;
9 }

35、NSString转换大小写的用法   

iOS 6中NSString对象有些新的使用方法,可以让字符串转变成全部大写,全部小写,或者每个单词首字母大写。
 
代码如下所示:

 1 NSString *str = @"mobile developer tips";
2 // Convert string to uppercase
3 NSString *upperStr = [str uppercaseStringWithLocale:[NSLocale currentLocale]];
4 NSLog(@"upperStr: %@", upperStr);
5
6 // Convert string to caps
7 NSString *capStr = [upperStr capitalizedStringWithLocale:[NSLocale currentLocale]];
8 NSLog(@"capStr: %@", capStr);
9
10 // Convert string to lowercase
11 NSString *lowerStr = [capStr lowercaseStringWithLocale:[NSLocale currentLocale]];
12 NSLog(@"lowerStr: %@", lowerStr);

运行结果:
iOS项目开发中的知识点与问题收集整理①

36、真机调试:could not change executable permissions错误?   

虽然更改了新demo的bundle identifier和之前的identifier一样,但是真机上还保留着之前调试时的demo,所以新的工程如果使用同样的identifier真机调试,需要先把机器上原来的demo删除,再使用新工程调试。

37、判断iphone5屏幕的宏定义 

1 #define iPhone5 ([UIScreen instancesRespondToSelector:@selector(currentMode)] ? CGSizeEqualToSize(CGSizeMake(640, 1136), 
[[UIScreen mainScreen] currentMode].size) : NO)

在需要判断屏幕尺寸的地方:
 mymapview = [[BMKMapView alloc] initWithFrame:CGRectMake(0,0,320,460+(iPhone5?88:0))];  
 
iphone5的View为568,减去Nav(44)+任务栏(20),为504,相比iphone4s及以前版本的480,减去Nav+任务栏,为416,高出88(差别).
http://www.cnblogs.com/maxfong/archive/2012/10/04/2711379.html

38、invalid deployment target for -stdlib=libc++ (requires iOS 5.0 or later)错误  

选中项目--target---build settings  找到C++Standard Library 改成:Compiler Default,再编译就不会有错误了.
 iOS项目开发中的知识点与问题收集整理①

39、如何调用系统声音?【iphone 调用系统铃声与震动功能】 

首先要在工程里加入Audio Toolbox framework这个库,然后在需要调用的文件里
#import <AudioToolbox/AudioToolbox.h>

最后在需要播放提示音的地方编写如下代码:

AudioServicesPlaySystemSound(1000);//新邮件消息提示

AudioServicesPlaySystemSound(kSystemSoundID_Vibrate); //震动

注:括号中为系统声音的id,详见请参考以下网址http://iphonedevwiki.net/index.php/AudioServices
http://blog.csdn.net/tskyfree/article/details/8096500
http://www.cnblogs.com/martin1009/archive/2012/06/14/2549473.html
http://www.cnblogs.com/chen1987lei/archive/2012/02/07/2341535.html

40、重复调用2次loadView和viewDidLoad   

最好不要在UIViewController的loadView方法中改变状态栏的可视性(比如状态栏由显示变为隐藏、或者由隐藏变为显示),因为会导致重复调用2次loadView和viewDidLoad方法。

//错误代码
1 - (void)loadView {
2 NSLog(@"loadView");
3 // 隐藏状态栏
4 [UIApplication sharedApplication].statusBarHidden = YES;
5
6 // .... 创建UIView
7 self.view = [[[UIView alloc] initWithFrame:[UIScreen mainScreen].bounds] autorelease];
8 self.view.backgroundColor = [UIColor grayColor];
9 }
10
11 - (void)viewDidLoad {
12 [super viewDidLoad];
13 NSLog(@"viewDidLoad");
14 }

打印信息:
1 2013-05-14 00:51:36.152 test[2251:c07] loadView  
2 2013-05-14 00:51:36.153 test[2251:c07] loadView  
3 2013-05-14 00:51:36.153 test[2251:c07] viewDidLoad  
4 2013-05-14 00:51:36.154 test[2251:c07] viewDidLoad

虽然运行效果是对的,但是系统连续调用了2次loadView和viewDidLoad方法,导致创建了2次UIView,造成了不必要的开销。

原因分析:
状态栏由显示变为隐藏,意味着屏幕的可用高度变长了,UIViewController的UIView的高度也要重新调整,因此系统会重新调用

loadView方法创建UIView,创建完毕后再次调用viewDidLoad方法。

>>>>>>>>>>第二部分<<<<<<<<<<<<

上一篇:IOS 支付、性能调试、IPv6兼容支持等


下一篇:27 python 初学(信号量、条件变量、同步条件、队列)