1 应用程序如何省电
iOS的电能管理系统保持电能的方法是关闭当前未使用的硬件功能。应用程序可以通过以下组件达到省电的目的:CPU WiFi和基带(EDGE,3G)无线信号 Core Location框架 加速计 磁盘
您的优化目标应该是以尽可能有效的方式完成大多数的工作。您应该总是采用Instruments和Shark工具对应用程序的算法进行优化。但是,很重要的一点,即使最优化的算法也可能对设备的电池寿命造成负面影响,因此,在写代码时应该考虑如下原则:
避免需要轮询的工作,因为轮询会阻止CPU进入休眠状态。您可以通过NSRunLoop或者NSTimer类在规划需要做的工作,而不是使用轮询
尽可能使共享的UIApplication对象的idleTimerDisabled属性保持NO。当设备不处于活动状态一段时间后,空闲定时器关闭设备的屏幕
尽可能将任务合并在一起,以便使空闲时间最大化。间歇性执行任务会阻止系统更长时间无法关闭硬件
避免过度访问磁盘 。举例来说,当你需要将状态信息保存在磁盘上,则当该状态信息发生变化时再进行保存,或者尽可能将状态变化合并保存,避免短时间频繁进行磁盘写入操作
尽可能快的以群发方式传递数据包,而不是拉长数据传输的时间
尽可能通过WiFi无线信号连接网络。
如果您通过Core Location框架收集位置数据,则请尽可能快地禁止位置更新,以及位置过滤器和精度水平设置为恰当的值。
2 写一个递归方法:计算N的阶乘,然后将计算结果进行存储。以便应用退出后下次启动课直接获取该值。
int f(int i)
{
// 设置退出条件
if(1 == i)
{
return 1;
}
//递归语句
return i*f(i-1);
}
NSInteger result = f(N);
// 创建文件管理器
NSFileManager *fileManager = [NSFileManager defaultManager];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
// 更改到待操作的目录下
[fileManager changeCurrentDirectoryPath:[documentDirectory stringByExpandingTildeInPath]];
// 创建文件fileName文件名称,contents文件的内容,如果开始没有内容可以设置为nil,attributes文件的属性,初始为nil
NSString *fileName = @“f.text”;
NSArray *array = [[NSArray alloc] initWithObject:result,nil];
[fileManager createFileAtPath:fileName contents:array attributes:nil];
3 NSArray和NSMutableArray的区别,多线程操作哪个更安全?
NSMutableArray相对于NSArray可以改变数组中的元素,进行增删改
当一个线程在修改数组,另一个数组在读取数组中的元素,会造成线程不安全,所以用NSArray更安全
解决方案,可在对array进行操作时加锁
NSLock *writeLock = [[NSLock alloc] init];
[writeLock lock];
// ……
[writeLock unLock];
4 当前有一个数组,里面有若干重复的数据,如何去除重复的数据?(会几个写几个)
因为涉及到重复数据项的问题,立马会想到集合(Set)这个数据结构,因为它是不容许存在重复数据项的数据结构。
思路一 :将数组中的每一个元素插入到一个set中,利用set的自动剔除重复数据项的功能,将导致所有重复的数据没办法插入成功,也就是add方法返回false,然后调用toArray方法,返回这个集合所对应的数组。
思路二 :随整个数组进行排序。然后遍历数组,将重复数据项,清除掉。假设下面这个算法的输入是一个已经排好序到的数组
for(int i = 0; i < array.length-1; i++){
if(array[i] == array[i +1]){
array[i] = -1;
}
}
然后遍历数组,删除所有为-1的数据项
5 isKindOfClass、isMemberOfClass作用分别是什么?
两者都是NSObject的比较Class的方法
但两者有很大的区别:
isKindOfClass来确定一个对象是否是一个类的成员,或者是这个类派生出来的类的成员
isMemberOfClass只能确认一个对象是否是当前类的成员
例如NSObject派生的类,用isMemberOfClass不能检测出任何类都是基于NSObject类的这一事实,而isKindOfClass可以
6 写出下面程序段的结果
NSDictionary *dict = [NSDictionary dictionaryWithObject:@"a string value" forKey:@"akey"];
NSLog(@"%@", [dict objectForKey:@"akey"]);
[dict release];
结果是: a string value
考察NSDictionary取值的两个方法:objectForKey 和valueForKey 建议Dictionary只用objectForKey:来取值
objectForKey: 返回指定key的value 若没有这个key返回nil
valueForKey: 同样是返回指定key的value 但有一点,一般key可以是任意字符串的组合 ,如果key不是以@开头 这时候valueForKey:就等同于objectForKey;如果是以@开头,去掉key里的@然互剩下部分执行[super valueForKey:]
[dict valueForKey:@"@theKey"]; 会把 key 里的 @ 去掉,也就变成了 [dict valueForKey:@"theKey"];,而 dict 不存在 theKey 这样的 property,转而执行 [dict valueForUndefinedKey:@"theKey"];,抛出 NSUndefinedKeyException 异常后 crash 掉。
7 请写出以下代码的执行结果
NSString * name = [ [ NSString alloc] init ];
name = @”Habb”;
[ name release];
NSString是一个不可变的字符串,它在初始化后,你不能改变该变量所分配的内存中的值(仅可重新分配该变量所处的内存空间)用NSMutableString即可
8 请分别写出SEL、id的意思?
id 和void *并非完全一样。id是一个指向任何一个继承了Object(或者NSObject)类的对象。需要注意的是id是一个指针,所有你在使用的时候不需要加 * 。比如id foo = nil 定义了一个nil指针,这个指针指向NSObject的一个任意的子类 。而id * foo = nil 则定义了一个指针,被指向的这个指针指向NSObject的一个子类
SEL是“selector”的一个类型,表示一个方法的名字。比如我们定义一个Foo类,这个类带有一个-(int)blah方法,那么
NSLog(@“SEL = %s”,@selector(blah)); 会输出SEL = blah 说白了SEL就是返回方法名
9 iPhone上,不能被应用程序直接调用的系统程序是什么?
时钟 视频 指南针 天气 计算器 备忘录 提醒事件 股市 (待定)
10 以.mm为拓展名的文件里,可以包含的代码有哪些?c和obj-c如何混用
.mm文件可以识别obj-c c c++
1 obj-c 的编译器处理后缀为m的文件时,可以识别obj-c和c的代码
处理mm文件可以识别obj-c c c++代码
但是cpp文件必须只能用c/c++代码,而且在cpp文件include的头文件中,也不能出现obj-c的代码
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的东西就行。obj-c的编译器支持cpp
11 说说如何进行后台运行程序
程序在进入后台运行一小段时间,就会进入挂起状态,此时应用不会再执行任何代码。可以通过调用beginBackgroundTaskWithExpirationHandler:方法让系统给出额外的时间完成一些需要在后台长时间执行的任务
进入后台要处理的任务通过application delegate的方法
-(void)applicationDidEnterBackground:(UIApplication:)application{
// 如处理界面的刷新和网络请求等
}
当程序从后台将要进入前台要处理的任务可以写在-(void)applicationWillEnterForeground:(UIApplication *)application{
// 恢复一些操作的处理
}
当然也可以注册系统通知来实现UIApplicationDidEnterBackgroundNotification和 UIApplicationWillEnterForegroundNotification
12 sizeof和strlen的区别和联系
一 sizeof
sizeof(…)是运算,在头文件中typedef为unsigned int ,其值在编译时就计算好了,参数可以是数组 指针 类型 对象 函数等
它的功能是:获得保证能容纳实现所建立的最大对象的字节大小
由于在编译时计算,因此sizeof不能用来返回动态分配的内存空间的大小。实际上,用sizeof来返回类型以及静态分配的对象 结构体 或数组所占的空间,返回值跟参数里存储的内容没有关系。
具体而言,但参数分别如下的时,sizeof返回值表示的含义如下:
数组 — 编译时分配的数组的大小
指针 — 存储该指针所用的空间大小(存储该指针的地址长度,是长整型 应该为4或者8)
类型 — 该类型所占的空间大小
对象 — 对象的实际占用空间大小
函数 — 函数的返回类型所占的空间大小 。函数的返回类型不能是void
二 strlen
strlen(…)是函数,要在运行时才能计算。参数必须是字符型指针(char *) 。当数组名作为参数传入时,实际上数组就退化成指针了。
它的功能是:返回字符串的长度。该字符串可能是自己定义的,也可能是内存中随机的,该函数实际完成的功能是从代表该字符串的第一个地址开始遍历,直到遇到结束符NULL。返回的长度大小不包括NULL
三 举例
char arr[10] = “what?”;
int len_strlen = strlen(arr);
int len_sizeof = sizeof(arr);
输出 5 and 10
点评:sizeof返回定义arr数组时,编译器为其分配的数组空间大小,不关心里面存了多少数据。strlen只关心存储的数据内容,不关心空间的大小和类型
char *parr = new char[10];
int len_strlen = strlen(parr);
int len_sizeof = sizeof(parr);
int len_sizeofA = sozeof(*parr);
输出 23 4 1
点评: 第一个输出结果23 实际上每次运行都不一样 ,这取决于parr里面存了什么(从parr[0]开始直到遇到第一个NULL结束);第二个结果实际上本意是想计算parr所指向的动态内存空间,但是事与愿违,sizeof认为parr是个字符指针,因此返回的是指该指针所占的空间(指针的存储用的是长整型,所以是4)第三个结果,由于*parr所代表的是parr所指向的地址空间存放的字符,所以长度是1
13 sprintf,strcpy,memcpy的功能?使用上要有哪些要注意的地方
不同拷贝函数的作用:
strcpy
对字符串进行操作,完成从源字符串到目的字符串的拷贝,当源字符串大小大于目的字符串的最大存储空间后,执行该操作会出现段错误
spintf
函数操作的源对象不限于字符串:源对象可以是字符串 也可以是任意基本类型的数据。主要实现将字符串或基本数据类型转化为字符串。要额外指定格式符并且进行格式转化。
如果源对象是字符串,并且指定%s格式符,也可以实现字符串的拷贝功能
memcpy
实现内存的拷贝,实现将一块内存拷贝到另一块内存。该函数的操作对象不限于某一类数据类型,或者说适用于任意数据类型,只要能给出对象的起始地址和内存长度信息,并且对象具有可操作性即可。通常限于同种类型数据或对象之间的拷贝,包括字符串以及基本数据类型的拷贝
在软件升级中,当进行数据拷贝时,最好使用memcpy来进行数据拷贝。因为strcpy sprintf进行拷贝时,当检查到源字符串中有’\0’即ascll码为00 时,被当做数据结束符,就会停止拷贝
14 自己写函数,实现strlen功能
strlen所做的仅仅是一个计数器的工作,它从内存某个位置开始扫描,直到碰到第一个结束符’\0’为止,然后返回计数器值
int strlen(const char *str){
assert(str != NULL);// 判断字符串地址非0
int len;
while((*str++) != ‘\0’){
len++;
}
return len;
}
15 写一个代码片段输入一个字符串“20130322152832”,输出一个NSDate类型的对象,打印该对象输出2013-03-22 15:28:32
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
// 设置格式
[formatter setDateFormat:”yyyy-MM-dd HH : mm : ss”];
将字符串类型转化成 NSDate类型
NSDate *Date = [formatter dateFromString:“20130322152832”]
NSLog(@“%@",Date);
16
找错误
a:void test1()
{
char string[10];
char* str1 = "0123456789”; 错误!!!// 加个’\0’表示结束符 strcpy只有遇到’\0’才停止 加上之后strcpy会造成string数组溢出
strcpy( string, str1 );
}
b:void GetMemory( char **p, int num )
{
*p = (char *) malloc( num );
}
void Test( void )
{
char *str = NULL;
GetMemory( &str, 100 );
strcpy( str, "hello" );
printf( str );
}