小毛的博客

追求卓越,精益求精


  • 首页

  • 分类

  • 归档

  • 标签

如何生成SSH密钥

发表于 2017-06-16 | 分类于 others

前言

在github和码云上需要做得方便一些,一般都会配置SSH。而且这个SSH都是能用的。


检查是否存在SSH key

如果有的话,可以直接走第3步,直接拷贝SSH key到需要的地方去,也可以再次走第2步,覆盖重新生成SSH key.

  • cd ~/.ssh //进入密钥 (或者open ~/.ssh)

    ~/ 表示用户的信息 。进入用户信息的.ssh文件 。

    可以直接 open ~/.ssh打开密钥文件夹,或者 open ~/ 打开用户信息列表 .有可能提示没有这个文件夹路径,这样就直接生成SSH就可以了。但也有可能,你进这用户信息列表看不到.ssh文件,因为默认情况下,它是隐藏的,包括cocoapods等这些安装包都是隐藏了的。
    
    补充一下:
    显示:defaults write com.apple.finder AppleShowAllFiles Yes && killall Finder 来显示隐藏的文件夹 (也可以在文件Finder中进行操作,具体可以百度一下就出来)
    

    隐藏:defaults write com.apple.finder AppleShowAllFiles No && killall Finder

  • 如果存在的话

    ls:察看密钥
    这两个命令就是检查是否已经存在 id_rsa.pub 或 id_dsa.pub 文件,如果文件已经存在,那么你可以跳过步骤2,直接进入步骤3。
    如果已级存在了终端会提示:
    id_rsaid_rsa.pubknown_hosts

创建一个 SSH key

  • ssh-keygen -t rsa -C “your_email@example.com”

    代码的一切含义:
    -t 指定密钥类型,默认是 rsa ,可以省略。
    -C 设置注释文字,比如邮箱。
    -f 指定密钥文件存储文件名。

    以上代码省略了 -f 参数,因此,运行上面那条命令后会让你输入一个文件名,用于保存刚才生成的 SSH key 代码:

    Generating public/private rsa key pair.# Enter file in which to save the key (/c/Users/you/.ssh/id_rsa): [Press enter]

    当然,一般我们可以不输入文件名,它会使用默认文件名,自动会生成 id_rsa 和 id_rsa.pub 两个秘钥文件。

  • 接着又会提示你输入两次密码

    该密码是你push文件的时候要输入的密码,而不是github管理者的密码)

    直接回车:
    我是没有输入密码的,因为输入了密码后,每次提交都需要你输入密码,很麻烦。直接回车

    Enter passphrase (empty for no passphrase): # Enter same passphrase again:

  • 接着会生成ssh key

    显示代码:

当你看到上面这段代码的收,那就说明,你的 SSH key 已经创建成功,你只需要添加到github的SSH key上就可以了。

添加你的 SSH key 到指定地方

这里我们举例 配置SSH Key 到 github上去

  • 首先你需要拷贝 id_rsa.pub 文件的内容:
    有三种方法:

    (1).pbcopy命令的方法
    pbcopy < ~/.ssh/id_rsa.pub

    (2).或者:cat命令的方法
    cat < ~/.ssh/id_rsa.pub

    (3).或者clip命令的方法
    clip < ~/.ssh/id_rsa.pub

    后者有可能会失败,提示-bash: clip: command not found,说明你的终端无没有clip命令。

  • 登录到github.com上面。从右上角的设置( Account Settings )点击出现下拉列表,然后点击菜单栏的 SSH and GPG keys 进入页面添加 SSH key。

  • 点击 Add SSH key 按钮添加一个 SSH key 。把你复制的 SSH key 代码粘贴到 key 所对应的输入框中,记得 SSH key 代码的前后不要留有空格或者回车。当然,上面的 Title是显示在 github 上的一个别名。默认的会使用你的邮件名称。

  • 测试一下该SSH key

    ssh -T git@github.com

    如果出现

    The authenticity of host 'github.com (207.97.227.239)' can't be established.    # RSA key fingerprint is 16:27:ac:a5:76:28:2d:36:63:1b:56:4d:eb:df:a6:48.    # Are you sure you want to continue connecting (yes/no)?
    

    这是正常的,你输入 yes 回车既可。如果你创建 SSH key 的时候设置了密码,接下来就会提示你输入密码:

    Enter passphrase for key '/c/Users/Administrator/.ssh/id_rsa’:
    
    当然如果你密码输错了,会再要求你输入,知道对了为止。
    注意:输入密码时如果输错一个字就会不正确,使用删除键是无法更正的。
    

    如果出现

    Hi your_username! You’ve successfully authenticated, but GitHub does not provide shell access.
    如果用户名是正确的,你已经成功设置SSH密钥。如果你看到 “access denied” ,者表示拒绝访问,那么你就需要使用 https 去访问,而不是 SSH 。

  • 如果把SSH部署到git@git.oschina码去上面的话,

    验证: ssh -T git@git.oschina.net

    第一次会提示你输入yes

    sc:~ mao$ ssh -T git@git.oschina.net
    The authenticity of host ‘git.oschina.net (120.55.226.24)’ can’t be established.
    ECDSA key fingerprint is SHA256:FQGC9Kn/eye1W8icdBgrQp+KkGYoFgbVr17bmjey0Wc.
    Are you sure you want to continue connecting (yes/no)? yes

    成功后会提示:
    sc:~ mao$ ssh -T git@git.oschina.net
    Welcome to Git@OSC,your username!

