小编Mat*_*ing的帖子

查找Swift String中的字符索引

现在是承认失败的时候了......

在Objective-C中,我可以使用类似的东西:

NSString* str = @"abcdefghi";
[str rangeOfString:@"c"].location; // 2
Run Code Online (Sandbox Code Playgroud)

在Swift中,我看到类似的东西:

var str = "abcdefghi"
str.rangeOfString("c").startIndex
Run Code Online (Sandbox Code Playgroud)

...但是这只是给了我一个String.Index,我可以使用它来下标回原始字符串,但不从中提取位置.

FWIW,String.Index有一个私人ivar _position,它具有正确的价值.我只是看不出它是如何曝光的.

我知道我可以轻松地将它添加到String中.我对这个新API中缺少的东西更感兴趣.

string swift

194
推荐指数
10
解决办法
22万
查看次数

Xcode将哪些来源注释识别为标签?

这主要是出于好奇心.我已经知道Xcode能够以形式识别评论// TODO: Something I don't feel like doing now.将该行添加到文件源将导致该TODO注释显示在Xcode的导航栏中:

在此输入图像描述

我最近还发现表单的注释// MARK: Something可以达到与#pragma mark某些东西相同的效果.所以我可以写一个看起来像这样的评论:

// MARK: -
// MARK: Future Improvements:
// TODO: Make something better
// TODO: Fix some bug
Run Code Online (Sandbox Code Playgroud)

Xcode会像这样呈现出来:

在此输入图像描述

这让我想知道:Xcode可以理解其他类型的评论来改进项目导航吗?

xcode comments

38
推荐指数
2
解决办法
7327
查看次数

关于Objective-C类别和扩展的细节

我在尝试弄清楚为什么我在私有类别中声明的readwrite属性没有生成setter时学到了一些东西.这是因为我的类别被命名为:

// .m
@interface MyClass (private)
@property (readwrite, copy) NSArray* myProperty;
@end
Run Code Online (Sandbox Code Playgroud)

将其更改为:

// .m
@interface MyClass ()
@property (readwrite, copy) NSArray* myProperty;
@end
Run Code Online (Sandbox Code Playgroud)

我的二传手是合成的.我现在知道,类扩展不仅仅是匿名类别的另一个名称.保留一个未命名的类别会导致它变成一个不同的野兽:一个现在提供编译时方法实施强制并允许你添加ivars.我现在理解每个基础的一般原理:类别通常用于在运行时向任何类添加方法,而类扩展通常用于强制私有API实现并添加ivars.我接受这个.

但有些小事让我感到困惑.首先,在高层:为什么要这样区别?这些概念看起来像是类似的想法,无法决定它们是相同的还是不同的概念.如果它们是相同的,我希望使用没有名称的类别和具有命名类别(它们不是)的类别可以完全相同.如果它们不同,(它们是)我会期望两者之间存在更大的语法差异.看起来很奇怪,"哦,顺便说一句,要实现一个类扩展,只需写一个类别,但忽略名称.它神奇地改变了."

第二,关于编译时强制的主题:如果你不能在命名类别中添加属性,为什么这样做会说服编译器你就是这么做的?为了澄清,我将用我的例子来说明.我可以在头文件中声明一个readonly属性:

// .h
@interface MyClass : NSObject
@property (readonly, copy) NSString* myString;
@end
Run Code Online (Sandbox Code Playgroud)

现在,我想转到实现文件并给自己私有的readwrite访问属性.如果我做得正确:

// .m
@interface MyClass ()
@property (readwrite, copy) NSString* myString;
@end
Run Code Online (Sandbox Code Playgroud)

当我不合成时,我会收到警告,当我这样做时,我可以设置属性,一切都很好.但是,令人沮丧的是,如果我碰巧有点误导了类别和类扩展之间的区别,我尝试:

// .m
@interface MyClass (private)
@property (readwrite, copy) NSString* myString;
@end
Run Code Online (Sandbox Code Playgroud)

编译器完全安心认为属性是readwrite.我没有得到任何警告,甚至没有好的编译错误"对象无法设置 - 无论是readonly属性还是没有找到setter",在设置myString时我都没有在类别中声明readwrite属性.我只是在运行时获得"不响应选择器"异常.如果(命名)类别不支持添加ivars和属性,那么要求编译器按相同规则播放是否太过分了?我错过了一些宏伟的设计理念吗?

objective-c

34
推荐指数
2
解决办法
7703
查看次数

NSURLConnection与NSData + GCD

NSData一直有一个非常方便的方法叫做+dataWithContentsOfURL:options:error:.虽然方便,但它也会阻止当前线程的执行,这意味着它对生产代码(忽略NSOperation)基本上没用.我很少使用这种方法,我完全忘记了它的存在.直到最近.

我从管中获取数据的方式是标准NSURLConnectionDelegate方法:编写一个处理各种NSURLConnectionDelegate方法的下载类,逐步构建一些数据,处理错误等.我通常会使这个通用的足以重用为尽可能多的要求.

假设我的典型下载程序类在100行的球场中运行.这是100行异步做什么NSData可以在一行同步.为了更复杂,下载程序类需要自己的委托协议来向其所有者传达完成和错误,并且所有者需要以某种方式实现该协议.

