逆袭学霸   发表于 2016-04-24 09:08:41

收藏 374 3

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

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)?  


如上图所示,回退到界面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);

复制代码

运行结果:
 

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,再编译就不会有错误了.
 

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方法。 


全部回复共3条
电梯直达
我要回复
关闭
关闭
QQ
交流群
邀请
好友
App
下载
意见
反馈
返回
顶部