背景。
请考虑以下步骤:
1) 在 Xcode 中创建一个新的“单 View 应用程序”。
2)创建类NSObject+Extension.h和.m文件:
// .h
@interface NSObject (Extension)
- (void)someMethod;
@end
// .m
@implementation NSObject (Extension)
- (void)someMethod {
NSLog(@"someMethod was called");
}
@end
3) 确保 NSObject+Extension.m 文件包含在主目标中。
4) 将以下行添加到 AppDelegate:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[[NSString new] performSelector:@selector(someMethod)];
return YES;
}
5) 确保 #import "NSObject+Extension.h line does not exists in anywhere in the app!
6) 运行应用程序。
输出是
2013-08-27 04:12:53.642 Experimental[32263:c07] someMethod was called
问题
我想知道是否在应用程序中的任何地方都没有此类别的任何#import,怎么可能NSString 仍然有 NSObject+Extension 可用?这种行为让我对我声明的每个 Objective-C 类别都感觉很糟糕,因为我希望我声明的类别仅在它们声明的范围内可用。例如,我希望 NSObject 仅在某些类中通过 Extension 进行扩展,而不是在整个应用程序中进行扩展,否则它的全局空间将被“污染”。
有没有办法避免这种行为?我确实希望我的类别仅在我明确导入它们时起作用,而不是在我将它们链接到我用来运行的目标时起作用。
最佳答案
I wonder if there is no any #import of this category anywhere in the app, how is it even possible that NSString does still have NSObject+Extension available? This behavior makes me feeling very bad about every Objective-C category I declare because I want the categories I declare to be available only in the scopes they are declared within. For example, I want NSObject to be extended by Extension only in some class but not in the whole app because its globalspace becomes "polluted" otherwise.
Objective-C 对象上没有命名空间。如果您声明一个类有一个方法(无论是通过类别还是在主 @interface 上),那么该类的每个实例都将有该方法。
Objective-C 处理“私有(private)”方法的方式是选择不告诉其他人有问题的方法(这是通过不#import-ing 声明这些方法的文件来实现的)方法)。这与 -Wundeclared-selector(如果您使用编译器不知道的选择器时发出警告)相结合,就相当于您将要获得的保护。
但无论如何,如果您将 .m 文件编译成最终的二进制文件,该方法将存在,即使没有其他人“知道”它。
Are there way to avoid this behavior? I do want my categories to work only when I explicitly import them, not just when I have them linked to a target I use to run.
是的,使用 -Wundeclared-selector,Xcode 会警告你。
关于ios - NSObject 的类别可用于每个 NSObject 子类,即使没有在任何地方导入该类别的 .h 文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18455541/
我尝试使用不同的ssh_options在同一阶段运行capistranov.3任务。我的production.rb说:set:stage,:productionset:user,'deploy'set:ssh_options,{user:'deploy'}通过此配置,capistrano与用户deploy连接,这对于其余的任务是正确的。但是我需要将它连接到服务器中配置良好的an_other_user以完成一项特定任务。然后我的食谱说:...taskswithoriginaluser...task:my_task_with_an_other_userdoset:user,'an_othe
我已经构建了一些serverspec代码来在多个主机上运行一组测试。问题是当任何测试失败时,测试会在当前主机停止。即使测试失败,我也希望它继续在所有主机上运行。Rakefile:namespace:specdotask:all=>hosts.map{|h|'spec:'+h.split('.')[0]}hosts.eachdo|host|begindesc"Runserverspecto#{host}"RSpec::Core::RakeTask.new(host)do|t|ENV['TARGET_HOST']=hostt.pattern="spec/cfengine3/*_spec.r
我在app/helpers/sessions_helper.rb中有一个帮助程序文件,其中包含一个方法my_preference,它返回当前登录用户的首选项。我想在集成测试中访问该方法。例如,这样我就可以在测试中使用getuser_path(my_preference)。在其他帖子中,我读到这可以通过在测试文件中包含requiresessions_helper来实现,但我仍然收到错误NameError:undefinedlocalvariableormethod'my_preference'.我做错了什么?require'test_helper'require'sessions_hel
这里有一个很好的答案解释了如何在Ruby中下载文件而不将其加载到内存中:https://stackoverflow.com/a/29743394/4852737require'open-uri'download=open('http://example.com/image.png')IO.copy_stream(download,'~/image.png')我如何验证下载文件的IO.copy_stream调用是否真的成功——这意味着下载的文件与我打算下载的文件完全相同,而不是下载一半的损坏文件?documentation说IO.copy_stream返回它复制的字节数,但是当我还没有下
我正在尝试解析一个文本文件,该文件每行包含可变数量的单词和数字,如下所示:foo4.500bar3.001.33foobar如何读取由空格而不是换行符分隔的文件?有什么方法可以设置File("file.txt").foreach方法以使用空格而不是换行符作为分隔符? 最佳答案 接受的答案将slurp文件,这可能是大文本文件的问题。更好的解决方案是IO.foreach.它是惯用的,将按字符流式传输文件:File.foreach(filename,""){|string|putsstring}包含“thisisanexample”结果的
1.错误信息:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:requestcanceledwhilewaitingforconnection(Client.Timeoutexceededwhileawaitingheaders)或者:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:TLShandshaketimeout2.报错原因:docker使用的镜像网址默认为国外,下载容易超时,需要修改成国内镜像地址(首先阿里
我花了几天时间尝试安装ruby1.9.2并让它与gems一起工作:-/我最终放弃了我的MacOSX10.6机器,下面是我的Ubuntu机器上的当前状态。任何建议将不胜感激!#rubytest.rb:29:in`require':nosuchfiletoload--mongo(LoadError)from:29:in`require'fromtest.rb:1:in`'#cattest.rbrequire'mongo'db=Mongo::Connection.new.db("mydb")#gemwhichmongo/usr/local/rvm/gems/ruby-1.9.2-p0/g
在Ruby中,是否有一种简单的方法可以将n维数组中的每个元素乘以一个数字?这样:[1,2,3,4,5].multiplied_by2==[2,4,6,8,10]和[[1,2,3],[1,2,3]].multiplied_by2==[[2,4,6],[2,4,6]]?(很明显,我编写了multiplied_by函数以区别于*,它似乎连接了数组的多个副本,不幸的是这不是我需要的)。谢谢! 最佳答案 它的长格式等价物是:[1,2,3,4,5].collect{|n|n*2}其实并没有那么复杂。你总是可以使你的multiply_by方法:c
print"Enteryourpassword:"pass=STDIN.noecho(&:gets)puts"Yourpasswordis#{pass}!"输出:Enteryourpassword:input.rb:2:in`':undefinedmethod`noecho'for#>(NoMethodError) 最佳答案 一开始require'io/console'后来的Ruby1.9.3 关于ruby-为什么不能使用类IO的实例方法noecho?,我们在StackOverflow上
我的rails3.1.6应用程序中有一个自定义访问器方法,它为一个属性分配一个值,即使该值不存在。my_attr属性是一个序列化的哈希,除非为空白,否则应与给定值合并指定了值,在这种情况下,它将当前值设置为空值。(添加了检查以确保值是它们应该的值,但为简洁起见被删除,因为它们不是我的问题的一部分。)我的setter定义为:defmy_attr=(new_val)cur_val=read_attribute(:my_attr)#storecurrentvalue#makesureweareworkingwithahash,andresetvalueifablankvalueisgiven