Cell高度的自适应

发表于 2017-04-25 | 分类于 iOS

前言


Auto sizing cell -estimatedRowHeight属性

iOS8之后,UITableView新增加了estimatedRowHeight属性,这样,我们可以用它来实现UITableViewCell的自动布局。就不用去计算每个cell上Label的高度再去约定cell的高度,甚至可以不用去实现heightForRowAtIndexPath的代理方法。


简单使用

先新建UITableViewCell

然后我们先添加上约束。这里我直接在storyboard上拉的,并关联Cell以便以自定的属性赋值。

需要注意的是:

1.label的高度不要约束定死,但是它离上下左右的距离要定好,label下面可以还有上些其他的控件要加在上面。

2.UITableViewCell的size inspector里面 Row Height 是Default而不是custom的数值。

3.label的的行数一定要设置为0,不然没有换行,系统不知道怎么去自动计算label的高度来进行调整。

设置estimatedRowHeight值

1.直接设值

self.tableView.estimatedRowHeight = 60;

2.或者分别给个大概值

- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath{

return 60;
}

完成后就可以看到效果了。

示例代码


注意事项

estimatedRowHeight是否可以随便设值?

虽然系统会自动帮我们调整cell的高度,而estimatedRowHeight的初始默认高度似乎没用,其实不然,estimatedRowHeight越接近cell的最终高度越好,因为cell的调整高度重绘cell会浪费程序的运行,就会相应的耗费资源。

因此可能会产生一些坑,比如设置初始值差距较大时,在调用scrollToRowAtIndexPath:滚动到最底部的方法时。就有可能出现此方法运行完了,cell的高度还没有调整完,导致视图显示不是最底部的小BUG.

参考

避免的方法

1.用dispatch_after一个很短的时间再去scrollToRowAtIndexPath。

2.设定estimatedRowHeight尽量接近最终的高度。
可以在

 - (CGFloat)tableView:(UITableView *)tableView   estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath{
return 60;//相对的计算一下高度。

}

Xcode的Toolbar显示控制

发表于 2017-04-11 | 分类于 Debug

前言

记得以前刚开始用Xcode进行iOS开发的时候,一看到Toolbar不显示,就立马有点呆了,特别是显示不全的话。这里我做一个简单的总结: 1.Xcode本身就可以控制Toolbar是否显示的。2.可能就出现Toolbar显示不全,就是没有显示工程以及选择运行设备(选择模拟器)的选项。


Toolrbar的显示和隐藏

在菜单栏中 点击”View“ 出现下拉菜单 ,可以选择 “Hide Toolbar“和”Show Toolbar“两种状态,对Toolbar进行控制。

Toolbar的控制


Toolbar的显示不全

就是在Toolbar中没有显示工程,以及选择模拟器的选项。

Toolbar的显示不全

我是这样出现这个问题的。我从SVN下把工程下载下来。工程是用一个workspace管理四个工程,而且就出现了没有选择工程的的那个选择框和后观的选择模拟器的选择框。

我试着重新打开Xcode,重新开机,都不行。当我选择其他工程的时候却是一切正常。

结论:这个是工程的问题。

管理Scheme的方法

  1. 点开No Scheme,会有三个选项,当有工程的时候,第一项我们再熟悉不过了,就是工程打包,制作静态库文件啊等要用的。现在没工程,点击无效果。

