linux c 开发两个好工具 gdb valgrind

linux c 开发两个好工具

gdb 调试工具

基本命令:

break  upload.c:200  #设置断点  upload.c 200行

run 运行

 

continue(c)  执行到下个断点

 

list  linenum  显示linenum周围的源代码

step 单步执行

next  单步步入

print  a  #打印变量

quit  #退出

valgrind 主要是查询程序内存问题如内存溢出、内存越界等

安装 yum -y install   valgrind

使用方法  valgrind –tool=memcheck –leak-check=full ./server

查看crontab执行日志

在crontab中添加了定时任务,但发现没有得到期望的结果,因而怀疑是crontab没有执行相应的任务,但怎么定位crontab是否执行呢?
这就需要查看crontab的执行历史记录,具体位置如下:
cd /var/log
tail -100 cron
在cron文件中即可查阅已经操作过的相关定时任务

http://www.cnblogs.com/Jerryshome/archive/2012/02/16/2353537.html

统计文件中出现次数最多的ip

记录类似下面的日志
http://vip.veryeast.cn/vip/ 2013-08-29 11:49:19 lijianwei 123456 183.230.11.44
需要分析ip最多的是哪几个
首先通过 awk   取到 ip   cat login.txt|awk ‘{print $6}’
然后统计出现次数最多的
cat login.txt |awk ‘{print $6}’|sort |uniq -c|sort -k1,1nr|head -10

sort:  对单词进行排序

uniq -c:  显示唯一的行,并在每行行首加上本行在文件中出现的次数

sort -k1,1nr:  按照第一个字段,数值排序,且为逆序

head -10:  取前10行数据

iOS编程之GCD(多线程技术)

GCD定义

Grand Central Dispatch或者GCD,是一套低层API,提供了一种新的方法来进行并发程序编写。从基本功能上讲,GCD有点像 NSOperationQueue,他们都允许程序将任务切分为多个单一任务然后提交至工作队列来并发地或者串行地执行。GCD比之 NSOpertionQueue更底层更高效,并且它不是Cocoa框架的一部分。

除了代码的平行执行能力,GCD还提供高度集成的事件控制系统。可以设置句柄来响应文件描述符、mach ports(Mach port 用于 OS X上的进程间通讯)、进程、计时器、信号、用户生成事件。这些句柄通过GCD来并发执行。

GCD的API很大程度上基于block,当然,GCD也可以脱离block来使用,比如使用传统c机制提供函数指针和上下文指针。实践证明,当配合block使用时,GCD非常简单易用且能发挥其最大能力。

GCD工作原理

让程序平行排队的特定任务,根据可用的处理资源,安排他们在任何可用的处理器核心上执行任务。一个任务可以是一个函数(function)或者是一个block。GCD的底层依然是用线程实现,不过这样可以让程序员不用关注实现的细节。GCD中的FIFO队列称为dispatch queue,它可以保证先进来的任务先得到执行。

GCD的优势

  1. 易用: GCD比之thread跟简单易用。由于GCD基于work unit而非像thread那样基于运算,所以GCD可以控制诸如等待任务结束监视文件描述符周期执行代码以及工作挂起等任务。基于block的血统导致它能极为简单得在不同代码作用域之间传递上下文。
  2. 效率: GCD被实现得如此轻量和优雅,使得它在很多地方比之专门创建消耗资源的线程更实用且快速。这关系到易用性:导致GCD易用的原因有一部分在于你可以不用担心太多的效率问题而仅仅使用它就行了。
  3. 性能: GCD自动根据系统负载来增减线程数量,这就减少了上下文切换以及增加了计算效率。

GCD的使用

GCD是纯c语言的,它被组建成面向对象的风格。GCD对象被称为dispatch object。Dispatch object像Cocoa对象一样是引用计数的。使用dispatch_release和dispatch_retain函数来操作dispatch object的引用计数来进行内存管理。但注意不像Cocoa对象,dispatch object并不参与垃圾回收系统,所以即使开启了GC,你也必须手动管理GCD对象的内存。

Dispatch Queues

GCD的基本概念就是dispatch queue。dispatch queue是一个对象,它可以接受任务,并将任务以先到先执行的顺序来执行。dispatch queue可以是并发的或串行的。并发任务会像NSOperationQueue那样基于系统负载来合适地并发进行,串行队列同一时间只执行单一任务。

