在Apple的并发编程指南中,NSOperation子类示例(非并发和并发变量)使用异常处理,我想知道为什么他们在操作中鼓励这种风格.
清单2-4响应取消请求
- (void)main {
@try {
BOOL isDone = NO;
while (![self isCancelled] && !isDone) {
// Do some work and set isDone to YES when finished
}
}
@catch(...) {
// Do not rethrow exceptions.
}
}
Run Code Online (Sandbox Code Playgroud)
我的理解是,通常异常处理不是Objective-C代码中的常见做法 - 异常本质上是程序员错误,应该导致应用程序崩溃,而意外输入最好由NSError处理.(我可能误导理解来自之类的东西这个和这个)
我想知道NSOperations是否存在特殊情况,其中异常处理很重要,或者这是否是该指南的特定作者的首选样式.
作为旁注,一些NSOperation示例代码遵循此样式,其他示例则不遵循此样式.大多数高可见性OSS不使用例外(例如AFNetworking).
我试图更好地理解操作和线程,并查看AFNetworking的AFURLConnectionOperation子类,例如,真实世界的源代码.
我目前的理解是当实例NSOperation被添加到操作队列时,队列等管理负责执行操作的线程.在苹果公司的文档,NSOperation它指出,即使子类返回YES的-isConcurrent操作将始终在一个单独的线程来启动(为10.6).
基于Apple在线程编程指南和并发编程指南中强大的语言,管理线程似乎最好留给内部实现NSOperationQueue.
但是,AFNetworking的AFURLConnectionOperation子类产生了一个新的NSThread,并且操作-main方法的执行被推送到此网络请求线程.为什么?为什么这个网络请求线程是必要的?这是一种防御性编程技术,因为该库旨在供广大受众使用吗?调试库的消费者是不是更麻烦?在专用线程上进行所有网络活动是否有(微妙的)性能优势?
(
在1月26日添加)在Dave Dribin 的博客文章中,他演示了如何使用NSURLConnection的具体示例将操作移回主线程.
我的好奇心来自Apple的线程编程指南中的以下部分:
保持你的线程合理繁忙.
如果您决定手动创建和管理线程,请记住线程占用宝贵的系统资源.您应该尽力确保为线程分配的任何任务都是合理的长寿和高效的.与此同时,您不应该害怕终止花费大部分时间闲置的线程.线程使用大量内存,其中一些是有线的,因此释放空闲线程不仅有助于减少应用程序的内存占用,还可以释放更多物理内存供其他系统进程使用.
在我看来,AFNetworking的网络请求线程没有"保持相当忙碌"; 它正在运行一个无限的while循环来处理网络I/O. 但是,请注意,这就是问题的关键 - 我不知道,我只是在猜测.
AFURLConnectionOperation对操作,线程(运行循环?)和/或GCD的具体问题的任何洞察或解构都将非常有利于填补我理解的空白.
objective-c nsoperation nsthread nsoperationqueue afnetworking
编译器似乎对以下两个声明没有问题:
NSObject * __weak weakThing;
__weak NSObject *anotherWeakThing;
Run Code Online (Sandbox Code Playgroud)
这两者有区别吗?行为是否像const关键字一样?
我问,因为Xcode的警告通常建议......
SomeDataType*__weak/__strong
......当你搞砸了什么.所以我试图遵循这种模式,但想知道是否存在差异.
我很惊讶地发现以下行为......
@interface Foo : NSObject
- (void)addBar:(id)aBar withCompletion:(void(^)(void))completion;
@end
@interface AwesomeClass : NSObject
@property (strong, nonatomic) Foo *foo;
- (void)doSomethingWithBar:(id)bar;
@end
@implementation AwesomeClass
- (void)doSomethingWithBar:(id)bar
{
[self.foo addBar:bar withCompletion:^{
NSLog(@"%@", self.foo);
}];
}
Run Code Online (Sandbox Code Playgroud)
在Xcode 4.6.1中,我在实现中得到警告-doSomethingWithBar:,"在这个块中强烈捕获'自我'可能会导致保留周期."
但是,如果我重构名称的方法-addBar:withCompletion:来-setupBar:withCompletion:此警告消失.看来我的惊喜表明我对Objective-C命名约定的知识存在差距!
我来自Objective-C,我们没有包和命名空间.
Android有android.text.format.DateFormat具有返回java.text.DateFormat中的实例(静态方法getLongDateFormat()和getMediumDateFormat()具体).
这些方法是否可以互换地称为"静态方法"或"类方法"?
看看Android文档,我怎么想知道android.text.format.DateFormat方法返回一个java.text.DateFormat实例而不是android.text.format.DateFormat实例(返回后者的实例就是我最初的预期)?
如何导入必要的包以便能够在我的源中使用这两个类?
是否可以这样编写我的实现代码:
DateFormat df = DateFormat.getLongDateFormat(this.getActivity());
mLabel.setText(df.format(mEvent.getDate());
Run Code Online (Sandbox Code Playgroud)
我写它的另一种方法是使用完整的包名,但这似乎是不必要的:
java.text.DateFormat df = android.text.format.DateFormat.getLongDateFormat(this.getActivity());
mLabel.setText(df.format(mEvent.getDate());
Run Code Online (Sandbox Code Playgroud) 背景:直到Xcode 4.2,使用任何模板创建的新项目都包含MainWindow.xib,因此将nil作为UIApplicationMain()的第四个参数传递.从Xcode 4.2开始,所有模板都通过将类字符串作为第四个参数传递来实例化应用程序委托,而不是在xib中构建应用程序的窗口.
在4.2中完成此设置是微不足道的,当然它按预期工作:创建xib设置文件的所有者到UIApplication并连接委托,在Info.plist中指定它,在main()中指定第四个参数.
问题:为什么Apple鼓励实例化应用程序委托并在代码中构建UIWindow而不是"旧方法"?有什么好处?
注意事项:如果您选择使用故事板作为管理UI的方式,我会期望这种新的模板行为,但是如果您取消选中"使用故事板",我会期望旧的pass-nil-and-use-MainWindow.xib模板.
这个问题在这里以迂回的方式提出,但讨论的答案有点薄弱.
实体:
关系:
在播放列表实体中,我没有公开playlistItem关系/集.相反,我有一个名为"视频"的瞬态未定义属性,它是通过对播放列表项集进行排序而生成的视频实体数组.播放列表和视频实体之间没有关系.
我在托管对象上下文中保存修改后的播放列表实例时遇到问题.
从playlist.m(NSManagedObject子类):
- (BOOL)validatePlaylistItems:(NSSet **)playlistItems error:(NSError **)outError
{
NSArray *currentVideos = [self videos];
NSArray *persistedVideos = [self videosFromPlaylistItems];
if ([currentVideos isEqual:persistedVideos]) {
return YES;
}
NSManagedObjectContext *context = [self managedObjectContext];
for (FHPlaylistItem *pi in *playlistItems) {
[context deleteObject:pi];
}
NSArray *videos = [self primitiveVideos];
NSUInteger count = [videos count];
for (int i = 0; i < count; i++) {
FHPlaylistItem *pi = [FHPlaylistItem playlistItemWithVideo:[videos objectAtIndex:i]
forIndex:i
insertIntoManagedObjectContext:[self managedObjectContext]]; …Run Code Online (Sandbox Code Playgroud) -[NSFileManager URLForDirectory:inDomain:appropriateForURL:create:error:]需要单个NSSearchPathDomainMask并返回单个URL.(该...appropriateForURL:create:error:部分在文档中有点令人困惑.)
-[NSFileManager URLsForDirectory:inDomains:] 允许您为domains参数创建位掩码并返回URL数组.
在我看来,这两种方法之间存在重叠.如果我的目标是从iOS应用程序的沙箱中获取Documents,或Library或etc目录,我何时应该使用另一个?
假设以下玩具示例:
protocol AwesomeType: Equatable {
var thingy: Int { get }
}
extension Array where Element: Equatable {
func doThing { ... }
}
extension Array where Element: AwesomeType {
func doThing { ... }
}
extension String: AwesomeType {
var thingy: Int { return 42 }
}
Run Code Online (Sandbox Code Playgroud)
如果我有一个Strings - 的数组[ "Foo", "Bar", "Baz" ]- 我打电话doThing()给它,将调用哪个实现?为什么?
我相信这是在编译时确定的; 换句话说,它不是一个动态的调度.但它是如何确定的?感觉它类似于协议扩展的规则,但这是一个动态的调度情况......
是否会明确声明类final并确保private注释的内容会增加或减少编译时间?我理解它如何通过减少动态调度来影响运行时.
有趣的是,我在一个中等大小的项目上试过这个(并打开Xcode默认打印编译时间),编译时间惊人地增加了(8秒).是不是更容易理解所有代码如何与消除子类的提示相结合?
objective-c ×3
nsoperation ×2
swift ×2
afnetworking ×1
clang ×1
compilation ×1
core-data ×1
exception ×1
generics ×1
ios ×1
ios5 ×1
java ×1
mainwindow ×1
namespaces ×1
nsthread ×1
packages ×1
xcode ×1
xcode4 ×1