Toolbar的解决办法一

  1. 我们点击第二项进来就可以选择工程了。我这里有四个工程,其中BaseLibs是公共基础工程。这五个工程都可以加入。

Toolbar的解决办法一

  1. 选择时,选择带工程文件的图片,其他的库文件啊,三方文件啊,我们没有必要导进来。

Toolbar的解决办法一

  1. 加入之后,你就可以选择相应的工程,选择模拟器,进行调试和开发了。

  2. 如果你把多余的三方的文件导进来,也没关系,不影响你的开发。不过如果你有强迫症,觉得多余的不好,那你就可以进入第三项管理 Manage Schemes…进入

Toolbar的解决办法一

  1. 选中多加入的三方文件,点减号就可以删除了。

Toolbar的解决办法一

  1. 在添加工程的时候,我们也可以直接进入Manage Schemes…,再点击添加按钮,跟第New Scheme是一样的用法。

Toolbar的解决办法一

只要你对 New Scheme 和 Manage Schemes… 进行操作一次,你就立马会清楚明白了。


删除xcuserdata文件的方法

造成这种情况的原因:用户信息文件引起的Xcode不能默认识别工程。

  1. 先关闭Xcode,打开工程目录,在目录下找到*.xcodeproj文件,右键选择 “显示包内容“。

  2. 找到xcuserdata,xcshareddata的文件都删除了。

注意: xcworkspace,和pods里面都有data文件,我试的时候是直接把这里面的都删了。打开工程后,你就发现可以选择Scheme了,不过,这样一来,Scheme里面的选择项就把这个文件中所有的工程和三方,库文件都成列表显示在这里以供选择了。所以了,还是第一种方式最好,而且简单方便,易懂。

情景扩展: 既然是xcuserdata文件的原因,而我又是从SVN上拷贝下,那应该是项目经理以新建工程是,把工程中不需要上传的xcuserdata和xchareddata文件都上传到了SVN服务器上。导致了开发人员下载到本地用Xcode打开时无法默认工程。这也说明此项目经理对iOS苹果开发的不太深入造成的。


GCD如何实现最大并发数呢?

发表于 2017-04-11 | 分类于 iOS

前言

大家都知道对于NSOperationQueue队列来说,要实现最大并发数是比较轻而易举的事,只需要设置它的属性maxConcurrentOperationCount就可以办到。

 //创建一个队列(非主队列)
NSOperationQueue *queue = [[NSOperationQueue alloc] init];

//设置最大并发量(最多同时执行10个任务)
queue.maxConcurrentOperationCount = 10;

对GCD而,只有靠自己想方法处理

GCD可以用信号量semaphore来实现,费话不多说,直接上代码

//建立任务组
dispatch_group_t group = dispatch_group_create();

//设置信号量大小
dispatch_semaphore_t semaphore = dispatch_semaphore_create(10);

//创建全局队列
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

//添加实现任务
 for (int i = 0; i < 100; i++) {

      //semphore值为0时会一直等待执行。当>=1时执行下面的代码。可通过一次,会将semphore的值减1.
      dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);

      //监视queue队列
      dispatch_group_async(group, queue, ^{

            NSLog(@"这里在执行耗时操作----%i",i);
            sleep(2);

            //当前线程执行完成后,使semaphore的值加1,这样,如果semphore的值就加1,会触发dispatch_semaphore_wait执行一条代码
            dispatch_semaphore_signal(semaphore);    
     });
 }


//永远地监听Group中的任务是否执行完成。
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);

关于信号量的一些深刻的理解,可以察看 fhbystudy的分享,也谢谢他的分享!


Markdown语法的简单说明

发表于 2017-04-10 | 分类于 others

标题

总共可以有六级标题,标题用#后面需要加一个空格,抒写如下

1
2
3
4
5
6
# 标题一
## 标题二
### 标题三
#### 标题四
##### 标题五
###### 标题六

代码块

`内容` 可也部分包装成块: 看看内容就知道了

这是部分块

用 ``` 内容 ```包裹的内容会被灰色框包裹成块。

1
用三个点顿号

用~~~内容~~~ 也一样可以

1
也可以用三个~线

前边四个空格

在前边空四格

有序列表和无序列表

用*,- + 还是需要一个空格,就可以显示无序列表

  • 你好1
  • 你好2
  • 你好3
  • 你好4