dispatch queue分为下面三种:

  1. The main queue: 与主线程功能相同。实际上,提交至main queue的任务会在主线程中执行。main queue可以调用dispatch_get_main_queue()来获得。因为main queue是与主线程相关的,所以这是一个串行队列。
  2. Global queues: 全局队列是并发队列,并由整个进程共享。进程中存在三个全局队列:高、中(默认)、低三个优先级队列。可以调用dispatch_get_global_queue函数传入优先级来访问队列。
  3. 用户队列: 用户队列 (GCD并不这样称呼这种队列, 但是没有一个特定的名字来形容这种队列,所以我们称其为用户队列) 是用函数 dispatch_queue_create 创建的队列. 这些队列是串行的。正因为如此,它们可以用来完成同步机制, 有点像传统线程中的mutex。

系统提供的dispatch方法

// 后台执行:
 dispatch_async(dispatch_get_global_queue(0, 0), ^{
 // something
 });
 // 主线程执行:
 dispatch_async(dispatch_get_main_queue(), ^{
 // something
 });
 // 一次性执行:
 static dispatch_once_t onceToken;
 dispatch_once(&onceToken, ^{
 // code to be executed once
 });
 // 延迟2秒执行:
 double delayInSeconds = 2.0;
 dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
 dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
 // code to be executed on the main queue after delay
 });

自定义queue

dispatch_queue_t urls_queue = dispatch_queue_create("blog.devtang.com", NULL);
dispatch_async(urls_queue, ^{
 // your code
});
dispatch_release(urls_queue);

dispatch_group_async的使用

dispatch_group_async可以实现监听一组任务是否完成,完成后得到通知执行其他的操作。这个方法很有用,比如你执行三个下载任务,当三个任务都下载完成后你才通知界面说完成的了。下面是一段例子代码:

dispatch_group_t group = dispatch_group_create();
 dispatch_group_async(group, dispatch_get_global_queue(0,0), ^{
 // 并行执行的线程一
 });
 dispatch_group_async(group, dispatch_get_global_queue(0,0), ^{
 // 并行执行的线程二
 });
 dispatch_group_notify(group, dispatch_get_global_queue(0,0), ^{
 // 汇总结果
 });

dispatch_barrier_async的使用

dispatch_barrier_async是在前面的任务执行结束后它才执行,而且它后面的任务等它执行完成之后才会执行。下面是一段例子代码:

dispatch_queue_t queue = dispatch_queue_create("gcdtest.rongfzh.yc", DISPATCH_QUEUE_CONCURRENT);
 dispatch_async(queue, ^{
 [NSThread sleepForTimeInterval:2];
 NSLog(@"dispatch_async1");
 });
 dispatch_async(queue, ^{
 [NSThread sleepForTimeInterval:4];
 NSLog(@"dispatch_async2");
 });
 dispatch_barrier_async(queue, ^{
 NSLog(@"dispatch_barrier_async");
 [NSThread sleepForTimeInterval:4];
});
 dispatch_async(queue, ^{
 [NSThread sleepForTimeInterval:1];
 NSLog(@"dispatch_async3");
 });

后台运行

GCD的另一个用处是可以让程序在后台较长久的运行。在没有使用GCD时,当app被按home键退出后,app仅有最多5秒钟的时候做一些保存或清理资源的工作。但是在使用GCD后,app最多有10分钟的时间在后台长久运行。这个时间可以用来做清理本地缓存,发送统计数据等工作。

让程序在后台长久运行的示例代码如下

// AppDelegate.h文件
@property (assign, nonatomic) UIBackgroundTaskIdentifier backgroundUpdateTask;
// AppDelegate.m文件
- (void)applicationDidEnterBackground:(UIApplication *)application
{
 [self beingBackgroundUpdateTask];
 // 在这里加上你需要长久运行的代码
 [self endBackgroundUpdateTask];
}
- (void)beingBackgroundUpdateTask
{
 self.backgroundUpdateTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
 [self endBackgroundUpdateTask];
 }];
}
- (void)endBackgroundUpdateTask
{
 [[UIApplication sharedApplication] endBackgroundTask: self.backgroundUpdateTask];
 self.backgroundUpdateTask = UIBackgroundTaskInvalid;
}

