在Objective-C中,我创建了一个非常方便的类别(在Swift术语中的扩展) NSObject该添加到任意的键/值对添加到任何的能力NSObject在运行时.它使用关联对象将可变字典附加到对象,然后提供get/set方法,用于从/到该字典获取/设置键/值对.它只有几行代码.
这使得可以在运行时将任意键/值对附加到ANY对象,包括由系统创建的对象.这是关键.在某些情况下,系统框架会向您返回一个对象,您需要能够为其附加值.
此技巧还可以创建具有新实例变量的类别.(好吧,它们不是真的,但是它确实允许你向类别中的对象添加新的状态变量.)
这在Swift 1.2中是不可能的,因为:
在Swift 1.2下我不得不放弃这个.
但Swift 2允许扩展协议.我想"很好,现在我可以添加我的扩展,让我可以向AnyObject添加键/值对!"
没有快乐.
当我尝试为AnyObject创建扩展时:
extension AnyObject: AssociatedObjectProtocol
Run Code Online (Sandbox Code Playgroud)
我收到错误消息
'AnyObject'协议无法扩展
Arghh!如此接近,但不是.似乎该语言明确禁止扩展AnyObject.为什么会这样,有什么办法吗?
我不经常在NSObject上使用我的类别,但是当我这样做时,它是一个救星.我想把它添加到我在Swift中的技巧包中.
我可以像在Objective-C中那样将它添加到NSObject,但这意味着它只适用于从NSObject继承的对象 - 使其不适用于本机Swift类.
我在网上看到了新发布的iOS 7.1的iBeacon支持.
特别:
我无法通过自己的测试来确认这些声明中的任何一个.事实上,我似乎不太可能从锁定的设备获取didEnterRegion/didExitRegion通知.(更准确地说,我似乎得到了didEnterRegion通知,但没有得到didExitRegion通知).这可能是因为Apple让我删除了我的info.plist中的BLE背景模式条目 - 我不完全确定.我还在努力解决这个问题.
即将推出的OSX 10.10("Yosemite")提供了一种新型视图NSVisualEffectView,它支持窗口内或窗口内的半透明效果.我对窗口的半透明感兴趣,所以我将在这个问题中专注于这一点,但它也适用于窗口内的半透明度.
在10.10中使用窗口半透明是微不足道的.您只需NSVisualEffectView在视图层次结构中放置一个位置并将其设置blendingMode为NSVisualEffectBlendingModeBehindWindow.这就是全部.
在10.10下你可以NSVisualEffectView在IB中定义s,设置它们的混合模式属性,然后你就可以开始运行了.
但是,如果您希望向后兼容早期的OSX版本,则无法执行此操作.如果您尝试NSVisualEffectView在XIB中包含一个,则在尝试加载XIB时会立即崩溃.
我想要一个"设置并忘记它"的解决方案,它将在10.10下运行时提供半透明效果,并且在早期操作系统版本上运行时简单地降级为不透明视图.
到目前为止我所做的是在XIB中使有问题的视图成为普通的NSView,然后添加检查的代码(由awakeFromNib调用),[NSVisualEffectView class] != nil当它被定义时,我创建了一个NSVisualEffectView的实例,将我当前视图的所有子视图移动到新视图,并将其安装到位.这是有效的,但它是我每次想要半透明视图时必须编写的自定义代码.
我想这可能是使用NSProxy对象.这就是我的想法:
定义NSView的自定义子类(让我们称之为MyTranslucentView).在所有的init方法(initWithFrame和initWithCoder)中,我会抛弃新创建的对象,而是创建一个具有私有实例变量(myActualView)的NSProxy子类.在初始时间,将决定以创建myActualView对象作为NSVisualEffectView如果OS> = 10.10,和OS下一个正常的NSView <10.10.
代理会将所有消息转发给myActualView.
这将是相当多的繁琐,低级代码,但我认为它应该工作.
有没有人做过这样的事情?如果是这样,你能指出我正确的方向还是给我任何指示?
苹果是MUCH更加开放与约塞米蒂一个测试版协议比以前的Beta版本.通过谈论这一点,我不认为我违反了我的Beta NDA,但实际使用的代码NSVisualEffectView可能需要在NDA下共享...
我已经看到传递语句,你可以输入复杂的语句,如LLDB命令中的for循环(在你正在调试的程序的语言中 - 在这种情况下是Objective-C)
我真的希望能够做到这一点.我从来没有学过Python,并且不想花时间这么做以便使用可用的python LLDB支持 - 当天没有足够的时间.
Swift具有OptionSet类型,它基本上将集合操作添加到C样式位标志.Apple在他们的框架中广泛使用它们.示例包括选项参数animate(withDuration:delay:options:animations:completion:).
从好的方面来说,它可以让你使用干净的代码:
options: [.allowAnimatedContent, .curveEaseIn]
Run Code Online (Sandbox Code Playgroud)
但是,也存在不利因素.
如果我想显示一个指定的值OptionSet,似乎没有一个干净的方法来做它:
let options: UIViewAnimationOptions = [.allowAnimatedContent, .curveEaseIn]
print("options = " + String(describing: options))
Run Code Online (Sandbox Code Playgroud)
显示非常无用的消息:
options = UIViewAnimationOptions(rawValue:65664)
其中一些位字段的文档将常量表示为二次幂值:
flag0 = Flags(rawValue: 1 << 0)
Run Code Online (Sandbox Code Playgroud)
但是我的示例OptionSet的文档UIViewAnimationOptions并没有告诉你关于这些标志的数值的任何信息,并且从十进制数中找出位并不是直截了当的.
是否有一些干净的方法将OptionSet映射到选定的值?
我想要的输出是这样的:
options = UIViewAnimationOptions([.allowAnimatedContent,.curveEaseIn])
但是如果没有一堆杂乱的代码需要我为每个标志维护一个显示名称表,我想不出办法做到这一点.
(我有兴趣为我自己的代码中创建的系统框架和自定义OptionSet执行此操作.)
Enums允许您同时拥有枚举的名称和原始值,但这些不支持使用OptionSets获得的set函数.
我正在尝试将我们的一个应用程序的新版本准备好提交到Mac App Store.
当我尝试验证存档时,我收到一条消息"您的应用程序包必须安装到"/ Applications"'.
我已经尝试过各种各样的东西试图解决它,但没有快乐.
我正在为一个客户端开发一个现有的(非app-store)应用程序,该应用程序使用IOSurface私有框架在后台进行屏幕捕获.这里有几个线程概述了技术,以及几个开源示例项目.
同样,这是客户端使用的内部应用程序.它不适用于app-store发布,因此它使用私有框架的事实是可以接受的.
这是Github上的一个示例项目,它使用了一种非常相似的技术:
https://github.com/k06a/UIView-FastScreenshot
我只是尝试在最新的iOS 9测试版上运行客户端的应用程序,并且它因无法加载库CoreSurface的错误而崩溃.
我已经看到文档CoreSurface是框架的先前名称IOSurface,但似乎在iOS 8中确实存在一个私有框架CoreSurface以及一个名为的私有框架IOSurface.
还有其他人能够用来IOSurface在iOS 9中从后台进行屏幕截图吗?
我正在为任何可以给我一个方法来为iOS 9做这个工作的人添加赏金(再次,私有框架很好,但它不能在Jailbroken设备上)
我最近一直在学习Swift.
我决定编写一个混合的Swift/Objective-C应用程序,它使用两种语言实现的相同算法完成计算密集型任务.
该程序计算大量素数.
我定义了一个协议,Swift和Objective-C版本的计算对象都应该符合.
对象都是单例,所以我在Objective-C中创建了一个典型的单例访问方法:
+ (NSObject <CalcPrimesProtocol> *) sharedInstance;
Run Code Online (Sandbox Code Playgroud)
整个协议看起来像这样:
#import <Foundation/Foundation.h>
@class ComputeRecord;
typedef void (^updateDisplayBlock)(void);
typedef void (^calcPrimesCompletionBlock)(void);
@protocol CalcPrimesProtocol <NSObject>
- (void) calcPrimesWithComputeRecord: (ComputeRecord *) aComputeRecord
withUpdateDisplayBlock: (updateDisplayBlock) theUpdateDisplayBlock
andCompletionBlock: (calcPrimesCompletionBlock) theCalcPrimesCompletionBlock;
@optional //Without this @optional line, the build fails.
+ (NSObject <CalcPrimesProtocol> *) sharedInstance;
@end
Run Code Online (Sandbox Code Playgroud)
该类的Objective-C版本完全按照上面的定义实现方法,不用担心.
swift版本有一个方法:
class func sharedInstance() -> CalcPrimesProtocol
Run Code Online (Sandbox Code Playgroud)
但是,如果我使该方法成为协议的必需方法,我得到编译器错误"类型"CalcPrimesSwift不符合协议'CalcPrimesProtocol'.
但是,如果我在协议中将单例类方法sharedInstance标记为可选,那么它可以工作,我可以在我的Swift类或Objective-C类上调用该方法.
我是否错过了Swift类方法定义中的一些细微之处?考虑到我可以在我的Swift类或Objective-C类上调用sharedInstance()类方法,这似乎不太可能.
您可以从Github下载该项目,如果您愿意,可以查看它.它叫做SwiftPerformanceBenchmark.(链接)
interop objective-c objective-c-protocol swift objective-c-nullability
回到2016年11月,我发布了一个问题,询问为什么我不能使用guard来创建一个使用与可选项相同名称的变量的解包版本,就像你可以使用if:
当我写下这个问题时,下面的代码将无法编译,并出现"定义与先前值冲突"的错误:
//Test of using guard to create an unwrapped version of a var, like if let
func guardTest(_ viewController: UIViewController?) -> UIViewController? {
// Check if the current viewController exists
print(String(describing: viewController))
guard let viewController = viewController else {
return nil
}
print(String(describing: viewController))
return viewController
}
Run Code Online (Sandbox Code Playgroud)
但是,我刚刚在工作中发现了一些代码,它现在可以编译而无需投诉,并按照我的意愿行事!运行时,print语句显示foo在guard之前是可选的,而在以下之后是一个unwrapped可选:
viewController = Optional(<TrochoidDemo.ViewController: 0x7ff16a039a00>)
viewController = <TrochoidDemo.ViewController: 0x7ff16a039a00>
Run Code Online (Sandbox Code Playgroud)
(guardTest(_:)如果你想尝试一下,我将测试功能添加到我最新的开源项目中.它可以在Github上获得,网址为https://github.com/DuncanMC/TrochoidDemo)
我很高兴这个结构现在可以按照我的意愿运行,但是为什么它现在合法,以及何时发生变化感到困惑.
是否有人知道最近对语言定义的更改使得此构造工作在之前没有的地方?
我有一种情况,我使用POST方法在模拟器中的safari浏览器中托管一个URL.在模拟器中启动我的iOS应用程序后,在safari中打开该网页.为了启动safari,我使用了[[UIApplication sharedApplication] openURL:...
post方法如下:
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"https://***some client url***.jsp"]];
NSString *post = [NSString stringWithFormat:@"username=%@&password=%@", userName, password];
NSData *postData = [post dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
[request setHTTPMethod:@"POST"];
[request setValue:[NSString stringWithFormat:@"%d", [postData length]] forHTTPHeaderField:@"Content-Length"];
[request setHTTPBody:postData];`
NSURLConnection* _urlConnection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
[_urlConnection start];
Run Code Online (Sandbox Code Playgroud)
NSURLConnection*_urlConnection = [[NSURLConnection alloc] initWithRequest:request delegate:self]; [_urlConnection start];
使用UIWebView时,这段代码可以正常工作.但我想使用这个"请求"启动Safari,该请求附加了POST方法的用户名和密码数据.
要启动Safari,我必须调用以下代码:
[[UIApplication sharedApplication] openURL:request];
Run Code Online (Sandbox Code Playgroud)
But this throws a warning obviously because "request" is of type NSMutableURLRequest. "Semantic Issue: Incompatible pointer types sending 'NSMutableURLRequest*' to parameter of type …