用1. 2. 3. 后接空格,可以显示有序列列表

注意它不会因为前面数据的不对而不从1开始排序

  1. 这是1
  2. 这是2
  3. 这是3
  4. 这是4

文本的处理

粗体

用**内容** 内容将以粗体显示: 粗体

**这是粗体字**

斜体

用*内容* 内容会以斜体体字显示: 斜体

*这是斜体*

文字删除线

这个在markdown上我还没有看出效果,不是知道是不是版本更新的原因。
用~~内容~~ 在内容文字上会有删除线: 文字删除线

~~这是文字删除线~~

分割线

用三个*或者\—号,可以作一条分割线



邮箱和网址连接

邮箱

用<邮箱>可以高亮显示 15208105440@163.com

网址连接

用<网址>有效连接: https://maojianxiang.github.io


图片

图片跟网址连接相似,多了一个!

!+[]+(图片的地址,相对路径也行)


网址连接(带别名)

用 [别名](网址)显示别点,点击跳转到网址

头像 [我的头像](http://on55qmgxp.bkt.clouddn.com/avatar.png) 得到的效果如下

头像 我的头像

博客 我的博客


引用

可以是多级引用,只需要多加>即可

1
2
3
4
5
6
7
> 引用 
> >再次引用
> > > 三次引用
> > > > 四次引用
> > > > > ok 完了

效果如下所示:

引用

再次引用

三次引用

四次引用

ok 完了


表格Table

1
2
3
4
5
6
7
姓名 | 年龄 | 地点
----|---- | ----
李明 | 15 | place1
王强 | 52 | place2
天明 | 30 | place3

效果如下所示:
姓名 年龄 地点
李明 15 place1
王强 52 place2
天明 30 place3

数学公式

最后再介绍一个数学公司,我也不常用

1
2
3
4
5
6
7
<math display="block">
<msubsup><mi>A</mi> <mi>S</mi> <mi>T</mi></msubsup>
<mo>=</mo>
<mi>B</mi>
</math>

效果如下所示:

A S T
=
B

OC代码转化成C++代码

发表于 2017-04-09 | 分类于 others

其实平时写的OC代码最后都是通过runtime转化成了C++代码,对于OC的文件,我们也可以转化成C语言的代码文件,这对于我们 研究低层,理解运行方式和实现原理 是一种不错的办法,不过这样就要求你要看得懂C语言的代码。


  • 打开终端,进入OC代码文件所在的目录

    cd + 文件所在的文件夹,这里我是以main.m为例。
    
  • 用clang命令转化OC代码文件

    clang -rewrite-objc main.m
    
  • 现在在当前文件就生成了同名字,后辍为.cpp的C代码文件、可以直接用终端找开

    open main.cpp 
    
  • 这是我成功将main.m 转化出的结果.

  • 你可仔细地进行对比研究了。

数值的一些常用处理方式

发表于 2017-04-09 | 分类于 Math

小数的绝对值

处理int类型的取绝对值

int abs(int i);  

处理double类型(或者float)的取绝对值

double fabs(double i);

小数的四舍五入

简要介绍

round:参数是小数,则求本身的四舍五入。
ceil:参数是小数,则求最小的整数但不小于本身.
floor:如果参数是小数,则求最大的整数但不大于本身. 

例如

如果值是 10.4的话,则结果

-- round  --> 10
-- ceil   --> 11
-- floor  --> 10

如果值是 10.5的话,则结果

-- round  --> 11
-- ceil   --> 11
-- floor  --> 10

如何优雅地解决UIScrollView使用中的bug

发表于 2017-04-01 | 分类于 Debug

ScrollView的位置或者其子控件位置不正确

没有注意视图控制器的透视效果

特别是子控制器的位置不对,自己都会怀疑子控件是否加到ScrollView上面去了。

1. 一般情况下都会先打断点、NSLog输出看frame是否正确,不正确会调整它。如果发现frame完全正确,才会联想到视图控制器问题的显示自动调整,这样就离成功近了一步。
2. 如果你有成功的Demo,然后一一对应,才发现视图控制器还有个透视效果属性:automaticallyAdjustsScrollViewInsets,关闭之后一切就正常了。

总结

UIScrollView的位置或者子控件的位置不正确,首先要确定其父控制器的透视效果属性:automaticallyAdjustsScrollViewInsets。其次再去检查一下frame,这个问题就OK了。

如果在某中情况下automaticallyAdjustsScrollViewInsets属性没有设置反而显示正确,那它也会造成下面的第二个问题。

ScorllView左右上下都可以随便拖拽

1.一般会想到是否是UIScorllView的contensize的大小设置跟frame不匹配造成的。
 然后打断点,NSLog输出,看看frame和contentsize,发现没什么问题。这里你会想会不会是视图控制器自动调整了某些属性

2.想得深一点会想到UIScorllView的两个方向的bounce属性:alwaysBounceVertical,alwaysBounceHorizontal,但是我们仔细一看UIScorllView.h文件,明确提示默认就是关闭的。

3.除了第1点和第2点,还有遗漏的了种情况,也是控制器的透视效果automaticallyAdjustsScrollViewInsets造成的。

总结

在使用UIScorllView控件时

1.首先确定父控制器的透视效果automaticallyAdjustsScrollViewInsets已关闭。但是这个问题也会造成这种情况。

2.然后再UIScorllView的contensize和frame是否配置正确。

3.特别需要时配置一下属性bounces,alwaysBounceVertical,alwaysBounceHorizontal。

  就可以很好的控制UIScrollView的拖拽滚动问题了。

ScrollViewDelegate中的滑动事件重复处理

UIScrollViewDelegate的代理实现

1.Method1:offset变动的时间回调

- (void)scrollViewDidScroll:(UIScrollView *)scrollView;

2.Method2:UIScrollView拖动嘎然而止时回调。

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView;

设置UIScrollView的offset(Meth3)

- (void)setContentOffset:(CGPoint)contentOffset animated:(BOOL)animated;

注意:Method2是拖动停止的时候回调,而且不是时时监听,而Method1是只要offset变动时就会时时回调。而只要使用Method3就会运行Method1;这样就会容易造成一种BUG:

1.当UIScrollVie拖动后对外控件A时时造成影响,会在Method1中实现影响A的代码,同时结束后会运行Method2。

2.那如果A点击后影响UIScrollView的offset,我们会在A点击的事件中使用Method3,而Method3的运行又会造成Method1方法的运行,而这种情况却不会运行Method2。

Bug出现: A点击的时候,会使用Method3,间接运行Method1,而Method1中又会运行影响A的代码。(A只是点击却最后还会影响A)。

解决方法

是在Method1中判断是否是外部事件来决定是否运行影响A的代码。那这个判断怎么处理了,这个问题在我搭建滑动切换视图控制器的框架时遇到了。费了好些时间,最后我发现UIScrollView.isDragging属性直接判断是否是拖动的回调,UIScrollView自动在设置offset的时候和拖动的时候自动更改isDragging,还是最基础的方法最靠谱。

总结

1.UIScrollView使用时特别要注意要关闭父视图控制器的透视效果属性automaticallyAdjustsScrollViewInsets。否则会造成UIScrollView本身可以任意拖拽和本身及其子控件的位置问题。

2.UIScrollView拖动时时影响外部控件的时候,在 - (void)scrollViewDidScroll:(UIScrollView *)scrollView的方法中最好使用属性isDragging判断是拖动才去实现影响外部控件的代码。避免外部控件反过来作用scrollView的offset的情况。

最后推广一下让我写这篇博客的Demo:https://github.com/MaoJianxiang/SlideSwitchController

Xcode 错误- Could not launch app 解决办法

发表于 2017-03-17 | 分类于 Debug

Xcode 错误- Could not launch app - No such file or directory Error.

蛋疼的一个XCode bug,基本上应该不是工程本身问题。

解决方法:

1、拔掉设备,删除之前Build的内容

2、退出Xcode,不是关闭窗口

3、删除那个/Users/XXX/Library/Developer/Xcode/DerivedData/XXX-grgrmtzqajhyqgghabyjttajwbsm文件夹

4、启动XCode连接设备,现在应该OK了

在Category中可以添加属性吗?

发表于 2017-03-17 | 分类于 iOS

Category直接添加属性使用会报错

类目和属性(Category and Property)

关于property,有两个关键字@synthesize和@dynamic:

@synthesize: 实现property所声明的方法的定义。

property 声明方法 ->头文件中申明getter和setter方法 synthesize定义方法 -> m文件中实现getter和setter方法。 如果我们没有手动的实现property的setter和getter方法,编译器会自动的添加上这两个方法。

@dynamic:
告诉编译器,属性的setter与getter方法由用户自己实现,不自动生成。

在平常我们都习惯了不写这两个关键词,这个时候其实默认是 @synthesize var = _var

我直接在ViewController (extension)中定义一个name属性。不使用它的时候运行完好。一使用它的时运行就会报错:

[ViewController setName:]: unrecognized selector sent to instance 0x7f9473705540。
而且编译器直接就提供警告:

Property ‘name’ requires method ‘setName:’ to be defined - use @dynamic or provide a method implementation in this category。
意思是在这个类中,属性name的setter的定义方法,用@dynamic 或者提供一个方法来实现。

然后我们在implementation中添加 @dynamic name;这样警告消失,但是运行依然会报 unrecognized selector sent to instance xxx的错误。

然后我们在 implementation 中实现它的getter和setter方法,也会直接报错 undeciarediared identifier XX

1

结论

1.类目(category)可以添加属性,但不能实现部分的@synthesize。

  1. 类目中可以实现setter和getter方法,但是不存在_name的成员变量。

解决方法

这个时候应该怎么办呢?我们知道Obj-c是一门动态语言,强大的运行时(Runtime)机制能够为类关联引用,然后通过这种方法来实现给类别添加属性。其实就是动态绑定。

属性添加和检索关联

首先需要导入Runtime相关的头文件
#import <objc/runtime.h>

//这个方法时为对象object添加key指定的地址作为关键字,以value为值关联引用,第四个参数pilicy指的是关联引用的存储策略。 //通过将value设置为nil 可以删除key的关联 OBJC_EXPORT void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy) __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_1);

//返回object以key为关键字关联的对象,如果没有,则反火nil OBJC_EXPORT id objc_getAssociatedObject(id object, const void *key) __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_1);

如果我们需要为一个类别的多个属性关联引用,所以我们需要用不同的key值来区别。
而且键值必须要使用一个确定且不可变的地址。所以选择定义在实现文件的static静态局部变量的地址。
policy策略就跟定义property的时候才用的存储关键字相似了。

关联的policy策略

objc_AssociationPolicy policy:enum {

//五种类型
OBJC_ASSOCIATION_ASSIGN = 0, //关联对象的属性是弱引用 weak

OBJC_ASSOCIATION_RETAIN_NONATOMIC = 1, //关联对象的属性是强引用并且关联对象不使用原子性 strong

OBJC_ASSOCIATION_COPY_NONATOMIC = 3, //关联对象的属性是copy并且关联对象不使用原子性 copy

OBJC_ASSOCIATION_RETAIN = 01401, //关联对象的属性是retain并且关联对象使用原子性 strong copy

OBJC_ASSOCIATION_COPY = 01403 //关联对象的属性是copy并且关联对象使用原子性 copy atomic
};

断开关联

runtime 提供了断开关联的函数。但是更喜欢使用传入nil来断开关联,会更佳安全,毕竟,我不敢保证是不是有其他地方会使用到已经关联的对象。而且当category中添加多个属性的时候可以单个断开关联。

OBJC_EXPORT void objc_removeAssociatedObjects(id object) __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_1);

代码实现

Category属性检索关联(动态绑定)

1、 导入头文件

#import <objc/runtime.h>

2、 定义用作键值的静态变量

//static char *nameKey = “nameKey”;也行

static const char *nameKey = “nameKey”;

3、定义存取方法

-(NSString *)name{
return objc_getAssociatedObject(self, nameKey);
}

-(void)setName:(NSString *)name{
objc_setAssociatedObject(self, nameKey, name, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

使用运行

首先在category中定义两个关联属性

在vievcontroller中也定义了两个属性作为试验

然后用objc_removeAssociatedObjects(self);断开关联

然后输出结果,category中关联的属性两个都输出null而本身的属性正常输出。

总结

通过简单的验证我的发现
1、objc_removeAssociatedObjects(id object)是断开所有关联。
2、使用runtime给对象关联的属性跟本身的属性本质是是不一样的,可使用却是完全一样的。

12
小毛纯一郎

小毛纯一郎

致力于苹果移动应用的开发

20 日志
6 分类
17 标签
GitHub
友情链接
  • 毛建祥
  • CepheusSun
© 2018 小毛纯一郎
由 Hexo 强力驱动
主题 - NexT.Mist
本站访客数人次 本站总访问量次