总结

总体来说,GCD能够极大地方便开发者进行多线程编程。如果你的app不需要支持iOS4.0以下的系统,那么就应该尽量使用GCD来处理后台线程和UI线程的交互。

iOS编程之浅析block

Block简介

Block 对象是 C 级别的语法和运行时特性。它们和标准 C 函数很类似,但是除了 可执行代码外,它们还可能包含了变量自动绑定(栈)或内存托管(堆)。所以一个 block 维护一个状态集(数据),它们可以在执行的时候用来影响程序行为。

Block使用环境

环境:可以在 Mac OS X v10.6 及其之后,和 iOS 4.0 及其之后上面使用 blocks。 Blocks 运行时是开源的,你可以在 LLVM’s compiler-rt subproject repository (LLVM 的 RT 编译器的子项目库)里面找到它。Blocks 同样作为标准 C 工作组出现在 N1370:Apple’s Extensions to C(该文档同样包括了垃圾回收机制)。因为 Objective-C 和 C++都是从 C 发展而来,blocks 被设计在三种语言上面使用(也包括 Objective-C++)。

Block功能

一个 block 就是一个匿名的内联代码集合体:

  1. 和函数一样拥有参数类型
  2. 有推断和声明的返回类型
  3.  可以捕获它的声明所在相同作用域的状态
  4. 可以和其他定义在相同作用域范围的 blocks 进行共享更改
  5.  在相同作用域范围(栈帧)被销毁后持续共享和更改相同作用域范围(栈帧)的状态

block作用

可以用 blocks 来编写函数表达式,这些表达式可以作为 API 使用,或可选的存 储,或被多个线程使用。Blocks 作为回调特别有用,因为 block 携带了进行回调所需要的执行代码和执行过程中需要的数据。

回调机制

回调就是把函数指针做为参数传入,如函数A 做为参数传入函数B,由B函数决定何时何地调用函数A。

Block的简单实例

block对象的声明,定义及调用

int (^adder) (int,int) = ^int (int a , int b) { //do some thing};
int m = adder(5,10);

上面实例是一个变量名为adder,实参为int a,int b,返回值为int类型的block函数,int(^adder)(int a,int b)为block变量的声明,^int(int a, int b) {};为此block的定义,adder(5,10)为此block对象的调用,int m为此block对象调用后的返回值。

block函数的回调实例

以下为ARC环境下编码:

ViewController.h

#import <UIKit/UIKit.h>
@interface AppDelegate : UIResponder <UIApplicationDelegate>
@property (strong, nonatomic) UIWindow *window;
@end

ViewController.m

#import "AppDelegate.h"
#import "ViewController.h" 
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
ViewController *viewController = [[ViewController alloc] init];
[self.window setRootViewController:viewController];
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
return YES;
}

- (void)applicationWillResignActive:(UIApplication *)application{
}
- (void)applicationDidEnterBackground:(UIApplication *)application{}
- (void)applicationWillEnterForeground:(UIApplication *)applicatio{}
- (void)applicationDidBecomeActive:(UIApplication *)application{
}

- (void)applicationWillTerminate:(UIApplication *)application
{

}

@end

UIViewController.h

#import <UIKit/UIKit.h>
@interface ViewController : UIViewController{
}
@end

UIViewController.m

#import "ViewController.h"
#import "TapView.h"
@implementation ViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
 self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
 if (self) {
 // Custom initialization
 self.view.backgroundColor = [UIColor lightGrayColor];
 TapView *view = [[TapView alloc] initWithFrame:CGRectMake(0, 0, 320, 220)];
 view.center = self.view.center;
 view.backgroundColor = [UIColor darkGrayColor];
 [view setChangeBlock:^(UIColor *color) {
 self.view.backgroundColor = color;
 NSLog(@"Button is clicked!");
 }];
 [self.view addSubview:view]; 
 }
 return self;
}
- (void)viewDidLoad
{
 [super viewDidLoad];
 // Do any additional setup after loading the view.
}
- (void)didReceiveMemoryWarning
{
 [super didReceiveMemoryWarning];
 // Dispose of any resources that can be recreated.
}
@end

TapView.h

