NSString *path = NSHomeDirectory();
上面的代码得到的是应用程序目录的路径,在该目录下有三个文件夹:Documents、Library、temp以及一个.app包!
该目录下就是应用程序的沙盒,应用程序只能访问该目录下的文件夹!!!
请参考下面的例子:
1、
NSString *path1 = NSHomeDirectory();
NSLog(@"path1:%@", path1);
path1:/Users/yuanjun/Library/Application Support/iPhone Simulator/4.2/Applications/172DB70A-145B-4575-A31E-D501AC6EA830
2、
NSString *path2 = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
NSLog(@"path2:%@", path2);
path2:/Users/yuanjun/Library/Application Support/iPhone Simulator/4.2/Applications/172DB70A-145B-4575-A31E-D501AC6EA830/Library/Caches
3、
NSString *path3 = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSLog(@"path3:%@", path3);
path3:/Users/yuanjun/Library/Application Support/iPhone Simulator/4.2/Applications/172DB70A-145B-4575-A31E-D501AC6EA830/Documents
4、
NSString *path4 = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents"];
NSLog(@"path4:%@", path4);
path4:/Users/yuanjun/Library/Application Support/iPhone Simulator/4.2/Applications/172DB70A-145B-4575-A31E-D501AC6EA830/Documents
5、
NSString *path5 = [NSHomeDirectory() stringByAppendingPathComponent:@"Library"];
NSLog(@"path5:%@", path5);
path5:/Users/yuanjun/Library/Application Support/iPhone Simulator/4.2/Applications/172DB70A-145B-4575-A31E-D501AC6EA830/Library
6、
NSString *path6 = [NSHomeDirectory() stringByAppendingPathComponent:@"temp"];
NSLog(@"path6:%@", path6);
path6:/Users/yuanjun/Library/Application Support/iPhone Simulator/4.2/Applications/172DB70A-145B-4575-A31E-D501AC6EA830/temp
(十三)块语法,循环引用
__block typeof(self)bself = self; 是什么意思? 是把当前的self 变成一个 block形式的指针吗? 但变成block的指针 又和原来self有那些不同呢? 希望高手指点 | |
shichangone | 2012-09-14 18:35 | 防止在block中用到self时把self对象retain, 造成内存泄露。 | |
joymoo | 2012-09-15 08:57 | block对于其变量都会形成strong reference,对于self也会形成strong reference ,而如果self本身对block也是 strong reference 的话,就会形成 strong reference 循环,造成内存泄露,为了防止这种情况发生,在block外部应该创建一个week(__block) reference。 所以在block内如果有self的话,一般都会在block外面加一句_block typeof(self)bself = self; __block typeof(self) bself = self; [self methodThatTakesABlock:^ { [bself doSomething]; } | |
(十四)一个类中开辟线程使用nstimer,不调用dealloc(彪哥)
_refreshTimer = [[NSTimerscheduledTimerWithTimeInterval:1.0target:selfselector:@selector(shuaUI)userInfo:nilrepeats:YES]retain];
[[NSRunLoopcurrentRunLoop]addTimer:_refreshTimerforMode:NSRunLoopCommonModes];关键在这
如果要刷界面(界面都在主线程中)就要回到主线程
[selfperformSelectorOnMainThread:@selector(shuaLabel:)withObject:dicwaitUntilDone:NO];
延时执行方法
[selfperformSelector:@selector(doneLoadingTableViewData)withObject:nilafterDelay:1.0];
// NSTimer * timer;
// NSDate *fireDate = [NSDate dateWithTimeIntervalSinceNow:1.0];
// timer = [[NSTimer alloc] initWithFireDate:fireDate interval:1.0f target:self selector:@selector(shuaUI) userInfo:nil repeats:YES];
// [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
// self.refreshTimer = timer;
// [timer release];
(十五)不能调用dealloc方法
循环引用容易照成不调用dealloc
当一个实例的retainCount不为0时,不会调用他的dealloc方法。
例如:
FinanceViewController *financeVC = [[FinanceViewController alloc] init];
[self pushViewController:financeVC withData:nil animate:YES];
//[financeVC release];
如果financeVC没有在这个时候release,当从financeVC pop回来的时候不会调用financeVC的dealloc方法,对于add上的view,如果没有removeFromSuperView的话,也不会调用该view的dealloc方法,造成内存泄露!
前几天在给游戏做收尾测试时,发现了一个关于内存泄露的问题,一直没找着问题所在,经过反复调试和查找资料今天终于解决了,特此记录下来以免以后再犯!
关于objective-c的内存管理,我们都知道一个原则就是“谁创建,谁释放”,换句话说,不是我们创建的,就不用我们去释放。但是实际上objective-c的内存管理远远没那么简单,我的情况是这样的:
我在debug模式下面用CCLOG在dealloc函数里面输出一些信息,目的就是要检查场景的dealloc方法在replaceScene的 时候有没有被调用,按照子龙山人大哥的说法,如果场景切换的时候dealloc没有调用,说明你这个场景的内存有问题。有可能被某个对象retain了, 其retainCount在replaceScene的时候没有减少到0,所以dealloc方法是不会调用的。如果dealloc方法都没有调掉,那么 这其实就是一种内存泄露。我在检查时,发现一个场景死活不调用dealloc,最后恨不得把所有的游戏逻辑都移除了,还是不走dealloc。
最后的最后才发现实际上是performSelector延时调用的问题,经查找资料,performSelector关于内存管理的执行原理是这 样的执行 [self performSelector:@selector(method1:) withObject:self.tableLayer afterDelay:3]; 的时候,系统会将tableLayer的引用计数加1,执行完这个方法时,还会将tableLayer的引用计数减1,而在我的游戏里这个延时执行函数是 被多次调用的,有时切换场景时延时函数已经被调用但还没有执行,这时tableLayer的引用计数没有减少到0,也就导致了切换场景dealloc方法 没有被调用,出现了内存泄露。
所以最后我的解决办法就是取消那些还没有来得及执行的延时函数,代码很简单:
[NSObject cancelPreviousPerformRequestsWithTarget:self]
当然你也可以一个一个得这样用:
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(method1:) object:nil]
加上了这个以后,切换场景也就很顺利地执行了dealloc方法,至此问题解决!
最后在找资料时也发现了,延时调用实现长按钮的实现思路,记录下来以备后用:
在touchBegan里面
[self performSelector:@selector(longPressMethod:) withObject:nil afterDelay:longPressTime]
然后在end 或cancel里做判断,如果时间不够长按的时间调用:
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(longPressMethod:) object:nil]
取消began里的方法
最后最后总结:
performSelector是一个很有用的函数,跟它打过不少交道,经过血与泪的教训,总结一下它的使用如下:
使用前先检测一下,
SEL testSelector = @selector(test:);
if([tester respondsToSelector:testSelector])
{
//如果响应就执行
[tester test:@"invoke test method"];
}
使用后,如果有必要,需要显示的调用cancelPreviousPerformRequestsWithTarget:selector:object: ,否则有可能产生内存泄露,而且这种内存泄露很难发现,因为它并不违反任何规则,所以一定要注意!
(十七) @selector可以叫做选择器
selector可以叫做选择器,其实指的就是对象的方法,也可以理解为C语言里面的函数指针,在面向对象里面的对应概念。
@selector(xxxx)的作用是找到名字为xxxx的方法。一般用于[a performSelector:@selector(b)];就是说去调用a对象的b方法,和[a b];的意思一样,但是这样更加动态一些。@selector(xxxx)返回的类型是SEL,看方法说明的时候如果参数类型是SEL,那么就是要接受@selector(xxxx)返回的值的那种了。
(十八) 输出坐标frame
NSLog(@"dv===%@",NSStringFromCGRect(dv.frame));
(十九) 计时器NSTimer
计时器NSTimer 方法使用
(本题目1秒钟做一次英雄攻击怪兽m即attackMonster:m共做5次)
千峰视频第7讲里面有计时器
第一种方法
-(void)initTimer{
[NSTimerscheduledTimerWithTimeInterval:1target:selfselector:@selector(do1:)userInfo:nilrepeats:YES];
} 参数解释:1为时间间隔 do1:是要调用的方法 nil是参数 yes是是否执行
第二种方法-(void)initTimer
{
NSTimer *timer;
timer = [NSTimerscheduledTimerWithTimeInterval:1.0
target:self
selector:@selector(handleTimer:)
userInfo:nil
repeats:YES];
[[NSRunLoopcurrentRunLoop ]addTimer:timerforMode:NSRunLoopCommonModes];
int i=5;
while (i>0) {
[[NSRunLoopcurrentRunLoop]runUntilDate:[NSDatedateWithTimeIntervalSinceNow:1.0]];
i--;
}
[timer invalidate];移除timer
}
想在initWithFrame或者其他函数里调用UIGraphicsGetCurrentContext()函数,
结果被告知Invalid Context,查资料。
按照文档中的说法,系统会维护一个CGContextRef的栈,而UIGraphicsGetCurrentContext()会取栈顶的CGContextRef,
正确的做法是只在drawRect里调用UIGraphicsGetCurrentContext(),
因为在drawRect之前,系统会往栈里面压入一个valid的CGContextRef,
除非自己去维护一个CGContextRef,否则不应该在其他地方取CGContextRef。
终于,恍然大悟
(二十一)
自动匹配iphone4或者iphone5屏幕大小
#define iPhone5 ([UIScreen instancesRespondToSelector:@selector(currentMode)] ? CGSizeEqualToSize(CGSizeMake(640, 1136), [[UIScreen mainScreen] currentMode].size) : NO)
#define DIPHONE4 CGRectMake(0, 0, 320, 460)
#define DIPHONE5 CGRectMake(0, 0, 640, 1136)
(二十二)NS、CF、CA、CG、UI***
在IOS开发中,经常会遇到NS开头的对象,这个要从乔帮主历史恩怨说起。当年Steve Jobs 和John Scullery与恩怨,乔帮主当年被人挤兑出苹果,自立门户的时候做了个公司叫做NextStep,里面这一整套开发包很是让一些科学家们喜欢,而现在Mac OS用的就是NextStep这一套函数库。
这些开发NextStep的人们比较自恋地把函数库里面所有的类都用NextStep的缩写打头命名,也就是NS****了。
你还可以看到其他名字打头的一些类,比如CF、CA、CG、UI等等,比如
CFStringTokenizer 这是个分词的东东
CALayer 这表示Core Animation的层
CGPoint 这表示一个点
UIImage 这表示iPhone里面的图片
CF说的是Core Foundation,CA说的是Core Animation,CG说的是Core Graphics,UI说的是iPhone的User Interface……还有很多别的,等你自己去发掘了。
(二十二)
OneV‘s Den在博客里出了10道iOS面试题,用他的话是:"列出了十个应聘Leader级别的高级Cocoa/CocoaTouch开发工程师所应该掌握和理解的技术" 。
在这里給一份我的答案。
1. 你使用过Objective-C的运行时编程(Runtime Programming)么?如果使用过,你用它做了什么?你还能记得你所使用的相关的头文件或者某些方法的名称吗?
Objecitve-C的重要特性是Runtime(运行时),在#import <objc/runtime.h> 下能看到相关的方法,用过objc_getClass()和class_copyMethodList()获取过私有API;使用
```objective-c
Method method1 = class_getInstanceMethod(cls, sel1);
Method method2 = class_getInstanceMethod(cls, sel2);
method_exchangeImplementations(method1, method2);
```
代码交换两个方法,在写unit test时使用到。
2. 你实现过多线程的Core Data么?NSPersistentStoreCoordinator,NSManagedObjectContext和NSManagedObject中的哪些需要在线程中创建或者传递?你是用什么样的策略来实现的?
没实现过多线程的CoreData(待实践)
http://blog.csdn.net/chen505358119/article/details/9344389
http://www.cnblogs.com/rolandash/p/3769127.html
<!--more-->
3. Core开头的系列的内容。是否使用过CoreAnimation和CoreGraphics。UI框架和CA,CG框架的联系是什么?分别用CA和CG做过些什么动画或者图像上的内容。(有需要的话还可以涉及Quartz的一些内容)
UI框架的底层有CoreAnimation,CoreAnimation的底层有CoreGraphics。
UIKit |
------------ |
Core Animation |
Core Graphics |
Graphics Hardware|
使用CA做过menu菜单的展开收起(太逊了)
4. 是否使用过CoreText或者CoreImage等?如果使用过,请谈谈你使用CoreText或者CoreImage的体验。
CoreText可以解决复杂文字内容排版问题。CoreImage可以处理图片,为其添加各种效果。体验是很强大,挺复杂的。
5. NSNotification和KVO的区别和用法是什么?什么时候应该使用通知,什么时候应该使用KVO,它们的实现上有什么区别吗?如果用protocol和delegate(或者delegate的Array)来实现类似的功能可能吗?如果可能,会有什么潜在的问题?如果不能,为什么?(虽然protocol和delegate这种东西面试已经面烂了…)
NSNotification是通知模式在iOS的实现,KVO的全称是键值观察(Key-value observing),其是基于KVC(key-value coding)的,KVC是一个通过属性名访问属性变量的机制。例如将Module层的变化,通知到多个Controller对象时,可以使用NSNotification;如果是只需要观察某个对象的某个属性,可以使用KVO。
对于委托模式,在设计模式中是对象适配器模式,其是delegate是指向某个对象的,这是一对一的关系,而在通知模式中,往往是一对多的关系。委托模式,从技术上可以现在改变delegate指向的对象,但不建议这样做,会让人迷惑,如果一个delegate对象不断改变,指向不同的对象。
6. 你用过NSOperationQueue么?如果用过或者了解的话,你为什么要使用NSOperationQueue,实现了什么?请描述它和GCD的区别和类似的地方(提示:可以从两者的实现机制和适用范围来描述)。
使用NSOperationQueue用来管理子类化的NSOperation对象,控制其线程并发数目。GCD和NSOperation都可以实现对线程的管理,区别是 NSOperation和NSOperationQueue是多线程的面向对象抽象。项目中使用NSOperation的优点是NSOperation是对线程的高度抽象,在项目中使用它,会使项目的程序结构更好,子类化NSOperation的设计思路,是具有面向对象的优点(复用、封装),使得实现是多线程支持,而接口简单,建议在复杂项目中使用。
项目中使用GCD的优点是GCD本身非常简单、易用,对于不复杂的多线程操作,会节省代码量,而Block参数的使用,会是代码更为易读,建议在简单项目中使用。
更详细的答案见我的这篇文章
7. 既然提到GCD,那么问一下在使用GCD以及block时要注意些什么?它们两是一回事儿么?block在ARC中和传统的MRC中的行为和用法有没有什么区别,需要注意些什么?
使用block是要注意,若将block做函数参数时,需要把它放到最后,GCD是Grand Central Dispatch,是一个对线程开源类库,而Block是闭包,是能够读取其他函数内部变量的函数。
更详细的答案见我的这篇文章
8. 您是否做过异步的网络处理和通讯方面的工作?如果有,能具体介绍一些实现策略么?
使用NSOperation发送异步网络请求,使用NSOperationQueue管理线程数目及优先级,底层是用NSURLConnetion,详细可见开源框架[LWConnetion](https://github.com/xunyn/LWConnetionDemo)。
9. 对于Objective-C,你认为它最大的优点和最大的不足是什么?对于不足之处,现在有没有可用的方法绕过这些不足来实现需求。如果可以的话,你有没有考虑或者实践过重新实现OC的一些功能,如果有,具体会如何做?
最大的优点是它的运行时特性,不足是没有命名空间,对于命名冲突,可以使用长命名法或特殊前缀解决,如果是引入的第三方库之间的命名冲突,可以使用link命令及flag解决冲突。
10. 你实现过一个框架或者库以供别人使用么?如果有,请谈一谈构建框架或者库时候的经验;如果没有,请设想和设计框架的public的API,并指出大概需要如何做、需要注意一些什么方面,来使别人容易地使用你的框架。
抽象和封装,方便使用。首先是对问题有充分的了解,比如构建一个文件解压压缩框架,从使用者的角度出发,只需关注发送给框架一个解压请求,框架完成复杂文件的解压操作,并且在适当的时候通知给是哦难过者,如解压完成、解压出错等。在框架内部去构建对象的关系,通过抽象让其更为健壮、便于更改。其次是API的说明文档。
(二十三)ios5的崩溃是因为广告框架的引用。改为弱引用
(二十四)block设成属性,循环引用不释放。
(二十五)命名冲突,一般是引用第三方类库引起的,去掉.m文件的强引用或者使用link命令及flag解决冲突
(二十六)单例的代理设成self,在释放的时候一定要将代理置nil。搜房帮代码
[SouFunSensitiveWordsFilter sharedSensitiveWordsFilter].delegate=self;
dealloc里面[SouFunSensitiveWordsFilter sharedSensitiveWordsFilter].delegate=nil;