现在,进入Grand Central Dispatch,我可以做一些非常简单的事情:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void) {

    NSData* data = [NSData dataWithContentsOfURL:someURL];
    // Process data, also async...

    dispatch_async(dispatch_get_main_queue(), ^(void) {
        // Back to the main thread for UI updates, etc.
    });
});
Run Code Online (Sandbox Code Playgroud)

而且我可以把这个傻瓜扔进我想要的任何地方,就像在线一样.无需下载类,无需处理连接委托方法:只需几行即可轻松实现异步数据.这种方法与我之前的GCD方法之间的差异非常大,足以触发太好的真实警报.

因此,我的问题:使用NSData+ GCD进行简单的数据下载任务是否有任何警告而不是NSURLConnection(假设我不关心下载进度之类的事情)?

objective-c nsurlconnection grand-central-dispatch ios

29
推荐指数
2
解决办法
7521
查看次数

Objective-C"私有"方法的命名约定是什么?

继承其他开发人员的代码使我坚信通过类扩展从类的公共接口中保留尽可能多的消息.我也坚信为类的特定于实现的私有成员采用特殊的命名约定.我真的希望能够一目了然地告诉我们发送的消息以及在实现环境中被引用的成员是不是供公众使用,反之亦然.如果没有别的,它会使我更容易掌握一个班级的整体语义,这是值得的.

理由之外,我写的类容载有容载量2的私有方法,但我从来没有真正拿出一个模式来命名,我真的很喜欢(像我做的ivars争议ivar_约定).值得注意的例子:

@interface myClass()

// I like this, but as we all know, Apple has dibs on this one, 
// and method name collisions are nasty.
- (void)_myPrivateMessage;

// The suffix version promoted by Google for ivars doesn't really translate
// well to method names in Objective-C, because of the way the method
// signature can be broken into several parts.
- (void)doWork_; // That's okay...
- (void)doWork_:(id)work with_:(id)something; // That's just ugly and tedious...
- (void)doWork_:(id)work with_:(id)something …
Run Code Online (Sandbox Code Playgroud)

cocoa cocoa-touch objective-c naming-conventions

20
推荐指数
3
解决办法
3134
查看次数

我可以使用AVFoundation将下载的视频帧流式传输到OpenGL ES纹理中吗?

我已经能够使用AVFoundation的AVAssetReader类将视频帧上传到OpenGL ES纹理中.但是,它有一个警告,因为当它与AVURLAsset指向远程媒体一起使用时会失败.这个失败没有很好的记录,我想知道是否有任何解决方法的缺点.

streaming opengl-es objective-c avfoundation ios

20
推荐指数
1
解决办法
8930
查看次数

可以在OpenGL ES中的EAGLContexts之间共享顶点数组对象(VAO)吗?

剧透:我对答案很有信心NO,但这只是经过一天非常沮丧的调试之后.现在我想知道是否确实如此(如果是这样,我可能知道的话),或者我是否只是做了一些完全错误的事情.

这是情况.我正在使用OpenGL ES 2.0来渲染我从各种文件(.obj,.md2等)加载的一些网格物体.为了性能和用户体验,我使用GCD将这些网格及其相关纹理的实际加载委托给后台线程.

根据Apple的 说明,在每个后台线程上,我创建并设置一个与shareGroup主渲染上下文相同的新EAGLContext .这允许在后台线程上创建的OpenGL对象(如纹理和缓冲区对象)立即被主线程上下文使用.

这一直在努力.现在,我最近了解到顶点数组对象是一种缓存与渲染某些缓冲区内容相关的OpenGL状态的方法.它看起来不错,并减少了样板状态检查和设置渲染每个网格所需的代码.最重要的是,Apple还建议在他们使用顶点数据最佳实践指南中使用它们.

但是我在让VAO为我工作时遇到了严重的问题.就像我对所有加载一样,我会将网格从文件加载到后台线程的内存中,然后生成所有关联的OpenGL对象.没有失败,我第一次尝试glDrawElements()使用VAO 调用时,应用程序崩溃了EXC_BAD_ACCESS.没有VAO,它就会很好.