#import <UIKit/UIKit.h>
typedef void (^ChangeViewBackgroundColorBlock) (UIColor*);
@interface TapView : UIView
{
// void (^changeViewBackgroundColorBlock) (UIColor*);
 ChangeViewBackgroundColorBlock changeBlock;
}
@property (nonatomic,copy) ChangeViewBackgroundColorBlock changeBlock;
@end
TapView.m
#import "TapView.h"
@implementation TapView
@synthesize changeBlock;
- (id)initWithFrame:(CGRect)frame
{
 self = [super initWithFrame:frame];
 if (self) {
 NSArray *colorArray = [[NSArray alloc] initWithObjects:@"红色", @"黄色", @"蓝色", @"绿色",nil];
 for (int i = 0; i < 4; i++) {
 UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
 int row = i/2;
 int line = i%2;
 [button setFrame:CGRectMake(line * 100 + 50, row * 50 + 50, 100 , 50)];
 [button setTitle:[NSString stringWithFormat:@"按钮:%@",(NSString*)[colorArray objectAtIndex:i]] forState:UIControlStateNormal];
 button.tag = i + 1;
 [button addTarget:self action:@selector(editBtn:) forControlEvents:UIControlEventTouchUpInside];
 [self addSubview:button];
 }
 }
 return self;
}
- (void) editBtn:(id)sender
{
 UIButton *button = (UIButton*)sender;
 UIColor *color = [UIColor clearColor];
 int index = button.tag - 1;
 if (index == 0) {
 color = [UIColor redColor];
 } else if (index == 1) {
 color = [UIColor yellowColor];
 } else if (index == 2) {
 color = [UIColor blueColor];
 } else if (index == 3) {
 color = [UIColor greenColor];
 }
 if (changeBlock) {
 changeBlock(color);
 }
}
- (void) setBlock:(void(^)(UIColor *color))block
{
 self.changeBlock = block;
}
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
 // Drawing code
}
*/
@end

 作为参数返回:

