iOS项目开发中的知识点与问题收集整理②
1、点击UIButton 无法产生触摸事件
如果在UIImageView中添加了一个按钮,你会发现在默认情况下这个按钮是无法被点击的,需要设置UIImageView的userInteractionEnabled为YES:
imageView.userInteractionEnabled = YES;
设置为YES后,UIImageView内部的按钮就可以被点击了
2、如何启动app时全屏显示Default.png(图片)?
大部分app在启动过程中全屏显示一张背景图片,比如新浪微博会显示这张:
要想在iOS中实现这种效果,毫无压力,非常地简单,把需要全屏显示的图片命名为Default.png即可,在iOS app启动时默认会去加载并全屏显示Default.png。
也可以用其他名称来命名图片,在Info.plist配置一下即可:
配置过后,app启动时就会去加载并全屏显示lufy.png
在默认情况下,app显示Default.png时并非真正的"全屏显示",因为顶部的状态栏并没有被隐藏,比如下面的效果:
大部分情况下,我们都想隐藏状态栏,让Default.png真正全屏显示。
说到这里,可能有人马上就想到了一种办法:在AppDelegate的application:didFinishLaunchingWithOptions:方法中添加如下代码:
[UIApplication sharedApplication].statusBarHidden = YES;
我只能说你的思路是对的,但实际上达不到想要的效果,你会发现显示Default.png时状态栏还是存在的,等Default.png显示完毕后,状态栏才被隐藏。
我先解释下为什么这种方法不可行,其实原因很简单:
1> Default.png是在app启动过程中加载的,并不是在app启动完毕后再加载的
2> AppDelegate的application:didFinishLaunchingWithOptions:方法是在app启动完毕后才调用的
下面说一下解决方案,在Info.plist中增加一个配置即可:
这里的YES表示在app初始化(启动)的时候就隐藏状态栏。
当然,在Default.png显示完毕后状态栏还是隐藏的。如果想重新显示状态栏,补上下面代码即可:
[UIApplication sharedApplication].statusBarHidden = NO;
3、使用ASIHTTPRequest保存cookies
假如我的APP,第一次启动请求了登录接口并得到了Cookie,然后我把APP关了,下次启动APP,我不请求登录接口了,
那上次得到的Cookie就不存在了。如果需要,那么2种方法,下次启动app,自动登入,这样能得到服务器分配给你的cookier
(这一种是最好的,因为session也会过期),还有一种是你把上次登入的时候,拿到的cookier存起来,然后下次启动app的时候,
手动给请求(ASIHTTP)添加cookie。所以当第一次登录成功后,可以把cookie保存到CoreData,SQLite,UserDefault等,
等到下次网络请求时,读取:
1 ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:UserInfoURL];
2 [request setRequestMethod:@"POST"];
3 [request addRequestHeader:@"Cookie" value:[NSString stringWithFormat:@"cookie=%@",[[NSUserDefaults standardUserDefaults] objectForKey:@"cookie"]]];
4 //把cookie的值放进Header里,这个cookie的值是一串很长的字符串。
4、设置UITextField只有当有字符输入后,键盘右下角的搜索/返回/done/等等键才可以使用
TextField设置这个属性为YES就可以了,默认为NO
searchField.enablesReturnKeyAutomatically =YES;
5、类似QQ等IM软件,长度和高度不一的聊天气泡的图片是如何做的?拉伸?
其实是一个小气泡png,然后拉伸中间部分,四个角不拉动,就是局部拉伸。ios自带方法,四个角可以不拉伸的,如下:
6、UITableView中有多个UITextField时,被挡住的TextField如何实现自动向上弹起?
首先要实现TextField的delegate,在方法:
1 - (void)textFieldDidBeginEditing:(UITextField *)textField {
2 [self.tableView setContentOffset:CGPointMake(0, 70) animated:YES];
4 }
这说明当开始输入时,tableview在原来的基础上向上抬起70个距离。多个UITextFiled可以通过判断来使用CGPoint的调整高度,我这写的是70.
tableview的scrollEnabled属性一定要是YES;要不然滚动不了了。
记得在return时复原tableview的位置:
1 - (BOOL)textFieldShouldReturn:(UITextField *)sender {
2 [self.tableView setContentOffset:CGPointMake(0, 0) animated:YES];
3 return YES;
4 }
7、ios如何在调试时,轻松找到程序在哪里崩溃?
我们给自己的工程添加一个全局的断点:
一步步按上面图完成操作。
再运行程序
自动就断点到这里来了,
log信息是:
2013-05-20 11:14:19.635 GestureRecognizer[1491:c07] -[__NSCFNumber isEqualToString:]: unrecognized selector sent to instance 0x7a88df0 2013-05-20 11:15:21.148 GestureRecognizer[1491:c07] *** Terminating app due to uncaught exception 'NSInvalidArgumentException',
reason: '-[__NSCFNumber isEqualToString:]: unrecognized selector sent to instance 0x7a88df0'
这样很简单就能发现程序崩溃是因为value没有 isEqualToString方法。如果没加上面这个通用的断点,那程序会直接断点到main函数去。
8、UIImageView 如何实现windows 桌面类似的背景壁纸屏幕(很小的图片会显示N多个)?
从UImageView上找ContentMode或clipToBounds是都不管用的,正确的办法是,不用UImageView,使用UIView,然后设置backgroundColor属性为我们的图片,这样的话自动会以屏幕的方式显示。
1 UIView *gridView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 195)];
2 gridView.backgroundColor = [UIColor colorWithPatternImage:BUNDLE_IMAGE(@"blue_grid")];
3 [self.view addSubview:gridView];
4 [gridView release];
下图所示:(原图是一个6X6的方格)
9、UITableViewCell 的backgroundColor不起作用的问题?
在开发时,想要在tableview中的某一个Cell设置选中状态,并且Cell的背景颜色是一个自定义颜色。
1 -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
2
3 <span style="white-space:pre"> </span>//省略....
5 cell.textLabel.font = [UIFont systemFontOfSize:6.0];
6 cell.textLabel.text = @"13832207020";
7
8 if (indexPath.row==0) {
10 [cell setBackgroundColor:[UIColor colorWithRed:100.0f/255.0f green:176.0f/255.0f blue:0.0f/255.0f alpha:1.0f]];
11 }
12 else{
13 [cell setBackgroundColor:[UIColor whiteColor]];
14 }
15
16 return cell;
17 }
这样的话,第1行cell就应该是我们设置好的颜色,不过请注意,此方法在UITableViewStylePlain的风格下有效,在 UITableViewStyleGrouped的样式下是无效的!这个跟tableview的backgroundView和backgroundColor是没有关系的,个人猜想应该是在Grouped风格下,cell选中的颜色有系统的view遮罩,导致我们设置的无法显示出来。
【补充】如果想在reload或init时设置tableview的某一cell为 selected状态,千万不要使用cell setSelected:YESanimated:YES,使用tableview的方法:
1 NSIndexPath *indexPath = [NSIndexPath indexPathForRow:i inSection:0];
2 terminalTableView selectRowAtIndexPath:indexPath animated:YES scrollPosition:UITableViewScrollPositionNone];
10、UITableViewCell选中时contentView中各组件的高亮状态
使用系统或简单自定义的UITableViewCell时,当选中某一行Cell后,除了背景颜色改变外,Cell上所有的组件(数据)比如UILabel,UIbutton等都被自动显示成了其
Highlighted(高亮)状态下的效果,(如果想显示出效果,你的那些自定义的组件必须要设置高亮状态,比如highlightedTextColor,UIControlStateHighlighted等),
所以这一点需要特别注意,如果不想要系统的这个自动特效,有两个解决办法:
1,组件不设置highlighted下的属性
2,如果自定义的Cell:
1 - (void)setSelected:(BOOL)selected animated:(BOOL)animated
2 {
4 [super setSelected:selected animated:animated];
6 if (selected) {
7 //强制系统在UITableViewCell选中时SettingButton组件的高亮状态为NO
8 [(UIButton *)[self.contentView.subviews objectAtIndex:1] setHighlighted:NO];
9 [settingBtn setImage:BUNDLE_IMAGE(@"accessory_sel") forState:UIControlStateNormal];
10 }
11 else{
12 [settingBtn setImage:BUNDLE_IMAGE(@"accessory_nor") forState:UIControlStateNormal];
13 }
16 }
11、IOS atomic与nonatomic,assign,copy与retain的定义和区别
atomic和nonatomic用来决定编译器生成的getter和setter是否为原子操作。
atomic
设置成员变量的@property属性时,默认为atomic,提供多线程安全。
在多线程环境下,原子操作是必要的,否则有可能引起错误的结果。加了atomic,setter函数会变成下面这样:
{lock}
if (property != newValue) {
[property release];
property = [newValue retain];
}
{unlock}
nonatomic
禁止多线程,变量保护,提高性能。
atomic是Objc使用的一种线程保护技术,基本上来讲,是防止在写未完成的时候被另外一个线程读取,造成数据错误。而这种机制
是耗费系统资源的, 所以在iPhone这种小型设备上,如果没有使用多线程间的通讯编程,那么nonatomic是一个非常好的选择。
指出访问器不是原子操作,而默认地,访问器是原子操作。这也就是说,在多线程环境下,解析的访问器提供一个对属性的安全访
问,从获取器得到的返回值或者通过设置器设置的值可以一次完成,即便是别的线程也正在对其进行访问。如果你不指定 nonato
mic,在 自己管理内存的环境中,解析的访问器保留并自动释放返回的值,如果指定了 nonatomic ,那么访问器只是简单地返回
这个值。
assign
对基础数据类型 (NSInteger,CGFloat)和C数据类型(int, float, double, char)等等。
此标记说明设置器直接进行赋值,这也是默认值。在使用垃圾收集的应用程序中,如果你要一个属性使用assign,且这个类符合
NSCopying协 议, 你就要明确指出这个标记,而不是简单地使用默认值,否则的话,你将得到一个编译警告。这再次向编译器
说明你确实需要赋值,即使它是可拷贝的。
retain
对其他NSObject和其子类对参数进行release旧值,再retain新值
指定retain会在赋值时唤醒传入值的retain消息。此属性只能用于Objective-C对象类型,而不能用于Core Foundation对象。
(原因很明显,retain会增加对象的引用计数,而基本数据类型或者Core Foundation对象都没有引用计数——译者注)。
注意: 把对象添加到数组中时,引用计数将增加对象的引用次数+1。
copy
对NSString 它指出,在赋值时使用传入值的一份拷贝。拷贝工作由copy方法执行,此属性只对那些实行了NSCopying协议
的对象类型有效。更深入的讨论 ,请参考“复制”部分。
copy与retain:
Copy其实是建立了一个相同的对象,而retain不是:
1.比如一个NSString 对象,地址为0×1111 ,内容为@”STR”,Copy 到另外一个NSString 之后,地址为0×2222 ,内容相同。
2.新的对象retain为1 ,旧有对象没有变化retain 到另外一个NSString 之后,地址相同(建立一个指针,指针拷贝),内容当然相同,
这个对象的retain值+1。
总结:retain 是指针拷贝,copy 是内容拷贝。
assign与retain:
1. 接触过C,那么假设你用malloc分配了一块内存,并且把它的地址赋值给了指针a,后来你希望指针b也共享这块内存,于是你又
把a赋值 给(assign)了b。 此时a和b指向同一块内存,请问当a不再需要这块内存,能否直接释放它?答案是否定的,因为a并不
知道b是否还在 使用这块内存,如果a释放了,那么b在使用这块内存的时候会引起程序crash掉。
2. 了解到1中assign的问题,那么如何解决?最简单的一个方法就是使用引用计数(reference counting),还是上面的那个例子,
我们给 那块内存设一个引用计数, 当内存被分配并且赋值给a时,引用计数是1。当把a赋值给b时引用计数增加到2。这时如果a
不再使用这块内存, 它只需要把引用计数减1,表明自己不再拥有这块内存。b不再使用这块内存时也把引用计数减1。当引用计数
变为0的时候,代表该内存不再 被任何指针所引用,系统可以把它直接释放掉。
总结:
上面两点其实就是assign和retain的区别,assign就是直接赋值,从而可能引起1中的问题,当数据为int, float等原生类型时,
可以使用assign。retain就如2中所述,使用了引用计数,retain引起引用计数加1, release引起引用计数减1,当引用计数为
0时,dealloc函数被调用,内存被回收。
12、#pragma mark -#pragma mark Initialization含义
它们告诉Xcode编译器,要在编辑器窗格顶部的方法和函数弹出菜单中将代码分隔开;注意 #pragma mark – 的“-”后面不能有空格。如果你的标志没有
出现在弹出菜单中,比如没有分隔线出现,请在Xcode菜单 “Preferences..”中的 “Code Sense”选项取消选中”Sort listalphabetically”即可。
13、自定义delegate变量声明时使用assign还是retain?
我们通过发送消息给对象出发特定动作;对象发送某些变化的时候通过回调函数(callback)通知我们。对象在特定事件发生的时候,就会调用对应的回调函数,
触发业务逻辑。回调函数通过所谓的代理(Delegation)来实现.
delegate使用方法:
@property (assign) <id>xxxDelegate delegate;
正确的使用方法是使用assign属性而不是retain。之所以对于delegate这类对象使用assign而不是用retain是为了防止循环retain(retain loop)
14、给成员变量(属性)赋值时使不使用self?
使用@property和@synthesize声明一个成员变量,给其赋值是时要在前面加上"self.",以便调用成员变量的setmember方法。直接调用成员变量并且给其赋值:
member=[NSString stringWithFormat:@””];将不执行setmember 方法。
使用self调用成员变量并且给其赋值:self.member=[NSString stringWithFormat:@””];将执行setmember方法。
15、如何给UIbutton 同时设置图片(Image)和文字(Title)以及它们的各种状态?
1 startRangeButton = [UIButton buttonWithType:UIButtonTypeCustom];
2 startRangeButton.frame = CGRectMake(85,componentOriginY, regionImage.size.width, 16);
3 [startRangeButton setBackgroundImage:regionImage forState:UIControlStateNormal];
4 //还可以设置其高亮状态startRangeButton setBackgroundImage:regionImage forState:UIControlStateHighlighted];
5 startRangeButton.titleLabel.font = [UIFont systemFontOfSize:7.0];
6 [startRangeButton setTitle:@"2013-08-01 07:00" forState:UIControlStateNormal];
7 [startRangeButton setTitleColor:COLOR(101, 199, 240, 1) forState:UIControlStateNormal];
8 [startRangeButton setTitleColor:[UIColor whiteColor] forState:UIControlStateHighlighted];
代码中我设置button背景图片为自己定义的一个regionImage,并设置了button的title = “2013-08-01 07:00”【注意,设置了背景图片后,title只能这样添加,以button.titleLabel.text方式添加会无法显示的】,并且设置了tiitle正常和高亮下文字颜色。
所以看到这里,应该明白button.setBackgroundImage 和 set Image 的区别了吧,前者是可以同时设置文字,后者是一旦设置了image,无法再显示文字。
普通:高亮:
16、如何将NSDate类型转化为距离1970/1/1的毫秒差?
[formatter setDateFormat:@"yyyy-MM-dd HH:mm"]; 这种格式得到的数值是精确到秒的,也就是说少1000,
但是尝试[formatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];或SS大写,或[formattersetDateFormat:@"yyyy-MM-dd HH:mm.ss.SSS"];都不起作用,最后才发现,
原来是这样
NSTimeInterval本身是个秒级别的double类型数值,小数点后面即毫秒数,*1000.0f即可得到毫秒级别的时间差
1 //为了兼容java版本,事件是从1970/1/1开始
2
3 -(NSDate *)getDateTimeFromMilliSeconds:(long long) miliSeconds
5 {
7 NSTimeInterval tempMilli = miliSeconds;
8
9 NSTimeInterval seconds = tempMilli/1000.0;
10
11 NSLog(@"seconds=%f",seconds);
12
13 return [NSDate dateWithTimeIntervalSince1970:seconds];
15 }
16
17
18
19 //将NSDate类型的时间转换为NSInteger类型,从1970/1/1开始
20
21 -(long long)getDateTimeTOMilliSeconds:(NSDate *)datetime
23 {
25 NSTimeInterval interval = [datetime timeIntervalSince1970];
26
27 NSLog(@"interval=%f",interval);
28
29 long long totalMilliseconds = interval*1000 ;
30
31 NSLog(@"totalMilliseconds=%llu",totalMilliseconds);
32
33 return totalMilliseconds;
35 }
也就是说,计算结果再自己乘以1000就可以了
1 NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
2 [formatter setDateFormat:@"yyyy-MM-dd HH:mm"];
3
4 NSDate *sDate = [formatter dateFromString:startRangeButton.titleLabel.text];
5 NSDate *eDate = [formatter dateFromString:endRangeButton.titleLabel.text];
6 NSTimeInterval sinterval = [sDate timeIntervalSince1970];
7 long long start = sinterval*1000;
8 NSTimeInterval einterval = [eDate timeIntervalSince1970];
9 long long end = einterval*1000;
10 [mConnectionHelper doTrack:mobile startTime:start endTime:end];
17、ios中的全局静态变量
Objective-C 支持全局变量
主要有两种实现方式:
(1)第一种和C/C++中的一样, 使用"extern"关键词;
(2)另外一种就是使用单例实现。
(比如我们经常会把一个变量放在AppDelegate里面作为全局变量来访问, 其中AppDelegate就是一个单例类)
在Objective-C中如何实现像C++中那样的静态成员变量呢?
你需要做的是在一个类A的implementation(.m或者.mm)文件中定义一个static变量,然后为A类定义静态成员函数(class method,也就是类方法)来操作该变量。
1 //example.h
2 @interface Example : NSObject {
3
4 }
5 - (id)init;
6 +(int)instanceCount;
7 @end
1 //example.m
2 #import "example.h"
3 static int count;
4 @implementation Example
5 -(id)init{
6 self = [super init];
7 if(nil!=self){
8 count+=1;
9 }
10 return self;
11 }
12 +(int)instanceCount{
13 return count;
14 }
15 @end
上面的例子中你就可以通过[Example instanceCount]对静态变量count进行访问,无须创建实例。
警告: static 写在interface外面编译是没有错误的,但是编译器会报警告,这么说这样的写法是不被编辑器认可的。
错误:static 写在interface里面会直接报错,显然这样的语法是不被认可的。
static关键字声明的变量必须放在implementation外面,或者方法中,如果不为它赋值默认为0,
它只在程序开机初始化一次。
18、如何使用 NSNotificationCenter 在viewcontroller之间进行传值?
简单点的来,两个界面间传值,直接上代码了:
sendViewcontroller.m
1 //SettingViewController :接受值的viewcontroller
2 SettingViewController *setting = [[SettingViewController alloc] init];
3 [[NSNotificationCenter defaultCenter] addObserver:setting selector:@selector(received:) name:@"msetting" object:nil];
4 NSDictionary *dict = [[NSDictionary alloc] initWithObjectsAndKeys:@"user",@"type", nil];
5
6 [[NSNotificationCenter defaultCenter] postNotificationName:@"msetting" object:dict];
7 [self.navigationController pushViewController:setting animated:YES];
8
9 [setting release];
10 SettingViewController.m(接收值的viewcontroller)
1 -(void)received:(NSNotification *)notification{
2
3 id data = [notification object];
4 NSLog(@"received data: %@",data);
5 }
这样就实现了基本的使用,跟delegate类似,注意 addObserver时,需要写目标viewcontroller的实例,而不是self。
19、Thread EXC_BAD_ACCESS : objc_retain, objc_getProperty 崩溃错误
如上图所示,遇到这个错误,从字面的意思我们大致能猜到,是有属性已经被release掉了,但是我们又使用它了,所以,一部一部排查把,一定有某个地方的属性
提前被release掉了,自己手动管理内存就会有这样的困恼,代码很多,不想去找,一定要有耐心,找的过程还可以学到很多知识。
如上图,这个就是我找到的原因所在,unarchiver release掉了,而我们在其它的类中想使用location的属性。
20、MAC 终端(bash)svn命令不识别 command not found
在mac os 10.8中,svn Command line tools是没有自动安装的,这样的话,svn 命令行就会失效,解决办法:
1.打开xcode偏好设置(comand+,)-->"Download" -->Components:
2.点击“Command line tools”下载,下载完成之后安装。
3.安装完成之后,打开终端,输入“svn help”,如果出现如下所示,说明命令行工具安装好了。
21、ios MapKit 判断坐标是否在MapView显示范围内
1 CLLocationDegrees leftDegrees = mapView.region.center.longitude –(mapView.region.span.longitudeDelta / 2.0);
2 CLLocationDegrees rightDegrees = mapView.region.center.longitude +(mapView.region.span.longitudeDelta / 2.0);
3 CLLocationDegrees bottomDegrees = mapView.region.center.latitude –(mapView.region.span.latitudeDelta / 2.0);
4 CLLocationDegrees topDegrees = self.region.center.latitude +(mapView.region.span.latitudeDelta / 2.0);
5 if (leftDegrees > rightDegrees) { // Int'l Date Line in View
6 leftDegrees = -180.0 - leftDegrees;
7 if (coords.longitude > 0) // coords to West of Date Line
8 coords.longitude = -180.0 - coords.longitude;
9 }
10 If (leftDegrees <= coords.longitude && coords.longitude <= rightDegrees && bottomDegrees <= coords.latitude && coords.latitude <= topDegrees) {
11 // 坐标在范围内
12 }
22、在App图标上显示数字徽标
IOS7 :
1 UIApplication *app = [UIApplication sharedApplication];
2
3 // 应用程序右上角数字
4 app.applicationIconBadgeNumber = 99;
上面的代码可以搞定
IOS8:
iOS8中设置application badge value 会抛错:Attempting to badge the application icon but haven't received permission from the user to badge the
原因是因为在ios8中,设置应用的application badge value需要得到用户的许可。使用如下方法咨询用户是否许可应用设置application badge value
UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeBadge categories:nil];
[[UIApplication sharedApplication] registerUserNotificationSettings:settings];
在这之前要判断系统是否为iOS8的系统,否则8之前的系统会报错。
1 UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeBadge categories:nil];
2
3 [[UIApplication sharedApplication] registerUserNotificationSettings:settings];
4
5 UIApplication *app = [UIApplication sharedApplication];
6 // 应用程序右上角数字
7 app.applicationIconBadgeNumber = 10;
注意:清除数字请将数字设置为 0
1-2设置标签栏按钮显示数字图标
1 UIViewController *second=[SecondViewController new];
2 UITabBarItem *item=[[UITabBarItem alloc]initWithTitle:@"支付" image:[UIImage imageNamed:@"008"] selectedImage:[UIImage imageNamed:@"002"]];
3 second.tabBarItem=item;
4 item.badgeValue=@"20";
效果如图
23、如何获取手机硬件信息?
通过使用UIDevice:
[[UIDevice currentDevice] systemName];
[[UIDevice currentDevice] systemVersion];//os version
[[UIDevice currentDevice] uniqueIdentifier];
[[UIDevice currentDevice] model];
[[UIDevice currentDevice] name];
真机上结果:
System Name: iPhone OS
System Version: 4.2.1
Unique ID: 9b5ded78d5fa0ac96250f8b4af0e46f40b96ea6d
Model: iPhone
Name: “wwk”的 iPhone
模拟器上结果:
System Name: iPhone OS
System Version: 4.2
Unique ID: 21FFE0FF-429B-5D0B-96D2-EADCA3203260
Model: iPhone Simulator
Name: iPhone Simulator
uniqueIdentifier:iPhone通过,向几个硬件标识符和设备序列号应用内部散列算法,而生成这一标识符。
http://blog.csdn.net/qiwancong/article/details/7914923 参考
24、设置隐藏头部状态栏(电池图标)
1-1 设置状态 如图
1-2添加代码:
1 //隐藏状态栏
2 [[UIApplication sharedApplication]setStatusBarHidden:YES];
实现效果 如图
25、根据App版本号来判断App开启时是否进入引导页
#define __kFirstVersion @"kFirstVersion"
1 //根据App版本号来判断App开启时是否进入引导页
2 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
3
4 //1.获取一个状态:是否已经进入过主界面
5 // BOOL b = [[[NSUserDefaults standardUserDefaults]valueForKey:__kFirst] boolValue];
6
7 //获取到当前的版本
8 NSString *key = (NSString *)kCFBundleVersionKey;
9 NSString *version = [NSBundle mainBundle].infoDictionary[key];
10
11 //获取到之前的版本
12 NSString *lastVersion = [[NSUserDefaults standardUserDefaults]valueForKey:__kFirstVersion];
13
14 //2.如果没有进入过主界面,则进入引导页
15 //如果两个版本号相同,则进入主界面,否则进入引导页
16 if (![lastVersion isEqualToString:version]) {
18 ViewController *vc = [[ViewController alloc]init];
20 [vc setCallback:^{
21 [self startApp];
22 [[NSUserDefaults standardUserDefaults]setValue:version forKey:__kFirstVersion];
23 [[NSUserDefaults standardUserDefaults]synchronize];
24 }];
26 self.window.rootViewController = vc;
27 }
28 //3.如果已经进入过主界面,则直接进入主界面
29 else
30 {
31 [self startApp];
32 }
33 return YES;
34 }
35
36
37 -(void)startApp
38 {
39 self.window.rootViewController = [[UINavigationController alloc]initWithRootViewController:[RootViewController new]];
40 }
26、计算文本内容所占空间大小方法
1)对于单行文本数据的显示调用- (CGSize)sizeWithAttributes:(NSDictionary *)attrs;方法来得到文本宽度和高度。
例如:
//根据文本内容取得文本占用空间大小
CGSize textSize=[@"Hello World" sizeWithAttributes:@{NSFontAttributeName: [UIFont systemFontOfSize:15]}];
2)对于多行文本数据的显示调用- (CGRect)boundingRectWithSize:(CGSize)size options:(NSStringDrawingOptions)options attributes:(NSDictionary *)attributes context:(NSStringDrawingContext *)context ;方法来得到文本宽度和高度;同时注意在此之前需要设置文本控件的numberOfLines属性为0。
1 //计算多行文本所占空间大小
2 CGSize textSize=[@"Hello WorldHello WorldHello WorldHello WorldHello WorldHello WorldHello World" boundingRectWithSize:CGSizeMake(100, MAXFLOAT)
3 options:NSStringDrawingUsesLineFragmentOrigin
4 attributes:@{NSFontAttributeName: [UIFont systemFontOfSize:15]} context:nil].size;
27、图解 imagView 的 UIContentMode的显示方式 如下图
28、解决view的缩放的时候,layer.border.width(圆角边框)随着view的放大时会出现锯齿化的问题。
self.layer.allowsEdgeAntialiasing = YES;
29、Xcode 7中http通信出现如下错误:Application Transport Security has blocked a cleartext HTTP (http://)
resource load since it is insecure. Temporary exceptions can be configured via your app's Info.plist file.
原因:
在iOS9 中,苹果将原http协议改成了https协议,使用 TLS1.2 SSL加密请求数据。
解决方法:
编辑 Info.plist,加入如下设置:NSAppTransportSecurity
----> NSAllowsArbitraryLoads
如图:
30、报错: You must rebuild it with bitcode enabled (Xcode setting ENABLE_BITCODE)(解决方案)
解决方法有两种:
方法一:使用Enable Bitcode的第三方库
方法二:将工程中的Enable Bitcode设置为NO 如图:
31、Xcode SVN 报错 The server certificate failed to verify. 解决方法
打开终端(实用工具 -->终端),在终端中输入如下命令:
svn ls https://xxxxxxxx/svn/xxxxxx SVN的路径
然后直接输入 “ p ” 确认,再分别输入电脑密码、svn用户名以及密码;就可以重新连接了。
32、ios修改textField的placeholder的字体颜色、大小 方法
1 textField.placeholder = @"username is in here!";
2 [textField setValue:[UIColor redColor]forKeyPath:@"_placeholderLabel.textColor"];
3 [textField setValue:[UIFont boldSystemFontOfSize:16]forKeyPath:@"_placeholderLabel.font"];
33、iOS获取当前根视图控制器并实现页面跳转的方法
1 - (UIViewController*)topViewController
2 {
3 return [self topViewControllerWithRootViewController:self.window.rootViewController];
4 }
5
6 - (UIViewController*)topViewControllerWithRootViewController:(UIViewController*)rootViewController
7 {
8 if ([rootViewController isKindOfClass:[UITabBarController class]]) {
9 UITabBarController *tabBarController = (UITabBarController *)rootViewController;
10 return [self topViewControllerWithRootViewController:tabBarController.selectedViewController];
11 } else if ([rootViewController isKindOfClass:[UINavigationController class]]) {
12 UINavigationController* navigationController = (UINavigationController*)rootViewController;
13 return [self topViewControllerWithRootViewController:navigationController.visibleViewController];
14 } else if (rootViewController.presentedViewController) {
15 UIViewController* presentedViewController = rootViewController.presentedViewController;
16 return [self topViewControllerWithRootViewController:presentedViewController];
17 } else {
18 return rootViewController;
19 }
20 }
21
22 //调用
23 [[self topViewController] presentViewController:[[TransViewController alloc] init] animated:YES completion:nil];
34、全局变量宏定义实现方法
1 #define APPDELEGATE ((AppDelegate *)[UIApplication sharedApplication].delegate)
2 //用法:在AppDelegate.h中定义变量 通过 APPDELEGATE对象实现全局调用
3
4 //AppDelegate.h 代码
5 #import <UIKit/UIKit.h>
6 @interface AppDelegate : UIResponder <UIApplicationDelegate>
7 @property (strong, nonatomic) UIWindow *window;
8 @property (strong,nonatomic) NSString *systemName;
9 @end
10
11 //调用方法 (注意得引用头文件 AppDelegate.h)
12 APPDELEGATE.systemName=@"KingKong";
35、解决MJExtension 转换字段为id(关键字)的问题处理
1 #import "HGProductModel.h"
2 #import "MJExtension.h"
3 @implementation HGProductModel
4
5 //重写 replacedKeyFromPropertyName 方法将id替换为我们定义的字段名
6 + (NSDictionary *)replacedKeyFromPropertyName
7 {
8 return @{@"productID" : @"id"};
9 }
10 @end
36、tableviewcell上按钮点击时确定当前所在行的方法
类似这种按钮:
1 -(void)btnClicked:(id)sender event:(id)event
2
3 {
4
5 NSSet *touches =[event allTouches];
6
7 UITouch *touch =[touches anyObject];
8
9 CGPoint currentTouchPosition =[touch locationInView:self.tableView];
10
11 NSIndexPath *indexPath =[self.tableView indexPathForRowAtPoint:currentTouchPosition];
12
13 UITableViewCell *cell=[self tableView:tableView cellForRowAtIndexPath:indexPath];
14
15 }
37、设置UItableViewCell 右侧小箭头
cell.accessoryType=UITableViewCellAccessoryDisclosureIndicator;
38、UILabel 文字显示删除线方法 如图:
1 NSString *bottomStr=[NSString stringWithFormat:@"原价%@",model.standardPrice];
2 NSMutableAttributedString *attrString=[[NSMutableAttributedString alloc]initWithString:bottomStr];
3 [attrString addAttribute:NSStrikethroughStyleAttributeName value:[NSNumber numberWithInteger:NSUnderlinePatternSolid | NSUnderlineStyleSingle]
4 range:NSMakeRange(0, bottomStr.length)];
5 self.bottomLb.attributedText=attrString;
39、xxx文件 is missing from working copy 解决方法
解决方案:
1.打开终端
2.cd 到警告所提示的文件夹下
3.执行命令svn rm --force 丢失文件的名称
4.回车
5. find . -type d -name .svn | xargs rm -rf //该命令为直接删除指定文件夹下所有SVN相关
6. sudo find /Users/KingKong/Desktop/Scitel_Project/iOS-BigEvent/ -name ".svn" -exec rm -r {} \;//红色字体为项目路径
40、解决 UITableView 等UI控件下移的问题
1.//下方显示不全 _tableView.contentInset=UIEdgeInsetsMake(0, 0, -20, 0); 2、//其他UI控件下移复位处理 self.navigationController.navigationBar.translucent = NO; self.edgesForExtendedLayout = UIRectEdgeNone; self.automaticallyAdjustsScrollViewInsets = YES; self.extendedLayoutIncludesOpaqueBars = YES;
41、UITableView 复用时实现修改FooterView背景色方法
- (void)tableView:(UITableView *)tableView willDisplayFooterView:(UIView *)view forSection:(NSInteger)section {
view.tintColor = HGTableViewBackColor;
}
42、修改UIProgressView 高度的方法
CGAffineTransform transform = CGAffineTransformMakeScale(1.0f, 5.0f);
self.progressView.transform = transform;
需要导入CoreGraphics.framework包
43、根据index(下标)获取TableViewCell
1 NSIndexPath *indexPath = [NSIndexPath indexPathForItem:i inSection:0];
2 UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
44、iOS 中 _OBJC_CLASS_$_xxxx 问题解决方案
错误代码:
Undefined symbols for architecture x86_64:
"_OBJC_CLASS_$_QQApiInterface", referenced from:
objc-class-ref in AppDelegate.o
"_OBJC_CLASS_$_ShareSDK", referenced from:
objc-class-ref in AppDelegate.o
objc-class-ref in RecipeDetailViewController.o
objc-class-ref in showViewController.o
objc-class-ref in video_show.o
"_OBJC_CLASS_$_TencentOAuth", referenced from:
objc-class-ref in AppDelegate.o
"_OBJC_CLASS_$_WXApi", referenced from:
objc-class-ref in AppDelegate.o
"_OBJC_CLASS_$_WeiboApi", referenced from:
objc-class-ref in AppDelegate.o
"_OBJC_CLASS_$_YXApi", referenced from:
objc-class-ref in AppDelegate.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
原因:
Xcode升级到6.1.1或以上版本后 默认让所有App都通过64位编译器编译。原来在Xcode6.1.1以下版本的时候默认的
Architectures只有(arm7,armv7s),到6.1.1或以上版本默认就带上arm64的参数了。
方法:
1.把1.选中Targets—>Build Settings—>Combined--->Architectures。
把build active architectures only 改为 NO。
2. 把最下面的Valid Architectures中的arm64参数删掉就可以了
或者:
双击Architectures,选择other,删除$(ARCH_STANDARD),然后增加armv7和armv7s(写上:$(ARCHS_STANDARD_32_BIT))。
3.clean 再build。
设置好后效果图:
45、Xcode更新到7.3后会出现NSObject+MJProperty.h报Cannot create __weak reference in file using manual reference counting错误
解决的办法:
在Build Settings---->Aplle LLVM7.1 - Language - Objectibe-C
---->Weak Reference In Manual Retain Release 设置为YES
46、清理Xcode中多余的开发证书方法
即此处显示的证书
进入此目录 ~/Library/MobileDevice/Provisioning Profiles 删除对应的证书即可。
47、解决no index path for table cell being reused 问题
问题原因是:我用nib自定义了一个cell。作为我的tableHeaderView.当然在我执行下面的这段代码的时候,tableHeaderView
的显示没有任何问题。
headCell = [[NSBundle mainBundle] loadNibNamed:@"RRTableHeadBtnCell" owner:self options:nil][0];
self.tableView.tableHeaderView = headCell;
但是:当我有数据需要更新cell的时候,当我要执行下面的代码的时候,标题的error就出现了。而且我的tableFootView 也同时消失了。
[self.tableview reloadSections:[NSIndexSet indexSetWithIndex:1] withRowAnimation:UITableViewRowAnimationFade];
问题是由于将cell作为section headerView 导致的题目所述错误。
解决方案其实很简单:
self.tableView.tableHeaderView = headCell.contentView;
48、Xcode 打开项目一直显示Indexing... 解决办法
Xcode用得久了,代码中类和方法等字体颜色不提示,文件失去关联,command+左键出现symbol not found。
defaults write com.apple.dt.Xcode IDEIndexDisable 1 这可以解决Xcode一直处于indexing状态;
* 需要时候,把1改为0就可以了: defaults write com.apple.dt.Xcode IDEIndexDisable 0 这样你的Xcode就
可以正常代码提示了 当然,这还有可能是因为工程索引文件被破坏导致,可通过以下方法解决:
1)、Xcode -> Organizer -> Projects ->把所有工程中的Derived Data 删除Delete掉。
2)、进入~/Library/Developer/Xcode/DerivedData 这个文件夹,把里面相关工程的文件夹删掉。
49、iOS修改UIStatusBar 文字颜色方法
1)、在plist里增加一行 UIStatusBarStyle(或者是“Status bar style”也可以),这里可以设置两个值,
UIStatusBarStyleDefault (默认黑色)和 UIStatusBarStyleLightContent (白色),同时必须在plist中添加
View controller-based status bar appearance 设置NO; 此方法只对iOS7以后的操作有效。
50、 真机调试弹出 "Mac OS X"想要进行更改。键入管理员的名称和密码以允许执行此操作("Mac OS X"想使用系统钥匙串)
解决方法:
打开钥匙串访问选择系统下对应的证书点开双击,将访问控制项改变到允许所有应用程序访问此项目,输入一次密码即可,
以后就不会弹出了!
51、Xcode8代码出现输出ubsystem: com.apple.UIKit, category: HIDEventFiltered, enable_level: 0 ...
解决办法:【Product】-【Scheme】-【Edit Scheme】-【Run】-【Argument】-【Environment Variable】
添加keyValue【OS_ACTIVITY_MODE disable】可以停止输出打印此日志
52、实现在一个viewcontroller上加载另一个viewcontroller方法
[self addChildViewController:otherVC];
[self.view addSubview:otherVC.view];
53、解决Xcode8 打开Xib文件后Xcode7 无法打开并编译的问题
修改如上图两个地方即可。
54、打包Framework中如果存在Category 造成在引用时崩溃的解决方法
在引用时需要在工程中的 Build Settings ----> other linker flags中添加 -ObjC 即可。