调试EXC_BAD_ACCESS是一种痛苦,特别是当NSZombies无法帮助时(他们显然不会这样做),但经过一段时间分析捕获的OpenGL帧后,我意识到,虽然在后台线程上创建VAO很顺利(不GL_ERROR,当一个时间来到主线程上的VAO时,我会得到一个GL_INVALID_OPERATION,当尝试绑定到一个不存在的VAO时,文档状态会发生.果然,看着在渲染时当前上下文中的所有对象的时候,没有一个单一的VAO待观察,但都与VAO生成的维也纳各组织在同一时间存在.如果我在主线程上加载VAO它可以正常工作.很沮丧.

我将加载代码提炼为更原子的形式:

- (void)generate {

    glGenVertexArraysOES(1, &_vao);
    glBindVertexArrayOES(_vao);

    _vbos = malloc(sizeof(GLuint) * 4);
    glGenBuffers(4, vbos);
}
Run Code Online (Sandbox Code Playgroud)

当在后台线程上执行上述操作时,如果有效EAGLContextshareGroup主上下文相同,则主上下文将有4个VBO,但没有VAO.如果我在主线程上执行它,使用主上下文,它将有4个VBO和VAO.这使我得出结论,EAGLContext在处理VAO时,s 的对象共享性质存在一些奇怪的例外.如果确实如此,我真的希望Apple文档能够在某处注明.不得不手动发现这样的小花絮是非常不方便的.是这样的,还是我错过了什么?

multithreading opengl-es objective-c eaglcontext ios

19
推荐指数
1
解决办法
2527
查看次数

使用Objective-C点运算符混合C前/后递增/递减有效吗?

假设我有一个标量属性类的类:

@property (nonatomic, assign) int myInt;
Run Code Online (Sandbox Code Playgroud)

为清楚起见,合成如下:

@synthesize myInt = _myInt;
Run Code Online (Sandbox Code Playgroud)

如果有人问我以下行是否有效:

self.myInt++;
Run Code Online (Sandbox Code Playgroud)

我会说"不".理由是我们都知道点运算符只是用于调用编译器生成的getter方法的语法糖.这条线就是字面意思:

[self myInt]++;
Run Code Online (Sandbox Code Playgroud)

如果你在Xcode中键入第二行,它将无法编译,说明:"分配给'readonly'不允许使用objective-c消息的返回结果".这是完全合理的,这是我所期望的.即使编译完成,我也希望结果能够增加堆栈上支持ivar的副本,而不是ivar本身.

但是,指令self.myInt++确实编译,并且它有效.它就像点运算符直接访问_myInt一样工作.通过提供我自己的getter和setter,我可以看到getter和setter都在这个过程中按顺序使用,就像它实际上一样:

[self setMyInt:[self myInt] + 1];
Run Code Online (Sandbox Code Playgroud)

那么,点运算符与方法调用完全相同的规则是一个例外,或者{--, ++, +=, -=}与点符号一起使用时,Objective-C编译器是否特别关注运算符?我一直认为它们是C语言的特性而没有特别考虑Objective-C.我可以看到这条简单的线条对于不熟悉Objective-C点符号的人来说非常混乱.

syntax objective-c

16
推荐指数
1
解决办法
1189
查看次数

是什么决定状态栏中是否存在iPhone位置服务图标?

这是我的情况.我正在开发一个使用Core Location来确定设备位置的iPhone应用程序.有一个图标:位置服务图标,显示在设备的状态栏中.我知道该图标的目的是告诉用户当前正在使用位置服务.对于敏锐的用户,这意味着电池寿命缩短.出于这个原因,我想确保只有当我的应用实际使用位置服务时才会显示图标.

输入混乱.作为开发人员,我们无法通过官方SDK访问状态栏.这意味着操作系统将根据应用程序的行为自动显示该图标.尽我所能,我找不到明确定义该图标显示的原因.

目前,图标出现在我的应用代表获得控制权之前,只要应用程序已安装,运行与否,它就会保持可见状态.这显然是最糟糕的情况,它让我怀疑我的使用CLLocationManager.我会详细说明我的用法,但作为极端情况,我尝试删除CoreLocation框架(以及MapKit框架,我怀疑它也使用CoreLocation),以及与位置相关的所有代码.在我删除应用程序之前,应用程序仍会显示图标并保持不变.然后,我创建了一个全新的应用程序,除了更改应用程序标识符以匹配我的应用程序的标识符之外,不做任何更改.图标仍然出现.我更改了标识符以使用我的某个未使用位置的应用程序的标识符,并且未显示图标.我确实确保在此测试期间重置设备.

这个问题真的让我很伤心.我无法想象应用程序ID与位置服务图标有什么关系,但我认为其持久性没有其他原因.它似乎是一个隐藏真正问题的红鲱鱼,但我对真正的问题感到茫然.

iphone objective-c core-location

15
推荐指数
2
解决办法
3230
查看次数

是什么原因(以及如何修复)这个奇怪的核心位置错误?

ERROR,Generic,Time,320195751.128,Function,"void CLClientHandleRegistrationTimerExpiry(__ CFRunLoopTimer*,void*)",注册计时器已过期,但客户端仍在注册!

我能够在更广泛的互联网上挖掘出这个问题,但是没有人提供有用的信息.这是上下文:

我有一个应用程序通过CLLocationManager的startUpdatingLocation方法监视设备的位置.它开始监视,运行一段时间,然后在调试输出中弹出此消息.从那时起,不再提供位置更新.

这个错误正在扼杀应用程序的位置功能,我对可能导致它的原因感到茫然.它甚至在最后都有一个感叹号,这意味着它显然是一个令人兴奋的错误.

更新:
虽然我从来没有找到问题的解决方案,或者弄清楚为什么它首先发生,但我也失去了重现它的能力.这似乎发生在我做了很多事情的一段时间内,包括代码结构的一般变化,然后更新到iOS 5 beta.似乎有些东西让我沉默了.

iphone objective-c core-location ios

15
推荐指数
1
解决办法
2603
查看次数