typedef void (^BoolBlock)(BOOL);
- (BoolBlock)foo()
{
    BoolBlock ablock = ^(BOOL bValue) {
        NSLog(@"Bool block!");
    };
    return [[ablock copy] autorelease];//一定要copy,将其复制到堆上,更详细的原理,将在后续章节讲解

iOS编程之ARC(自动引用计数)

ARC是什么

ARC是iOS 5推出的新功能,全称叫 ARC(Automatic Reference Counting)。简单地说,就是代码中自动加入了retain/release,原先需要手动添加的用来处理内存管理的引用计数的代码可以自动地由编译器完成了。

该机能在 iOS 5/ Mac OS X 10.7 开始导入,利用 Xcode4.2 可以使用该机能。简单地理解ARC,就是通过指定的语法,让编译器(LLVM 3.0)在编译代码时,自动生成实例的引用计数管理部分代码。有一点,ARC并不是GC,它只是一种代码静态分析(Static Analyzer)工具。

ARC历史简介

Objective-C提供了三种内存管理方式:manual retain-release(MRR,手动管理),automatic reference counting(ARC,自动引用计数),garbage collection(垃圾回收)。iOS不支持垃圾回收,所以在苹果提供ARC技术前,iOS开发者使用MRR来手动管理内存。

MRR手动管理内存是基于引用计数的,只是需要开发者发消息给某块内存(或者说是对象)来改变这块内存的引用计数以实现内存管理(ARC技术则是编译器代替开发者完成相应的工作)。一块内存如果计数是零,也就是没有使用者(owner),那么objective-C的运行环境会自动回收这块内存。

MRR核心原则:

  1. 你拥有你创建的对象
    也就是说创建的对象(使用alloc,new,copy或者mutalbeCopy等方法)的初始引用计数是1;
  2. 给对象发送retain消息后,你拥有了这个对象;
  3. 当你不需要使用该对象时,发送release或者autorelease消息放弃这个对象;
  4. 不要对你不拥有的对象发送“放弃”的消息;
  5. dealloc方法
    dealloc方法用来释放这个对象所占的内存(包括成员变量)和其它资源;
  6. Autorelease Pool
    Autorelease Pool可以延后发送release消息给一个对象。发送一个autorelease消息给一个对象,相当于说这个对象在“一定时期”内都有效,“一定时期”后再release这个对象。

使用ARC的优点和缺点

优点:

  • ARC的使用使Objective-C的代码变得简单多了,因为我们不需要担心烦人的内存管理,担心内存泄露了
  • 代码的总量变少了,看上去清爽了不少,也节省了劳动力
  • 代码高速化,由于使用编译器管理引用计数,减少了低效代码的可能性

缺点:

  • 记住一堆新的ARC规则 — 关键字及特性等需要一定的学习周期
  • 一些旧的代码,第三方代码使用的时候比较麻烦;修改代码需要工数,要么修改编译开关

ARC的使用

ARC使用的基本规则

  • retain, release, autorelease, dealloc由编译器自动插入,不能在代码中调用
  • dealloc虽然可以被重载,但是不能调用[super dealloc]

MRR到ARC的自动转换

  1. 创建工程时勾选Use Automatic Reference Counting;
  2. 更改整个工程文件是否使用ARC模式,点击工程target选项–>Build Settings–>Apple LLVM compiler x – Language –>Objecive-C Automatic Reference Counting选项–>更改yes(使用)或no(不使用)(或直接右上角search栏搜索Objective-C Automatic Reference Counting更改选项);
  3. ①整个工程不支持ARC模式,使部分文件支持ARC,点击工程target选项–>Build Phases–>Compile Sources–>对应类双击,在弹出框中输入-fobjc-arc,enter键确认即可;
    ②整个工程支持ARC模式,使部分文件不支持ARC,点击工程target选项–>Build Phases–>Compile Sources–>对应类双击,在弹出框中输入-fno-objc-arc,enter键确认即可;
  4. 将MRR部分类快速转化为支持ARC模式的文件,Edit->Refactor–>Convert to Objective-C ARC–>选择要转换的文件–>precheck。

ARC引用关键字

  • __strong
    变量声明缺省都带有__strong关键字,如果变量什么关键字都不写,那么缺省就是强参照。
  • __weak
    弱参照的关键字。该概念是新特性,从 iOS 5/ Mac OS X 10.7 开始导入。由于该类型不影响对象的生命周期,所以如果对象之前就没有持有者,那么会出现刚创建就被破弃的问题,比如下面的代码。

    NSString __weak *string = [[NSString alloc] initWithFormat:@"First Name: %@", [self firstName]];
    NSLog(@"string: %@", string); //此时 string为空

    如果编译设定OS版本 Deployment Target 设定为这比这低的版本,那么编译时将报错(The current deployment target does not support automated __weak references),这个时候,我们可以使用下面的__unsafe_unretained。
    弱参照还有一个特征,即当参数对象失去所有者之后,变量会被自动付上nil (Zeroing)。

  • __unsage_unretained
    该关键字与__weak一样,也是弱参照,与__weak的区别只是是否执行nil赋值(Zeroing)。但是这样,需要注意变量所指的对象已经被破弃了,地址还还存在,但内存中对象已经没有了。如果还是访问该对象,将引起「BAD_ACCESS」错误。
  • __autoreleasing
    该关键字使对像延迟释放。比如你想传一个未初始化的对像引用到一个方法当中,在此方法中实例化此对像,那么这种情况可以使用__autoreleasing。他被经常用于函数有值参数返回时的处理,比如下面的例子。

    - (void) generateErrorInVariable:(__autoreleasing NSError **)paramError {
        ....
        *paramError = [[NSError alloc] initWithDomain:@"MyApp" code:1 userInfo:errorDictionary];
    }
    
    ....
    {
        NSError *error = nil;
        [self generateErrorInVariable:&error];
        NSLog(@"Error = %@", error);
    }

    又如函数的返回值是在函数中申请的,那么希望释放是在调用端时,往往有下面的代码。

    -(NSString *)stringTest
    {
        NSString *retStr = [NSString stringWithString:@"test"];
    
        return [[retStr retain] autorelease];
    }
    
    // 使用ARC
    
    -(NSString *)stringTest
    {
        __autoreleasing NSString *retStr = [NSString alloc] initWithString:@"test"];
    
        return retStr;
    }

    即当方法的参数是id*,且希望方法返回时对象被autoreleased,那么使用该关键字。

与标准C语言和Core Foundation类库的自由桥接

