objective-c跬步
内存管理规则。
http://www.apple.com.cn/developer/iphone/library/documentation/UserExperience/Conceptual/MemoryMgmt/MemoryMgmt.html
让程序在运行过程中不锁屏
[UIApplication sharedApplication].idleTimerDisabled=YES;//not let iphone go to sleep
获取界面语言设置
NSUserDefaults* defs = [NSUserDefaults standardUserDefaults]; NSArray* languages = [defs objectForKey:@"AppleLanguages"]; NSString* preferredLang = [languages objectAtIndex:0];
NSString 去掉前后 spaces and tab
NSString *textStr = [_msgTextField.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
类变量
与C/C++语言中的静态变量一样,Objective-C 中的类变量就是以 static 声明的变量。(只在当前定义文件中有效)如果子类也想参照父类中的类变量的时候,须定义属性参照方法(类方法)。(这与面向对象中的封装概念有所背驰,降低了凝聚度)
Objective-C中获取类名
NSLog(@"class name>> %@",NSStringFromClass([self class]));
方法二:
Class cls;
cls = [NSString class];
printf("class name %s\n", ((struct objc_class*)cls)->name);
设置应用内的系统控件语言
编辑info.plist,单击右键选择Add Row,名称填入CFBundleLocalizatons,同时向该数组加入一个元素:zh_CN:
<key>CFBundleLocalizations</key>
<array>
<string>zh_CN</string>
<string>en</string>
</array>
NSArray *allControllers = self.navigationController.viewControllers;
UITableViewController *parent = [allControllers lastObject];
[parent.tableViewreloadData];
重写object的respondsToSelector方法,现实出现EXEC_BAD_ACCESS前访问的最后一个object
有时程序崩溃根本不知错误发生在什么地方。比如程序出现EXEC_BAD_ACCESS的时候,虽然大部分情况使用设定 NSZombieEnabled环境变量可以帮助你找到问题的所在,但少数情况下,即使设定了NSZombieEnabled环境变量,还是不知道程序崩 溃在什么地方。那么就需要使用下列代码进行帮助了:
#ifdef _FOR_DEBUG_
-(BOOL) respondsToSelector:(SEL)aSelector {
printf("SELECTOR: %s\n", [NSStringFromSelector(aSelector) UTF8String]);
return [super respondsToSelector:aSelector];
}
#endif
你需要在每个object的.m或者.mm文件中加入上面代码,并且在 other c flags中加入-D _FOR_DEBUG_(记住请只在Debug Configuration下加入此标记)。这样当你程序崩溃时,Xcode的console上就会准确地记录了最后运行的object的方法。
Swift项目:
在Swift Complier - Custom Flags下面的Other Swift Flags中加入-D _FOR_DEBUG_
__attribute__ ((warn_unused_result))的含义
如果某个函数使用了这个关键字,那么函数在被调用的时候,要检查或者使用返回值,某则编译器会进行警告。
使用场合:在把一些功能封装起来(或者SDK的编写)时候,如果对返回值的使用比较重要,那么使用这个关键字提醒编译器要检查返回值是否被利用。
举例:
-(BOOL)TestFunc:(NSInteger) num __attribute__ ((warn_unused_result))
{
return num > 0?YES:NO;
}
如果我这么调用
[self TestFunc:10];
修改UINavigationBar 中 navigationItem 左侧 “返回” 按钮的名称
在父级中:
override func viewDidLoad() { super.viewDidLoad() // 定义所有子页面返回按钮的名称 self.navigationItem.backBarButtonItem = UIBarButtonItem(title: "返回", style: UIBarButtonItemStyle.Plain, target: nil, action: nil) }
什么情况下不会autosynthesis(自动合成)?
- 同时重写了 setter 和 getter 时
- 重写了只读属性的 getter 时
- 使用了 @dynamic 时
- 在 @protocol 中定义的所有属性
- 在 category 中定义的所有属性
重载的属性
_objc_msgForward
消息转发做的几件事:
调用
resolveInstanceMethod:
方法 (或resolveClassMethod:
)。允许用户在此时为该 Class 动态添加实现。如果有实现了,则调用并返回YES,那么重新开始objc_msgSend
流程。这一次对象会响应这个选择器,一般是因为它已经调用过class_addMethod
。如果仍没实现,继续下面的动作。调用
forwardingTargetForSelector:
方法,尝试找到一个能响应该消息的对象。如果获取到,则直接把消息转发给它,返回非 nil 对象。否则返回 nil ,继续下面的动作。注意,这里不要返回 self ,否则会形成死循环。调用
methodSignatureForSelector:
方法,尝试获得一个方法签名。如果获取不到,则直接调用doesNotRecognizeSelector
抛出异常。如果能获取,则返回非nil:创建一个 NSlnvocation 并传给forwardInvocation:
。调用
forwardInvocation:
方法,将第3步获取到的方法签名包装成 Invocation 传入,如何处理就在这里面了,并返回非ni。调用
doesNotRecognizeSelector:
,默认的实现是抛出异常。如果第3步没能获得一个方法签名,执行该步骤。
上面前4个方法均是模板方法,开发者可以override,由 runtime 来调用。最常见的实现消息转发:就是重写方法3和4,吞掉一个消息或者代理给其他对象都是没问题的
也就是说_objc_msgForward
在进行消息转发的过程中会涉及以下这几个方法:
resolveInstanceMethod:
方法 (或resolveClassMethod:
)。forwardingTargetForSelector:
方法methodSignatureForSelector:
方法forwardInvocation:
方法doesNotRecognizeSelector:
方法
自定义的 NSOperation 和 NSThread 需要手动创建自动释放池。比如: 自定义的 NSOperation 类中的 main 方法里就必须添加自动释放池。否则出了作用域后,自动释放对象会因为没有自动释放池去处理它,而造成内存泄露。
但对于 blockOperation 和 invocationOperation 这种默认的Operation ,系统已经帮我们封装好了,不需要手动创建自动释放池。