想询问一个objective c编程-c的UIView的draw问题

Objective-C 理解之方括号[  ]的使用
我的图书馆
Objective-C 理解之方括号[  ]的使用
1. 用于通知某个对象该做什么即通知对象去执行某动作
1.1. 在Objective-C中,方括号还有其它意义:它们用于通知某个对象该做什么。
//这句话说明,通知对象shape去执行draw这个动作,例如让一个rectangle去画一个矩形。&
1.2. 在Objective-C中,通知对象执行某种操作,被称为:发送消息。
//表示向对象shape发送draw消息。
2. 创建新对象
为了创建新对象,我们需要向相应的类发送new消息。
该类接收并处理完new消息后,我们就会得到一个可以使用的新对象实例了。
id Shape[3];
Shape[0] = [Circle
//向Circle类发送new消息,则创建了新对象,并把该新对象赋给Shape[0].
3. 在类中向超类发送消息
3.1 例如:
@interface Circle : Shape
@end // Circle
@implementation Circle
-(void) SetFillColor:(ShapeColor) c {
&&& if (c ==
kRedColor) {
c& = kGreenC
setFillColor:c];& //
向超类Shape发送消息,超类将会执行它的setFillColor方法。
@end //Circle
3.2 例如:
self = [super init];&
//作用是,使超类NSObject完成它的初始化工作。并且如果返回一个新对象,
&&&&&&&&&&&&&&&&&&&&&&//则需要更新self。
TA的最新馆藏[转]&[转]&[转]&
喜欢该文的人也喜欢Objective-C 2015新特性 - IOS - 伯乐在线
& Objective-C 2015新特性
刚开始做iOS开发的那些日子。 我仍然记得几年前买的那些老书籍。现在他们静静的躺在我办公室的书架上。多年前我虔诚的翻阅它们的时候,我不禁担心Objective-C做不到什么而不是它能做到的事。 今年(Objective-C)能做更多事了。本周我们会看到一个成熟的老朋友。让我们来看下Objective-C有什么提高吧。
朋友们,让我们去那条走过很多次的小道散散步。
Objective-C
@property (strong, nonatomic) NSArray *someV
@property (strong, nonatomic) NSArray *someViews;
这是一个熟练的Objective-C开发者的标准写法。表示包含一些视图的集合属性。但是有一些内在的缺陷隐藏在这一小段代码中。 它可以返回空吗? 除非有文档说明或者这个开发者在现场,我们不能单凭看这些代码得到答案。 这里面除了UIView类型对象之外还有其他类型的对象吗? 和上面类似,谁知道呢?或许可以使用反射做判断(译者注:这里指的是isKindOfClass之类的方法)?或者这里能有除了UIView之外的对象吗?或者说UIView的任何子类? 看起来这会需要很多转换 因为这是包含某些对象的数组,当某人找出这个数组里面对象类型——用它来做一些事时会花费很长的时间。 这削弱了Swift代码和可读性 不幸的是,Swift有泛型。这意味着,一个集合类型被看做可选的任意对象类型。当使用这个属性的时候,(这个特点)强迫开发者对Swift和Objective-C进行转换。
当你知道一个简单的属性会引起这么多问题时可能有点不舒服。维护有潜在问题的代码更容易出错,更别提在上述语言和一个新的语言(如Swift)之间交互了。 能够让这件事变的简单的第一步是我最喜欢的Objective-C新特性——可空注释。这些注释在编程中提供了一些非常有价值的东西。 意图 他们详细地描述了一个API。能返回空(nil),不能返回空。简单来说,可以避免花几个小时在调试上。有三个可用值:
nullable(可以为 nil 或 NULL)——对应(在Swift中的使用方式)’ UIView?’
nonnull (不为 nil,如果传 nil 给该指针,将会收到编辑器的警告)——对应(在Swift中的使用方式)’UIView’
null_unspecified(是否为 nil 是不确定的)——对应(在Swift中的使用方式)’UIView!’
让我们再看一下例子中的那个属性。假设这个属性是用来在运行时创建一些用户界面的迭代器。这种情况下,这里应该存放的是一些按钮和视图。 但是天呐——他们在任何情况下都不应该为空。现在应该这样写:
Objective-C
@property (strong, nonatomic, nonnull) NSArray *someV
@property (strong, nonatomic, nonnull) NSArray *someViews;
不仅这对Objective-C有帮助,现在这个属性也使得Swift里不再到处是optionals。 开发者看到这些代码就知道它是不是会返回空指针。好极了。 我们已经改良了静态检查、Swift的可用性以及这些API使用时最重要的意图。
全世界使用Objective-C的开发者都很高兴。哎呀,泛型遍布各地,这些应该归功于勇敢的开发者。 如果Cocoa Touch是孩子的睡前故事并且Objective-C是主人公,这本书肯定以上面几句话结尾。长期以来,泛型的缺席一直是很多开发者的痛处。 尽管用了32年,Objective-C现在有泛型了。尽管沉浸在Swift 2 发布的喜悦中,WWDC 15的参会者和消费者等不应该轻视这个消息。它代表了很多改变,而且大多都是积极的。 回到我们的属性。我们现在可以写下来告诉编译器和开发者这里要求的是UIView。
Objective-C
@property (strong, nonatomic, nonnull) NSArray&UIView *& *someV
@property (strong, nonatomic, nonnull) NSArray&UIView *& *someViews;
这很好,因为如果一个人试着把除了UIViews之外的对象赋值给这个属性,那么编译器会提示和警告。这也会省去了一些头疼的转换。 Swift也很高兴。在最近的更新中,我们让Swift知道一些对象不是可选的。现在Swift也知道这里面包含了UIView,所以可以摆脱任何有歧义的对象声明。 开发者可以像C#、C++、Swtft以及其他语言一样,使用&&括号标识类型。虽然这(符号)代表了遵循协议一致性,编译器经过推断知道何时、何地、如何运用它们。 长远来看,参数化扩展(extensions)、类目(categories)和类(classes)也会成为可能。带来的好处不仅在集合类。泛型这个特性可以用在Objective-C的任何地方,容器类只是其中之一。例如,看着下面的NSDictionary 类会让你展开微笑:
Objective-C
@interface NSDictionary&KeyType, ObjectType& (Lookup)
- (nullable ObjectType)objectForKey:(KeyType)aK
@interface NSDictionary&KeyType, ObjectType& (Lookup)- (nullable ObjectType)objectForKey:(KeyType)aKey;@end
尽管在我知道泛型是通过类型擦除来实现时有点失望,考虑到Objective-C老代码中大量遗留问题你就会懂(为什么这样做)。 类型擦除实现了二进制兼容,它也允许不改变Objective-C运行时。所以亲爱的开发者,皱皱眉头,抱怨一下C#的泛型实现确实比任何其他语言都好,我们还是要接着工作。
KindOf 类型
哎,我们的旅行还剩重要的一步。回忆一下我们提到可以包UIView的属性。所以,正常情况下能推断这里面包含了一些视图和按钮。 有了这些,当有人写出下面这样的代码时会发生什么呢:
Objective-C
[self.someViews[0] addTarget:self action:selector(aMethod:) forControlEvents:UIControlEventTouchUpInside];
[self.someViews[0] addTarget:self action:selector(aMethod:) forControlEvents:UIControlEventTouchUpInside];
啊,一个编译器警告。 这很正常,因为尽管在这个属性中插入一个按钮是有效的,并且你也可以说它是一个视图,在转换前无法确定它就是一个按钮。 这种情况比想象中发生的要多,利用KindOf新特性很容易解决这个问题。回到这个例子中的属性。
Objective-C
@property (strong, nonatomic, nonnull) NSArray&__kindof UIView *& *someV
@property (strong, nonatomic, nonnull) NSArray&__kindof UIView *& *someViews;
实际上,我们告诉编译器这个属性和它的容器可以包含UIView类型的对象。类型契约中支持了更多的我们以前没有的类型信息。 其本质是什么?向下转型。 这意味着代码在编译器上运行良好,因为编译器知道肯定有一个按钮在容器内。 现在,如果你再回头看最初的担心,他们都被搞定了。 当Swift否定者对(Objective-C)的价值大加赞赏时,他们也应该心存感激。因为(Objective-C语言)价值的提升基于一点:Swift的交互性。 尽管如此,在一些特殊的场合,Objective-C是比以前更强大。
Objective-C是我编程生涯的初恋。它是与众不同(到现在仍是),它的显著优点以及缺点都让我着迷。现在Swift快速赢得了我这颗编程之心,我仍然发现我在使用Objective-C时很快乐。这些新特性很受欢迎。它们能够被用来编写更好的代码,并且它们已经在Foundation框架中随处可见了。
关于作者:
可能感兴趣的话题
关于iOS频道
iOS频道分享iOS和Swift开发,应用设计和推广,iOS相关的行业动态。
新浪微博:
推荐微信号
(加好友请注明来意)
– 好的话题、有启发的回复、值得信赖的圈子
– 分享和发现有价值的内容与观点
– 为IT单身男女服务的征婚传播平台
– 优秀的工具资源导航
– 翻译传播优秀的外文文章
– 国内外的精选文章
– UI,网页,交互和用户体验
– 专注iOS技术分享
– 专注Android技术分享
– JavaScript, HTML5, CSS
– 专注Java技术分享
– 专注Python技术分享
& 2017 伯乐在线Howdy, Stranger!
It looks like you're new here. If you want to get involved, click one of these buttons!
Objective-C static public variable?
Im an old Java developer, staring on Objective-C. In Java I often declare some static variables to be used to test on later, like this:
public class Foo {
public static int TYPE_CIRCLE = 0;
public static int TYPE_SQUARE = 1;
public void draw(int type) {
if(type == TYPE_CIRCLE) {
And then I can use this from another class like this:
public class Bar {
Foo f = new Foo();
f.draw(Foo.TYPE_CIRCLE);
Can I do something like this in Objective-C, or what do you guys do to archive something like this?
Post edited by neigaard on January 20110
the apple dev docs has got some useful info on static variables:
When you define a new class of objects, you can decide what instance
variables they should have. Every instance of the class will have its
own copy of all the v each object controls its own
However, you can't prescribe variables
no &class variable& counterparts to instance variables. Only internal
data structures, initialized from the class definition, are provided for
the class. The class object also has no access to the instance variables
it can't initialize, read, or alter them.
Therefore, for all the instances of a class to share data, an external
variable of some sort is required. Some classes declare static variables
and provide class methods to manage them. (Declaring a variable static
in the same file as the class definition limits its scope to just the
class-and to just the part of the class that's implemented in the file.
Unlike instance variables, static variables can't be inherited by
subclasses.)
Static variables help give the class object more functionality than just
that of a &factory& it can approach being a
complete and versatile object in its own right. A class object can be
used to coordinate the instances it creates, dispense instances from
lists of objects already created, or manage other processes essential to
the application. In the case when you need only one object of a
particular class, you can put all the object's state into static
variables and use only class methods. This saves the step of allocating
and initializing an instance.
Im an old Java developer, staring on Objective-C. In Java I often declare some static variables to be used to test on later, like this:
public class Foo {
public static int TYPE_CIRCLE = 0;
public static int TYPE_SQUARE = 1;
public void draw(int type) {
if(type == TYPE_CIRCLE) {
And then I can use this from another class like this:
public class Bar {
Foo f = new Foo();
f.draw(Foo.TYPE_CIRCLE);
Can I do something like this in Objective-C, or what do you guys do to archive something like this?主题 : 困惑,学完Objective-C基础后怎么学UIView等iOS基础知识?
级别: 新手上路
可可豆: 11 CB
威望: 11 点
在线时间: 20(时)
发自: Web Page
来源于&&分类
困惑,学完Objective-C基础后怎么学UIView等iOS基础知识?&&&
困惑,学完Objective-C基础后怎么学UIView等iOS基础知识?最后能不能详细说下 iOS开发 学习路线?
级别: 侠客
可可豆: 220 CB
威望: 210 点
在线时间: 116(时)
发自: Web Page
接着学习UI控件
级别: 精灵王
发帖: 3023
可可豆: 3353 CB
威望: 3331 点
在线时间: 4703(时)
发自: Web Page
找些简单有趣的小项目来做做,可以跟着书走,例如apress的水果系列,有一本是基础的,每个章节都有一个小项目带你认识各种控件的使用,比起那些罗列参数属性少有实用例子的教材好。
级别: 新手上路
UID: 528615
可可豆: 85 CB
威望: 57 点
在线时间: 104(时)
发自: Web Page
看看吧。。。。。。。。。。。
描述:学习路线图
图片:iOS学习路线图.jpg
级别: 圣骑士
UID: 452831
可可豆: 1416 CB
威望: 1103 点
在线时间: 648(时)
发自: Web Page
找一套配信机构的教学视频学就行,跟着步骤走就行,然后最主要的还是自己多写代码,这事最主要的
喜欢iOS的可以逛一下我的论坛
级别: 骑士
UID: 268348
可可豆: 1650 CB
威望: 1103 点
在线时间: 383(时)
发自: Web Page
控件的使用难道不应该算是object-c的基础吗?不然到底什么算基础
级别: 侠客
UID: 522827
可可豆: 432 CB
威望: 293 点
在线时间: 223(时)
发自: Web Page
找网上的视频跟着学,关于学习方法,我认为每个人的学习方法都不一样,需要自己慢慢摸索
级别: 新手上路
可可豆: 11 CB
威望: 11 点
在线时间: 20(时)
发自: Web Page
谢谢各位,只是觉得看完BNR的Objective-C Programming后有点无从下手了。去github上找的开源项目,不知道如何入手,想模仿一个都感觉力不从心。直接上OC项目有点困难。请问接下去改如何做呢?我的选择是1.看完斯坦福老爷爷的iOS7的视频,并完成课后练习。2继续看BNR的另一本iOS Programming,并完成相应练习。3开始仿照里的教程一步步写几个小应用。请问那个应该先进行呢?还是说大家觉得有更好的办法?
级别: 侠客
UID: 527892
可可豆: 404 CB
威望: 367 点
在线时间: 313(时)
发自: iPhone
我刚学到UI,楼主加个好友不,互相学习
关注本帖(如果有新回复会站内信通知您)
发帖、回帖都会得到可观的积分奖励。
按"Ctrl+Enter"直接提交
关注CocoaChina
关注微信 每日推荐
扫一扫 关注CVP公众号
扫一扫 浏览移动版小站会根据您的关注,为您发现更多,
看到喜欢的小站就马上关注吧!
下一站,你会遇见谁的梦想?
发布一些iOS开发相关的内容,Xcode开发的一些诀窍,Cocos2d-iPhone的游戏开发的介绍.
iOS判断一个字符串中是否都是数字
第一种方式是使用NSScanner:
1. 整形判断
- (BOOL)isPureInt:(NSString&*)string{
NSScanner* scan = [NSScanner&scannerWithString:string];&
return&[scan&scanInt:&val] && [scan&isAtEnd];
2.浮点形判断:
- (BOOL)isPureFloat:(NSString&*)string{
NSScanner* scan = [NSScanner&scannerWithString:string];&
return&[scan&scanFloat:&val] && [scan&isAtEnd];
第二种方式是使用循环判断
- (BOOL)isPureNumandCharacters:(NSString *)text
& & for(int i = 0; i & [text length]; ++i)&{
& && &&&int a = [text characterAtIndex:i];
& && &&&if ([self isNum:a]){
& && && && &
& && &&&} else {
& && && && &return NO;
& & return YES;
或者 C语言中常用的方式.
- (BOOL)isAllNum:(NSString *)string{& && & for (int i=0; i&string. i++) {& && &&&c=[string characterAtIndex:i];& && &&&if (!isdigit(c)) {& && && && &return NO;& && &&&}& & }& & return YES;}
第三种方式则是使用NSString的trimming方法
- (BOOL)isPureNumandCharacters:(NSString *)string
string = [string stringByTrimmingCharactersInS[NSCharacterSet decimalDigitCharacterSet]];
if(string.length & 0)
& & &return NO;
return YES;
以上三种能够帮助实现判断是否为数字的函数,iOS中没有直接判断是否是数字的方法,所以只能够自己添加方法去实现了.
iOS6屏幕旋转详解(自动旋转、手动旋转、兼容IOS6之前系统)
概述:在iOS6之前的版本中,通常使用&shouldAutorotateToInterfaceOrientation&来单独控制某个UIViewController的方向,需要哪个viewController支持旋转,只需要重写shouldAutorotateToInterfaceOrientation方法。但是iOS 6和iOS 7里屏幕旋转改变了很多,之前的&shouldAutorotateToInterfaceOrientation 被列为&DEPRECATED 方法,查看UIViewController.h文件也可以看到:&
//&Applications&should&use&supportedInterfaceOrientations&and/or&shouldAutorotate.. &-&(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation&NS_DEPRECATED_IOS(2_0,&6_0); &&系统给了如下2个方法来代替:&
-&(BOOL)shouldA &
-&(NSUInteger)supportedInterfaceO &&除了重写这个2个方法,IOS6里面要旋转还有一些需要注意的地方,下面会细述。另外还有一个硬性条件,需要在Info.plist文件里面添加程序支持的所有方向,可以通过以下2种方式添加&1. 在Info.plist的Supported interface orientations的数组里面增加想要的方向,另外,放在第一个的,会在模拟器上默认进入的样式.2. 或者也可以工程的Target的General里面直接选择想要的方向.&另外要兼容IOS6之前的系统,要保留原来的&shouldAutorotateToInterfaceOrientation 方法,还有 willRotateToInterfaceOrientation 等方法。&
IOS6&7自动旋转设置:IOS6以上的系统里面,控制某个viewController旋转并不是像IOS5以下那样在这个viewController里面重写上面那2个方法,而是需要在这个viewController的rootViewController(根视图控制器)里面重写,怎么解释呢?就是最根的那个viewController,直接跟self.window接触的那个controller,比如以下代码:&&
UIViewController&*viewController&=&[[UIViewController&alloc]&init]; UINavigationController&*naviController =&[[UINavigationController&alloc]&initWithRootViewController:&viewController]; &
if&([window&respondsToSelector:@selector(setRootViewController:)])&{
& & & &self.window.rootViewController&=&naviController; &
& & & &[self.window&addSubview:&naviController.view]; &
如果需要设置viewController的旋转,那么不能在UIViewController里面重写shouldAutorotate和supportedInterfaceOrientations方法,而是需要在naviController里面设置,又因为UINavigationController是系统控件,所以这里需要新建一个UINavigationController的子navigationController的子类,然后在里面实现shouldAutorotate和supportedInterfaceOrientations方法,比如:&
-(NSUInteger)supportedInterfaceOrientations{
& & & & &return&UIInterfaceOrientationMaskAllButUpsideD
&-&(BOOL)shouldAutorotate{ &
& & & &return&YES;
} &&例如:如果上面的例子是self.window.rootViewController =&viewController,而不是naviController,那么上面的那2个控制旋转的方法就应该写在UIViewController里面!
例如:如果viewController又pushViewController到viewController2,需要设置viewController2的旋转,怎么办呢? 还是在naviController里面控制,因为viewController1和viewController2的rootViewController都是naviController,一般的写法都是&
UIViewController&*&viewController2&=&[[UIVewController&alloc]&init]; &[self.navigationController.navigationController&pushViewController:&viewController2&animated:YES]; &&
所以要控制一个UINavigationController push到的所有viewController的旋转,那么就得在naviController里面区分是哪个viewController,以便对他们一一控制!同样如果rootViewController是UITabbarController,那么需要在子类化的UITabbarController里面重写那2个方法,然后分别控制!&
但是有时候我初始化UINavigationController的时候,并不知道所有我所有需要push到的viewController,那么这里有一个通用的方法,就是让viewController自己来控制自己,首先在navCtrl里面的实现方法改为以下方式:&
-&(BOOL)shouldAutorotate
& & & & &return [self.topViewController shouldAutorotate];
(NSUInteger)supportedInterfaceOrientations
& & & & &return [self.topViewController supportedInterfaceOrientations];
} &&全部调用self.topViewController,就是返回当前呈现出来的viewController里面的设置,然后在viewController、viewController2等等这些viewController里面重写shouldAutorotate和supportedInterfaceOrientations,以方便设置每个viewController的旋转
例如:如果viewController&是&presentModalViewController 到&viewController3,那么viewController3的旋转设置就不在naviController里面了!如果presentModalViewController的viewController是naviController、tabbarController包装过的viewController3,那么就应在新包装的navController、tabbarController里面设置,如果是直接presentModalViewController到viewController3,那么就在viewController3里面设置
IOS5以下的自动旋转设置
这个简单很多,没有上面的硬性条件,只需要在需要旋转的viewController里面重写&shouldAutorotateToInterfaceOrientation 方法就行&
手动旋转手动旋转也有2种方式,一种是直接设置&UIDevice 的 orientation,(私有方法,而且测试的时候,第一次有效,第二次设置的时候就会存在问题.)但是这种方式不推荐,上传appStore有被拒的风险:&
if&([[UIDevice&currentDevice]&respondsToSelector:@selector(setOrientation:)]) {
& & & & &[[UIDevice&currentDevice]&performSelector:@selector(setOrientation:)&withObject:(id)UIInterfaceOrientationPortrait];
}&第二种是假旋转,并没有改变&UIDevice 的 orientation,而是改变某个view的&transform,利用&CGAffineTransformMakeRotation&来达到目的,比如:
self.view.transform&=&CGAffineTransformMakeRotation(M_PI/2) &&
下面讲解采用第二种方式的各版本手动旋转:思想是首先设置&statusBarOrientation,然后再改变某个view的方向跟&statusBarOrientation 一致!&
IOS6&7的手动旋转:1. 那既然是旋转,最少也得有2个方向,那么还是少不了上面说的那个硬性条件,先在plist里面设置好所有可能需要旋转的方向。既然是手动旋转,那么就要关闭自动旋转:
-&(BOOL)shouldAutorotate{ &
& & & & return&NO;
}&2.手动触发某个按钮,调用方法,这个方法的实现如下:&
[[UIApplication&sharedApplication]&setStatusBarOrientation:UIInterfaceOrientationLandscapeRight];
self.view.transform&=&CGAffineTransformMakeRotation(M_PI/2); &
self.view.bounds&=&CGRectMake(0,&0,&kScreenHeight,&320); &
注意:1. 只需要改变self.view.transform,那么self.view的所有subview都会跟着自动变;其次因为方向变了,所以self.view的大小需要重新设置,不要使用self.view.frame,而是用bounds。2. 如果shouldAutorotate 返回YES的话,下面设置setStatusBarOrientation 是不管用的!setStatusBarOrientation只有在shouldAutorotate 返回NO的情况下才管用!&
IOS5以下的手动旋转:1.在需要手动旋转的viewController里的 shouldAutorotateToInterfaceOrientation 方法设置 interfaceOrientation == [UIApplicationsharedApplication].statusBarOrientation&
-&(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation{
& & & & return&(interfaceOrientation&==&[UIApplication&sharedApplication].statusBarOrientation); &} &
2.手动触发某个按钮,调用方法,这个方法的实现如下:&
[[UIApplication&sharedApplication]&setStatusBarOrientation:UIInterfaceOrientationLandscapeRight];
self.view.transform&=&CGAffineTransformMakeRotation(M_PI/2);
self.view.bounds&=&CGRectMake(0,&0,&kScreenHeight,&320); &
注意:只需要改变self.view.transform,那么self.view的所有subview都会跟着自动变;其次因为方向变了,所以self.view的大小需要重新设置,不要使用self.view.frame,而是用bounds。&&
经验分享:1.IOS6&7里面,如果一个项目里面需要各种旋转支持,有自动,有手动,那么我们可以新建2个navController或者tabbarController的子类,一个是不旋转,一个旋转,那么所有需要旋转的UINavigationController都可以用这个子类来代替!包括我们可以定制短信呀、邮件呀的旋转!2.supportedInterfaceOrientations 方法一般是写UIInterfaceOrientationMask方向,但是如果程序要兼容4.3以下的SDK(4.3以下的SDK必须是4.5以下的Xcode,不支持IOS6),那么在用4.5以下的Xcode编译的时候通不过!所以可以用statusBarOrientation代替或者直接写死数字!&
-(NSUInteger)supportedInterfaceOrientations{
& & & & &return&[UIApplication&sharedApplication].statusBarO &
} &&3.一般都不建议在程序里面直接调用 UIDeviceOrientation 的方向,而是用 UIInterfaceOrientation,他们之间是不同的&
UIInterfaceOrientationLandscapeLeft&=&UIDeviceOrientationLandscapeRight, UIInterfaceOrientationLandscapeRight&=&UIDeviceOrientationLandscapeLeft &&看到吗,左右是反的!Xcode图形化设置方向也是以 UIInterfaceOrientation 为准,就是home按键所在的方向
iOS NSMutableDictionary使用枚举器的时候删除数据出现 Exception
&& & & & 今天使用NSMutableDictionary的时候,使用forin枚举的方式枚举一个字典里面所有的元素,在枚举的时候,如果符合某个条件,就删除这一条数据。& & & & 错误如下:*** Terminating app due to uncaught exception 'NSGenericException', reason: '*** Collection &__NSDictionaryM: 0x& was mutated while being enumerated.'
& & &&代码如下:&
NSMutableDictionary *dic= [NSMutableDictionary&dictionaryWithObjectsAndKeys:
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& @"Value1",@"Key1",
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& @"Value2",@"Key2",
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& @"Value3",@"Key3",
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& @"Value4",@"Key4",
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& nil];
for (NSString *key in dic)
& &&if([[dic objectForKey: key] isEqualTo:&@"Value2"])
& & & & &[dic removeObjectForKey: key];
}修改如下:
NSArray *keyArr = [dic allKeys];&& & & & & &&for (NSString *key in keyArr)
NSMutableDictionary&*dic= [NSMutableDictionary&dictionaryWithObjectsAndKeys:
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&@"Value1",@"Key1",
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&@"Value2",@"Key2",
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&@"Value3",@"Key3",
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&@"Value4",@"Key4",
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&nil];
NSArray&*keyArr = [dic&allKeys];//只要增加这一个就可以解决问题了,相对比较方便
for&(NSString&*key&in&keyArr)//修改dic为keyArr,这样枚举的时候使用的是keyArr,修改的是另一个
& &&if([[dic&objectForKey: key]&isEqualTo:&@"Value2"])
& & & & &[dic&removeObjectForKey: key];
The Tumblr Architecture Yahoo Bought For A Cool Billion Dollars
It's being reported&Yahoo bought Tumblr for $1.1 billion. You may recall&Instagram was profiled on HighScalability&and they were also bought by Facebook for a ton of money. A coincidence? You be the judge.
Just what is Yahoo buying? The business acumen of the deal is not something I can judge, but if you are doing due diligence on the technology then Tumblr would probably get a big thumbs up. To see why, please keep on reading...
With over 15 billion page views a month Tumblr has become an insanely popular blogging platform. Users may like Tumblr for its simplicity, its beauty, its strong focus on user experience, or its friendly and engaged community, but like it they do.&
Growing at over 30% a month has not been without challenges. Some reliability problems among them. It helps to realize that Tumblr operates at surprisingly huge scales: 500 million page views a day, a peak rate of ~40k requests per second, ~3TB of new data to store a day, all running on 1000+ servers.
One of the common patterns across successful startups is the perilous chasm crossing from startup to wildly successful startup. Finding people, evolving infrastructures, servicing old infrastructures, while handling huge month over month increases in traffic, all with only four engineers, means you have to make difficult choices about what to work on. This was Tumblr&s situation. Now with twenty engineers there&s enough energy to work on issues and develop some very interesting solutions.
Tumblr started as a fairly typical large LAMP application. The direction they are moving in now is towards a distributed services model built around Scala, HBase, Redis, Kafka, Finagle, &and an intriguing cell based architecture for powering their Dashboard. Effort is now going into fixing short term problems in their PHP application, pulling things out, and doing it right using services.&
The theme at Tumblr is transition at massive scale. Transition from a LAMP stack to a somewhat bleeding edge stack. Transition from a small startup team to a fully armed and ready development team churning out new features and infrastructure. To help us understand how Tumblr is living this theme is startup veteran&Blake Matheny, Distributed Systems Engineer at Tumblr. Here&s what Blake has to say about the House of Tumblr:
500 million page views a day
15B+ page views month
~20 engineers
Peak rate of ~40k requests per second
1+ TB/day into Hadoop cluster
Many TB/day into MySQL/HBase/Redis/Memcache
Growing at 30% a month
~1000 hardware nodes in production
Billions of page visits per month per engineer
Posts are about 50GB a day. Follower list updates are about 2.7TB a day.
Dashboard runs at a million writes a second, 50K reads a second, and it is growing.
OS X for development, Linux (CentOS, Scientific) in production
PHP, Scala, Ruby
Redis, HBase, MySQL
Varnish, HA-Proxy, nginx,
Memcache, Gearman, Kafka,&Kestrel, Finagle
Thrift, HTTP
Func&- a secure, scriptable remote control framework and API
Git, Capistrano, Puppet, Jenkins
500 web servers
200 database servers (many of these are part of a spare pool we pulled from for failures)
30 memcache servers
22 redis servers
15 varnish servers
25 haproxy nodes
14 job queue servers (kestrel + gearman)
Architecture
Tumblr has a different usage pattern than other social networks.
With 50+ million posts a day, an average post goes to many hundreds of people. It&s not just one or two users that have millions of followers. The graph for Tumblr users has hundreds of followers. This is different than any other social network and is what makes Tumblr so challenging to scale.
#2 social network in terms of time spent by users. The content is engaging. It&s images and videos. The posts aren&t byte sized. They aren&t all long form, but they have the ability. People write in-depth content that&s worth reading so people stay for hours.
Users form a connection with other users so they will go hundreds of pages back into the dashboard to read content. Other social networks are just a stream that you sample.
Implication is that given the number of users, the average reach of the users, and the high posting activity of the users, there is a huge amount of updates to handle.
Tumblr runs in one colocation site. Designs are keeping geographical distribution in mind for the future.
Two components to Tumblr as a platform: public&Tumblelogs&and&Dashboard
Public Tumblelog is what the public deals with in terms of a blog. Easy to cache as its not that dynamic.
Dashboard is similar to the Twitter timeline. Users follow real-time updates from all the users they follow.
Very different scaling characteristics than the blogs. Caching isn&t as useful because every request is different, especially with active followers.
Needs to be real-time and consistent. Should not show stale data. And it&s a lot of data to deal with. Posts are only about 50GB a day. Follower list updates are 2.7TB a day. Media is all stored on S3.
Most users leverage Tumblr as tool for consuming of content. Of the 500+ million page views a day, 70% of that is for the Dashboard.
Dashboard availability has been quite good. Tumblelog hasn&t been as good because they have a legacy infrastructure that has been hard to migrate away from. With a small team they had to pick and choose what they addressed for scaling issues.
Old Tumblr
When the company started on Rackspace it gave each custom domain blog an A record. When they outgrew Rackspace there were too many users to migrate. This is 2007. They still have custom domains on Rackspace. They route through Rackspace back to their colo space using HAProxy and Varnish. Lots of legacy issues like this.
A traditional LAMP progression.
Historically developed with PHP. Nearly every engineer programs in PHP.
Started with a web server, database server and a PHP application and started growing from there.
To scale they started using memcache, then put in front-end caching, then HAProxy in front of the caches, then MySQL sharding. MySQL sharding has been hugely helpful.
Use a squeeze everything out of a single server approach. In the past year they&ve developed a couple of backend services in C: an&ID generator&and&Staircar, using Redis to power Dashboard notifications
The Dashboard uses a scatter-gather approach. Events are displayed when a user access their Dashboard. Events for the users you follow are pulled and displayed. This will scale for another 6 months. Since the data is time ordered sharding schemes don&t work particularly well.
New Tumblr
Changed to a JVM centric approach for hiring and speed of development reasons.
Goal is to move everything out of the PHP app into services and make the app a thin layer over services that does request authentication, presentation, etc.
Scala and Finagle Selection
Internally they had a lot of people with Ruby and PHP experience, so Scala was appealing.
Finagle was a compelling factor in choosing Scala. It is a library from Twitter. It handles most of the distributed issues like distributed tracing, service discovery, and service registration. You don&t have to implement all this stuff. It just comes for free.
Once on the JVM Finagle provided all the primitives they needed (Thrift, ZooKeeper, etc).
Finagle is being used by Foursquare and Twitter. Scala is also being used by Meetup.
Like the Thrift application interface. It has really good performance.
Liked Netty, but wanted out of Java, so Scala was a good choice.
Picked Finagle because it was cool, knew some of the guys, it worked without a lot of networking code and did all the work needed in a distributed system.
Node.js wasn&t selected because it is easier to scale the team with a JVM base. Node.js isn&t developed enough to have standards and best practices, a large volume of well tested code. With Scala you can use all the Java code. There&s not a lot of knowledge of how to use it in a scalable way and they target 5ms response times, 4 9s HA, 40K requests per second and some at 400K requests per second. There&s a lot in the Java ecosystem they can leverage.
Internal services are being shifted from being C/libevent based to being Scala/Finagle based.
Newer, non-relational data stores like HBase and Redis are being used, but the bulk of their data is currently stored in a heavily partitioned MySQL architecture. Not replacing MySQL with HBase.
HBase backs their URL shortner with billions of URLs and all the historical data and analytics. It has been rock solid. HBase is used in situations with high write requirements, like a million writes a second for the Dashboard replacement. &HBase wasn&t deployed instead of MySQL because they couldn&t bet the business on HBase with the people that they had, so they started using it with smaller less critical path projects to gain experience.
Problem with MySQL and sharding for time series data is one shard is always really hot. Also ran into read replication lag due to insert concurrency on the slaves.
Created a common services framework.
Spent a lot of time upfront solving operations problem of how to manage a distributed system.
Built a kind of Rails scaffolding, but for services. A template is used to bootstrap services internally.
All services look identical from an operations perspective. Checking statistics, monitoring, starting and stopping all work the same way for all services.
Tooling is put around the build process in&SBT&(a Scala build tool) using plugins and helpers to take care of common activities like tagging things in git, publishing to the repository, etc. Most developers don&t have to get in the guts of the build system.
Front-end layer uses HAProxy. Varnish might be hit for public blogs. 40 machines.
500 web servers running Apache and their PHP application.
200 database servers. Many database servers are used for high availability reasons. Commodity hardware is used an the MTBF is surprisingly low. Much more hardware than expected is lost so &there are many spares in case of failure.
6 backend services to support the PHP application. A team is dedicated to develop the backend services. A new service is rolled out every 2-3 weeks. Includes dashboard notifications, dashboard secondary index, URL shortener, and a memcache proxy to handle transparent sharding.
Put a lot of time and effort and tooling into&MySQL sharding. MongoDB is not used even though it is popular in NY (their location). MySQL can scale just fine..
Gearman, a job queue system, is used for long running fire and forget type work.
Availability is measured in terms of reach. Can a user reach custom domains or the dashboard? Also in terms of error rate.
Historically the highest priority item is fixed. Now failure modes are analyzed and addressed systematically. Intention is to measure success from a user perspective and an application perspective. If part of a request can&t be fulfilled that is account for
Initially an Actor model was used with Finagle, but that was dropped. &For fire and forget work a job queue is used. In addition, Twitter&s&utility library&contains a&Futuresimplementation and services are implemented in terms of futures. In the situations when a thread pool is needed futures are passed into a future pool. Everything is submitted to the future pool for asynchronous execution.
Scala encourages no shared state. Finagle is assumed correct because it&s tested by Twitter in production. Mutable state is avoided using constructs in Scala or Finagle. No long running state machines are used. State is pulled from the database, used, and writte n back to the database. Advantage is developers don&t need to worry about threads or locks.
22 Redis servers. Each server has 8 - 32 instances so 100s of Redis instances are used in production.
Used for backend storage for dashboard notifications.
A notification is something &like a user liked your post. Notifications show up in a user&s dashboard to indicate actions other users have taken on their content.
High write ratio made MySQL a poor fit. &
Notifications are ephemeral so it wouldn&t be horrible if they were dropped, so Redis was an acceptable choice for this function.
Gave them a chance to learn about Redis and get familiar with how it works.
Redis has been completely problem free and the community is great.
A Scala futures based interface for Redis was created. This functionality is now moving into their Cell Architecture.
URL shortener uses Redis as the first level cache and HBase as permanent storage.
Dashboard&s secondary index is built around Redis.
Redis is used as Gearman&s persistence layer using a memcache proxy built using Finagle.
Slowly moving from memcache to Redis. Would like to eventually settle on just one caching service. Performance is on par with memcache.
Internal Firehose
Internally applications need access to the activity stream. An activity steam is information about users creating/deleting posts, liking/unliking posts, etc. &A challenge is to distribute so much data in real-time. Wanted something that would scale internally and that an application ecosystem could reliably grow around. A central point of distribution was needed.
Previously this information was distributed using Scribe/Hadoop. Services would log into Scribe and begin tailing and then pipe that data into an app. This model stopped scaling almost immediately, especially at peak where people are creating 1000s of posts a second. Didn&t want people tailing files and piping to grep.
An internal firehose was created as a message bus. Services and applications talk to the firehose via Thrift.
LinkedIn&s Kafka is used to store messages. Internally consumers use an HTTP stream to read from the firehose. MySQL wasn&t used because the sharding implementation is changing frequently so hitting it with a huge data stream is not a good idea.
The firehose model is very flexible, not like Twitter&s firehose in which data is assumed to be lost.
The firehose stream can be rewound in time. It retains a week of data. On connection it&s possible to specify the point in time to start reading.
Multiple clients can connect and each client won&t see duplicate data. Each client has a client ID. Kafka supports a consumer group idea. Each consumer in a consumer group gets its own messages and won&t see duplicates. Multiple clients can be created using the same consumer ID and clients won&t see duplicate data. This allows data to be processed independently and in parallel. Kafka uses ZooKeeper to periodically checkpoint how far a consumer has read.
Cell Design For Dashboard Inbox
The current scatter-gather model for providing Dashboard functionality has very limited runway. It won&t last much longer.
The solution is to move to an inbox model implemented using a Cell Based Architecture that is similar to&Facebook Messages.
An inbox is the opposite of scatter-gather. A user&s dashboard, which is made up posts from followed users and actions taken by other users, &is logically stored together in time order.
Solves the scatter gather problem because it&s an inbox. You just ask what is in the inbox so it&s less expensive then going to each user a user follows. This will scale for a very long time.
Rewriting the Dashboard is difficult. The data has a distributed nature, but it has a transactional quality, it&s not OK for users to get partial updates.
The amount of data is incredible. Messages must be delivered to hundreds of different users on average which is a very different problem than Facebook faces. Large date + high distribution rate + multiple datacenters.
Spec&ed at a million writes a second and 50K reads a second. The data set size is 2.7TB of data growth with no replication or compression turned on. The million writes a second is from the 24 byte row key that indicates what content is in the inbox.
Doing this on an already popular application that has to be kept running.
A cell is a self-contained installation that has all the data for a range of users. All the data necessary to render a user&s Dashboard is in the cell.
Users are mapped into cells. Many cells exist per data center.
Each cell has an HBase cluster, service cluster, and Redis caching cluster.
Users are homed to a cell and all cells consume all posts via firehose updates.
Each cell is Finagle based and populates HBase via the firehose and service requests over Thrift.
A user comes into the Dashboard, users home to a particular cell, a service node reads their dashboard via HBase, and passes the data back.
Background tasks consume from the firehose to populate tables and process requests.
A Redis caching layer is used for posts inside a cell.
Request flow: a user publishes a post, the post is written to the firehose, all of the cells consume the posts and write that post content to post database, the cells lookup to see if any of the followers of the post creator are in the cell, if so the follower inboxes are updated with the post ID.
Advantages of cell design:
Massive scale requires parallelization and parallelization requires components be isolated from each other so there is no interaction. Cells provide a unit of parallelization that can be adjusted to any size as the user base grows.
Cells isolate failures. One cell failure does not impact other cells.
Cells enable nice things like the ability to test upgrades, implement rolling upgrades, and test different versions of software.
The key idea that is easy to miss is:&&all posts are replicated to all cells.
Each cell stores a single copy of all posts. Each cell can completely satisfy a Dashboard rendering request. Applications don&t ask for all the post IDs and then ask for the posts for those IDs. It can return the dashboard content for the user. Every cell has all the data needed to fulfill a Dashboard request without doing any cross cell communication.
Two HBase tables are used: one that stores a copy of each post. That data is small compared to the other table which stores every post ID for every user within that cell. The second table tells what the user&s dashboard looks like which means they don&t have to go fetch all the users a user is following. It also means across clients they&ll know if you read a post and viewing a post on a different device won&t mean you read the same content twice. With the inbox model state can be kept on what you&ve read.
Posts are not put directly in the inbox because the size is too great. So the ID is put in the inbox and the post content is put in the cell just once. This model greatly reduces the storage needed while making it simple to return a time ordered view of an users inbox. The downside is each cell contains a complete copy of call posts. Surprisingly posts are smaller than the inbox mappings. Post growth per day is 50GB per cell, inbox grows at 2.7TB a day. Users consume more than they produce.
A user&s dashboard doesn&t contain the text of a post, just post IDs, and the majority of the growth is in the IDs.
As followers change the design is safe because all posts are already in the cell. If only follower posts were stored in a cell then cell would be out of date as the followers changed and some sort of back fill process would be needed.
An alternative design is to use a separate post cluster to store post text. The downside of this design is that if the cluster goes down it impacts the entire site. &Using the cell design and post replication to all cells creates a very robust architecture.
A user having millions of followers who are really active is handled by selectively materializing user feeds by their access model (see&Feeding Frenzy).
Different users have different access models and distribution models that are appropriate. Two different distribution modes: one for popular users and one for everyone else.
Data is handled differently depending on the user type. Posts from active users wouldn&t actually be published, posts would selectively materialized.
Users who follow millions of users are treated similarly to users who have millions of followers.
Cell size is hard to determine. The size of cell is the impact site of a failure. The number of users homed to a cell is the impact. There&s a tradeoff to make in what they are willing to accept for the user experience and how much it will cost.
Reading from the firehose is the biggest network issue. Within a cell the network traffic is manageable.
As more cells are added cells can be placed into a cell group that reads from the firehose and then replicates to all cells within the group. A hierarchical replication scheme. This will also aid in moving to multiple datacenters.
On Being A Startup In New York
NY is a different environment. Lots of finance and advertising. Hiring is challenging because there&s not as much startup experience.
In the last few years NY has focused on helping startups. NYU and Columbia have programs for getting students interesting internships at startups instead of just going to Wall Street. Mayor Bloomberg is establishing a local campus focused on technology.
Team Structure
Teams: infrastructure, platform, SRE, product, web ops, services.
Infrastructure: Layer 5 and below. IP address and below, DNS, hardware provisioning.
Platform: core app development, SQL sharding, services, web operations.
SRE: sits between service team and web ops team. Focused on more immediate needs in terms of reliability and scalability.
Service team: focuses on things that are slightly more strategic, that are a month or two months out.
Web ops: responsible for problem detection and response, and tuning.
Software Deployment
Started with a set of rsync scripts that distributed the PHP application everywhere. Once the number of machines reached 200 the system started having problems, deploys took a long time to finish and machines would be in various states of the deploy process.
The next phase built the deploy process (development, staging, production) into their service stack using Capistrano. Worked for services on dozens of machines, but by connecting via SSH it started failing again when deploying to hundreds of machines.
Now a piece of coordination software runs on all machines. Based around Func from RedHat, a lightweight API for issuing commands to hosts. Scaling is built into Func.
Build deployment is over Func by saying do X on a set of hosts, which avoids SSH. Say you want to deploy software on group A. The master reaches out to a set of nodes and runs the deploy command.
The deploy command is implemented via Capistrano. It can do a git checkout or pull from the repository. Easy to scale because they are talking HTTP. They like Capistrano because it supports simple directory based versioning that works well with their PHP app. Moving towards versioned updates, where each directory contains a&SHA&so it&s easy to check if a version is correct.
The Func API is used to report back status, to say these machines have these software versions.
Safe to restart any of their services because they&ll drain off connections and then restart.
All features run in dark mode before activation.
Development
Started with the philosophy that anyone could use any tool that they wanted, but as the team grew that didn&t work. Onboarding new employees was very difficult, so they&ve standardized on a stack so they can get good with those, grow the team quickly, address production issues more quickly, and build up operations around them.
Process is roughly Scrum like. Lightweight. &
Every developer has a preconfigured development machine. It gets updates via Puppet.
Dev machines can roll changes, test, then roll out to staging, and then roll out to production.
Developers use vim and Textmate.
Testing is via code reviews for the PHP application.
On the service side they&ve implemented a testing infrastructure with commit hooks, Jenkins, and continuous integration and build notifications.&
Hiring Process
Interviews usually avoid math, puzzles, and brain teasers. Try to ask questions focused on work the candidate will actually do. Are they smart? Will they get stuff done? But measuring &gets things done& is difficult to assess. Goal is to find great people rather than keep people out.
Focused on coding. They&ll ask for sample code. During phone interviews they will use Collabedit to write shared code.
Interviews are not confrontational, they just want to find the best people. Candidates get to use all their tools, like Google, during the interview. The idea is developers are at their best when they have tools so that&s how they run the interviews.
Challenge is finding people that have the scaling experience they require given Tumblr&s traffic levels. Few companies in the world are working on the problems they are.
Example, for a new ID generator they needed A JVM process to generate service responses in less the 1ms at a rate at 10K requests per second with a 500 MB RAM limit with High Availability. They found the serial collector gave the lowest latency for this particular work load. Spent a lot of time on JVM tuning.
On the Tumblr Engineering Blog they&ve posted memorials giving their respects for the passing of&Dennis Ritchie&&&John McCarthy. It&s a geeky culture.
Lessons Learned
Automation everywhere.
MySQL (plus sharding) scales, apps don't.
Redis is amazing.
Scala apps perform fantastically.
Scrap projects when you aren&t sure if they will work.
Don&t hire people based on their survival through a useless technological gauntlet. &Hire them because they fit your team and can do the job.
Select a stack that will help you hire the people you need.
Build around the skills of your team.
Read papers and blog posts. Key design ideas like the cell architecture and selective materialization were taken from elsewhere.
Ask your peers. They talked to engineers from Facebook, Twitter, LinkedIn about their experiences and learned from them. You may not have access to this level, but reach out to somebody somewhere.
Wade, don&t jump into technologies. They took pains to learn HBase and Redis before putting them into production by using them in pilot projects or in roles where the damage would be limited.
I&d like to thank Blake very much for the interview. He was very generous with his time and patient with his explanations. Please&contact me&if you would like to talk about having your architecture profiled.
Related Articles
Tumblr Engineering Blog&- contains a lot of good articles
Building Network Services with Finagle and Ostrich&by Nathan Hamblen - Finagle is awesome
Ostrich&- A stats collector & reporter for Scala servers
ID Generation at Scale&by Blake Matheny
Finagle&- a network stack for the JVM that you can use to build asynchronous Remote Procedure Call (RPC) clients and servers in Java, Scala, or any JVM-hosted language. Finagle provides a rich set of protocol-independent tools.
Finagle Redis client from Tumblr
Tumblr. &Massively Sharded MySQL&by Evan Elias - one of the better presentations on MySQL sharding available
Staircar: Redis-powered notifications&by Blake Matheny
Flickr Architecture&- talks about Flickr's cell architecture
将你的代码迁移到Objective-C ARC(译)
& & & &最近,苹果公司提出了几个给开发者的东西包括 Xcode4、ARC、LLVM Compiler 3.0和iOS5.0。通过在Statck overflow(一个与语言无关,让程序员可以提出问题或者回答问题的网站,网址:/)的一些问题,我可以知晓,大多数的关于ARC的困惑的增加源于一个事实&&开发者不清楚&ABC&(表示这一个单词不理解,Automatic Block Counting?)是一个LLVM 3.0的或者iOS 5的或者ARC的特性/限制。& & & Retain cycles(引用计数环),auto-release pools(自动回收池),@autorelease blocks(自动释放块)!天哪!这么多新的东西,我该怎么做啊?没错,坦诚地说,ARC,或者说Objective-C Automatic Reference Counting(Objective-C自动引用计数)已经和iPad一样神奇了。& & & 在这篇帖子里,我已经尽最大努力揭开ARC的神秘面纱。但是在开始之前,我必须提醒你,这是一篇相当长的帖子。如果你已经很厌烦了,保存(Instapaper,在线书签,是一款网页脱机阅读软件,它能保存你未能阅读的网页,以供你今后离线浏览,包含电脑,ios多种应用。网址:/)这篇文章留待以后阅读。但是,很幸运的,我相信在阅读完这篇文章之后,你会对ARC如何工作有一个更深的理解,并且有能力解决在转换你的工程的时候ARC抛出的无数错误。& & & 已经说了这么多了,让我们开始吧~目录:&一、什么是ARC& & & ARC是新LLVM 3.0编译器的一个特性,它能够帮助你放心的写你的代码而不用过多的担心内存管理。内存管理可以被广义的分为两种机制:垃圾回收机制和引用计数机制。在深入讨论之前,让我们简要的讨论一下这两类机制并理解为什么对ARC的需要这么迫切。& & & 1、当前机制的问题& & & & & & & 当前在Objective-C中使用的内存管理模式是在iOS上手动引用计数,在Mac上使用垃圾回收机制。这两种内存管理机制都有一定的问题,这个问题同时也是ARC被开发出来的原因。& & & & & & & ①、垃圾回收& & & & & & & & & & 垃圾回收是一个更高层次的语言特性大概是从Java中引入的(或者更专业的,Java Virtual Machine,Java虚拟机)&&
Migrating your code to Objective-C ARC
Recently, Apple introduced several new developer stuff including Xcode 4, ARC, LLVM Compiler 3.0 and iOS 5. From some of the questions on Stack overflow, I could understand that, most of the ARC related confusions arise due to the fact that, developers don&t know if &ABC& is a feature/restriction of LLVM 3.0 or iOS 5 or ARC.Retain cycles, auto-release pools, @autorelease blocks, oh man! So many new things? What am I going to do? You are right. ARC, or Objective-C Automatic Reference Counting is almost&. No really.In this post, I&ve made an attempt to demystify the air around this. Before starting, I&ll have to warn you that, this is a fairly long post. If you are too bored, Instapaper this article and read it later. But, hopefully, at the end of this, I believe, you will have a better understanding on how ARC works and be able to work around the innumerable errors it spits out when you convert your project.Having said that, let&s get started.Contents
What is ARC
Problems with the current model.
Garbage collection
Reference Counting
Automatic Reference Counting
Compiler level feature
Also a run time feature
ARC Ownership qualifiers
ARC knows more Objective-C than you
Toll-free bridging
How does ARC work internally?
ARC front end
ARC optimizer
The actual Migration using Xcode 4.2
Common ARC migration errors
Cast of Objective-C pointer to C Pointer type
performSelector may cause a leak because its selector is unknown
Receiver type "*" doesn't declare the method with selector "*"
Common workarounds that you use in ARC on code that otherwise looks normal
Capturing "*" strongly is likely to lead to a retain cycle
Avoiding early releases using __block
That last question
When should you migrate?
Where to go from here?&What is ARCARC is a feature of the new LLVM 3.0 compiler that helps you to write code without worryingmuch&about memory management. Memory management can be broadly classified into two, garbage collected and reference counted models. Before going to the details, let&s briefly discuss these two models and understand why ARC is even needed.Problems with the current model.The current memory model we use in Objective-C is manual reference counting on iOS and Garbage collection on Mac.There are certain problems with both these memory models which probably was the reason why ARC was developed.Garbage collectionGarbage collection is a higher level language feature probably introduced in Java (or technically, Java Virtual Machine) and implemented in a variety of other programming platforms including Microsoft&s Common Language Runtime. While Garbage collection worked well for higher level languages, Objective-C, which is still C under the hood, didn&t really fly high. Pointers (or rather references) in other languages like Java were actually objects that managed retain count and automatically releases itself when the count reaches zero. One of the design goals of C was to be optimized for performance and not &easy of use&. While pointer objects (read&) are great object oriented abstractions, they have an adverse effect on the performance of the code and since Objective-C was intended primarily for native programming where developers are used to use pointers, pointers within a structure, pointer to a pointer (for dereferencing a out parameter), it was just too difficult to introduce something like a smart pointer that would require a lot of mindset change from the developers who prefer a deterministic memory management model (Reference counting) over a non-deterministic memory management model (Garbage collection). Nevertheless, GC (Generational GC) was introduced in Objective-C 2.0 for Mac. While Generational GC doesn&t suffer from &Stop the world& issues like the mark and sweep alogrithm, they don&t collect every released variable and an occasional mark and sweep collection is still needed.Reference CountingThe memory management model used in iOS is called as reference counting model, or more precisely, manual reference counting.In manual reference counting model, you as a developer, have to deallocate every object you allocated. When you don&t do this, you either leak memory or over release it, causing a crash. While that counting sounds easy, Most of the memory leaks happen when you transfer ownership of objects across scope boundaries. That&s a creator method that allocates an object for you and expects the caller to deallocate it. To circumvent this problem, Objective-C introduced a concept called autorelease. auto-released variables are added to the auto-release pool and are released at the end of the runloop. While this sounds too good, auto-release pools do incur an additional overhead.For example, comparing the two code blocks,
NSDictionary *dict = [[NSDictionary alloc] init];
// do something with the dictionary here
// I'm done with the dictionary, I don't need it anymore
[dict release];
// more code}
NSDictionary *dict = [NSDictionary dictionary]; // auto-released object
// do something with the dictionary here
// I'm done with the dictionary, I don't need it anymore&
// more code}
the first block is an example of optimized use of memory where as the second depends on auto-release pools. While this block of code doesn&t really incur significant memory overhead, code like these slowly adds together and makes your reference counted model heavily dependent on auto-release pools. That is, objects that you know could be deallocated, will still linger around in the auto-release pool for a little longer.Automatic Reference CountingSay hello to ARC. ARC is a compiler feature that auto inserts retain and release for you. So in the first code block of the above example, you no longer have to write the release method and ARC auto-inserts for you before compilation.
NSDictionary *dict = [[NSDictionary alloc] init];
// do something with the dictionary here
// I'm done with the dictionary, I don't need it anymore
[dict release]; // ARC inserts this code for you.
// more code}
When you create an autoreleased object, like in the second block of code, ARC compiler is clever enough not to add a release call. Sound great, so how should I go about doing this ARC thing? Just delete all release/retain codes and pray? Unfortunately, it isn&t that easy. ARC is not just some auto insert or macro expander kind of tool.&It forces you to think in terms of object graphs instead of memory allocation, retain or release.&Let&s delve a little deeper into ARC.Compiler level featureARC is a compiler level feature. I repeat. ARC IS A COMPILER LEVEL FEATURE. This means, when you use ARC, you don&t have to worry about upgrading your deployment target and so on. However, only the latest LLVM 3.0 compiler supports ARC. If you are still stuck with GCC, you are out of luck. (Meh!) Some more points that you should know about ARC are,
ARC is backward compatible with libraries and framework compiled with under non-ARC.
ARC can be used within your project on a file-by-file basis. So you can mix and match ARC code with non-ARC code.
You can also integrate ARC compiled libraries into your project that doesn&t use ARC and vice-versa.
You use a&compiler switch&to turn ARC on and off.
(The keyword here is compiler switch)
You can also set the complete target to build with ARC by default (and use non-ARC compiler only when instructed so.) This is shown in the illustration below.
The two main compiler switches that you would often use are when you build your application with a third party library that is not ARC compliant and vice versa, are
-fno-objc-arc
-fobjc-arc
-f is the switch and&no-objc-arc&and&objc-arc&are the options that you are turning on. As evident from the names, the first one turns off ARC and the second turns on.For example, if your application is ARC enabled but a third party library is not, you use the first switch&-fno-objc-arcto exclude the third party library. Conversely, if your application is not yet ARC enabled (gasp!) but the third party library you are integrating is, you use the second switch&-fobjc-arc&You add these flags to the project from the Build phases tab as shown below.Also a run time featureWait! You just told me (and repeated) that ARC is a compiler level feature? Now what? Sorry, I hear you, but, unfortunately, things aren&t that easy and it doesn&t just stop here. ARC also backs up on a runtime feature calledzero-ing weak references. Oh, damn, another keyword! I should have introduced this before. But that&s ok. We will revisit about the run-time dependency of ARC, a little later in this post.ARC Ownership qualifiersAs I showed you earlier, ARC automatically inserts releases and retains in your code in a pre-compilation step. But for ARC to know when to release your objects and when to retain them, you need to somehow tell the life of your variables. You use ownership qualifiers for that. A strong understanding of ownerships is vital to understand and use ARC properly. Once you understand this concept, you will be thinking in terms of object graphs instead of retain/release. Secondly, when you use ARC, all variables local or ivars are initialized to nil automatically for you. This means, there is little chance of having a dangling reference in your application.
__unsafe_unretained
__autoreleasingThe first qualifier, __strong, is the default and you might not even be using this explicitly. It is use to tell the ARC compiler that, the declared variable &owns& the reference. The opposite of this is __weak, which tells the ARC compiler that the declared variable doesn&t own the reference.The __weak is&synonymous&to the &assign& modifier. You normally use assign modifier for IBOutlets and delegates. Under ARC, this is replaced with __weak. However, there is a caveat. __weak requires you to deploy the app on a runtime that supports&zero-ing weak references. This includes, iOS 5 and Lion. Snow Leopard and older operating systems or iOS 4 and older operating systems don&t support zero-ing weak references. This obviously means you cannot use __weak ownership modifiers if you plan to deploy to older operating systems. Fret not. ARC includes another ownership qualifier, __unsafe_unretained that is synonymous to __weak, except that when the pointer is de-referenced, it is not set to nil, but remains dangling. A while ago, I told something about zero-ing weak references? When the runtime supports zero-ing weak references, your __weak variables are automatically set to nil when they are released. This is the only feature that requires a higher deployment target (iOS 5/Lion). Otherwise, you are good to deploy on iOS 4/Snow Leopard.A couple other important things to know about __weak vs __unsafe_unretained is that, the compiler doesn&t allow you to use __weak when your deployment target is set to a operating system that doesn&t support zero-ing weak references. The Convert to Objective-C ARC wizard uses __weak only when your deployment target supports zero-ing weak references. So if your deployment target is iOS 4, the Objective-C convert ion wizard will replace assign modifiers with __unsafe_unretained instead of __weak.The last ownership qualifier, __auto_releasing is used mostly when passing a reference to a function for writing out. You would use this in places where you normally use pointer indirection like returning a NSError object via an out parameter.Properties in your header file can also have the above ownership qualifiers except the __auto_releasing. When applied to properties, ARC automatically generates the correct code in dealloc to release them when the object dies.Lastly, and more importantly, all of ARC managed&objects&are initialized to nil when they are created. So, again, no more dangling pointers because you forgot a initialize statement. However, do note that this initialization doesn&t initialize primitive data types. So a declaration like,
might contain a garbage value for a.Whew! That&s pretty taxing. Take a break. We just started.ARC knows more Objective-C than youARC also taps into a the Objective-C language naming conventions and infers the ownership of the returned object.In Objective-C, a method that stats with any one of the following prefix,
mutableCopy and
neware considered to be transferring ownership of the returned object to the caller.This means, in your application, when you create a method, ARC automatically infers whether to return a autoreleased object or a +1 retained object from your method name. In fact, in most cases, instead of returning auto-release objects, ARC just inserts a manual release in the calling code, automatically for you. However, there is a small caveat. Let&s assume that you have a method that starts with &copy&, as in
-(NSString*) copyRightS
ARC assumes that it would transfer the ownership of the returned string to the caller and inserts a release automatically. Everything works well, if both the called method and the calling method are compiled using ARC.
But&if your &copyRightString& method is in a third party library that isn&t compiled with ARC, you will over-release the returned string. This is because, on the calling code, ARC compiler inserts a release to balance out the retain count bumped up by the &copy& method. Conversely, if the third party library is compiled with ARC and your method isn&t, you will have a memory leak. You can however override this behavior by adding one of the following attribute to your methods.
NS_RETURNS_NON_RETAINED
NS_RETURNS_RETAINEDSo your method will now look like this.
-(NSString*) copyRightString NS_RETURNS_NON_RETAINED;
You can also rename the method name to&copyrightString&(note the case) or&getCopyRightString&instead of adding an attribute. However, I wouldn&t recommend the former method as it breaks the cocoa naming conventions (prefixing a method with &get& or &set& is Java-ish)You will see methods having the NS_RETURNS_* prefixes throughout the header files in Apple&s own UIKit.framework or the foundation classes. Now that you know what happens behind the scenes and how compiler treats these decorations, you can solve crazy memory issues, like a crash when you call a&copyRightString&in your metho}

我要回帖

更多关于 objective c高级编程 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信