与Objective-C库不同,我们在Objective-C中使用的标准C语言和Core Fundation类库(CF *方法)不会遵循那些命名约定。这意味着ARC编译器无法百分百地释放不需要的内存。在ARC出现之前,我么可以将CF*对象强制转变成NS*对象,这称为自由桥接(toll-free bridging)。也就是说,我们可以将CFString*通过类型转换变成NSString*类型。而有了ARC,我们便无法再这么做了,至少不指定一个所有权转移修饰符时确实如此。

ARC允许使用一下这些所有权转移修饰符:

  •   __bridge
  •   __bridge_retained
  •   __bridge_transfer
  1. __bridge
    它告诉ARC不要增加它的引用计数的值,也不要更改所有权。
  2. __bridge_retained
    若想要转换C指针类型并增加引用计数的值,我们可以使用第二个修饰符。当要从Objective-C方法(它创建一个Core Fundation对象并在之后使用CFRelease方法将其释放)返回一个保留过的指针时,我们可以使用这个修饰符。如果Objective-C方法属于NSRETURNS_RETAINDED系列,就要返回保留过的指针。
  3. __bridge_transfer
    如果要将Core Fundation指针类型转换成Objective-C指针并为引用计数加1,可以使用最后一个修饰符。若Core Fundation方法创建一个对象,并且想要靠ARC来管理对象的内存,我们便可以使用这个修饰符。

ARC使用注意事项

  1. 不可以使用retain,retainCount,release,autorelease 用@select()这样的调用也不行.属性命名不能以new开头。
  2. 若重写一个类子类的dealloc,不应调用[super dealloc],当然也不用写什么release释放一些什么对象,只是处理一些你觉得必要处理的事情吧,比如中止一个还没有完成的网络请求.
  3. 不能使用NSAllocateObject和NSDeallocateObject
  4. 你不能在c结构中使用对象,更好的方式是使用Objective-c类来代替.
  5. 在id和void*之间不能隐士转换,必须指明相应转换的生命周期。
  6. 不能使用NSAutoreleasePool对象,ARC使用@autoreleasepool{}块代替。
  7. 不能使用内存块,NSZone已经不需要使用了,现在运行时已经忽略之。
  8. 循环保留
    当两个对象对彼此都有所有权时就会发生循环保留,比如子视图控制器拥有指向父视图控制器的强指针。为了避免这种循环保留,可以使用__weak(或者__unsafe_unretained)所有权修饰符。
  9. block和ARC
    block是可以捕获上下文的特殊代码块,当block“捕获”了上下文,它就会为其作用域内的每个标量变量创建一个副本。有一种常见得错误:通过self拥有一个block,而再block中修改了实例变量,这是就会出错,代码如下:

    self.myBlock = ^(NSString* returnedString) {                                           
         self.labelControl.text = returnedString;
    }

    上面的例子self保留了block,而block又捕获(保留)了self,这样就会引发循环保留。为了避免这种情况,需要在block中捕获未保留的self引用。在没有ARC时,我们可以使用__block关键字和__unsafe_unretained来复制一个未保留的引用副本,并在block中使用。在ARC中,使用__weak(或者__unsafe_unretained)引用。

  10. ARC禁止在结构体(struct)或集合体(union)中使用Objective-C对象。

其他

  1. 除了nib的Top-Level(main nib文件里面的对象,除了File’s owner和 Application)对象,其他的IBOutlet最好都是weak型的.
  2. 如果一定要实现类的自定义的retain和release,那么同时也要在类中加入
    -(BOOL)supportsWeakPointers { return NO; }
  3. 在c型的结构中使用objective-c对象
    使用void*代替id;或者使用__unsage_unretained 修饰objective-c对象
  4. 不能zeroing-weak引用的类有
    SATSTypesetter, NSColorSpace, NSFont, NSFontManager, NSFontPanel, NSImage, NSMenuView, NSParagraphStyle, NSSimpleHorizontalTypesetter, NSTableCellView, NSTextView, NSViewController, NSWindow, and NSWindowController.
    他们的对象,作为属性,使用assign代替weak;作为变量,使用__unsafe_unretained代替__weak。
    ARC下也不能weak引用NSHashTable, NSMapTable, or NSPointerArray。
  5. __block修饰的变量默认也是__strong引用的.
Pages: 1 2 3 4 5 6 7 8 9 10 ...38 39 40 Next