小编Zme*_*mey的帖子

处理Swift扩展中的类初始化失败

我正在将下面的Objective C类重写为Swift:

@implementation UIImage (Extra)

+ (UIImage *)validImageNamed:(NSString *)name
{
    UIImage *image = [self imageNamed:name];
    NSAssert(image, @"Unable to find image named '%@'", name);
    return image;
}
Run Code Online (Sandbox Code Playgroud)

这要求作为一个方便的init实现,但是如何检查指定的初始化程序self.init(命名:)是否成功?

extension UIImage {
    convenience init(validateAndLoad name: String!) {
        self.init(named: name)

        // need to assert here if self.init fails
    }
Run Code Online (Sandbox Code Playgroud)

当self.init(named :)调用失败时,扩展的init停止执行.

我已经尝试创建一个UIImage实例并将其分配给自己,但这不会编译.

当然,可以像ObjC版本一样使用辅助方法:

extension UIImage {

    class func validImage(named name: String) -> UIImage {
        var image = UIImage(named: name)
        assert(image == nil, "Image doesn't exist")
        return image
    }
Run Code Online (Sandbox Code Playgroud)

但有没有办法使用初始化程序实现这一点?

ios swift swift-extensions

11
推荐指数
1
解决办法
4177
查看次数

使用Windows API写入和读取可用磁盘空间

是否可以使用Windows API写入磁盘上的可用群集或从中读取数据?我发现了Defrag API:https//docs.microsoft.com/en-gb/windows/desktop/FileIO/defragmenting-files

FSCTL_GET_VOLUME_BITMAP可用于获取每个群集的分配状态,FSCTL_MOVE_FILE可用于在群集之间移动。但是我找不到从自由集群读取数据或向其写入数据的方法。

更新:想到的解决方法之一是创建一个新的小文件,向其中写入一些数据,然后将其重新放置到所需位置并删除该文件(数据将保留在释放的群集中)。但这仍然不能解决阅读问题。

我想做的是某种透明的缓存,因此用户仍然可以照常使用他的NTFS分区,并且仍然将这些群集视为可用空间,但是我可以在其中存储一些数据。数据安全性无关紧要,它可以被用户操作覆盖,并且当群集再次释放时稍后将重新生成/重新下载。

windows filesystems winapi diskspace disk

7
推荐指数
1
解决办法
208
查看次数

将C字符串数组转换为Swift字符串数组

在Swift 3中,带有签名的C函数const char *f()映射到UnsafePointer<Int8>! f()导入时.它的结果可以转换为Swift字符串:

let swiftString = String(cString: f())
Run Code Online (Sandbox Code Playgroud)

问题是,如何将NULL终止的C字符串C字符串映射到Swift字符串数组?

原始C签名:

const char **f()
Run Code Online (Sandbox Code Playgroud)

导入的Swift签名:

UnsafeMutablePointer<UnsafePointer<Int8>?>! f()
Run Code Online (Sandbox Code Playgroud)

Swift数组字符串:

let stringArray: [String] = ???
Run Code Online (Sandbox Code Playgroud)

arrays pointers type-conversion swift swift3

6
推荐指数
1
解决办法
809
查看次数

在Swift中使用libevent和GCD(libdispatch)

我正在Swift 3中创建一个服务器端应用程序.我选择了libevent来实现网络代码,因为它是跨平台的并且不会遇到C10k问题.Libevent实现了它自己的事件循环,但我想保持CFRunLoop和GCD(DispatchQueue.main.after等)功能,所以我需要以某种方式粘贴它们.

这就是我想出的:

var terminated = false

DispatchQueue.main.after(when: DispatchTime.now() + 3) {
    print("Dispatch works!")
    terminated = true
}

while !terminated {
    switch event_base_loop(eventBase, EVLOOP_NONBLOCK) { // libevent
    case 1:
        break // No events were processed
    case 0:
        print("DEBUG: Libevent processed one or more events")
    default: // -1
        print("Unhandled error in network backend")
        exit(1)
    }
    RunLoop.current().run(mode: RunLoopMode.defaultRunLoopMode,
                          before: Date(timeIntervalSinceNow: 0.01))
}
Run Code Online (Sandbox Code Playgroud)

这有效,但引入了0.01秒的延迟.当RunLoop正在休眠时,libevent将无法处理事件.当应用程序空闲时,降低此超时会显着增加CPU使用率.

我也在考虑只使用libevent,但是项目中的第三方库可以在内部使用dispatch_async,因此这可能会有问题.

在另一个线程中运行libevent的循环会使同步变得更加复杂,这是解决此延迟问题的唯一方法吗?

LINUX更新.上面的代码在Linux上不起作用(2016-07-25-a Swift snapshot),RunLoop.current().run存在错误.下面是一个工作的Linux版本,重新实现了计时器和dispatch_main.它遇到了相同的延迟问题:

let queue = dispatch_get_main_queue()
let timer = …
Run Code Online (Sandbox Code Playgroud)

network-programming libevent grand-central-dispatch swift swift3

5
推荐指数
1
解决办法
547
查看次数

如何在Swift中创建非原子全局或静态变量

我经常需要缓存一个值,以便在类的多个实例中重用它,例如:

class Session {
    typealias T = Session

    let chatId: Int64
    let userId: Int64
    var name = ""
    var url = ""

    // ------- Define schema helpers --------
    // The problem: access to them is dispatch_once-d.
    static let table = Table("Session")
    static let chatIdColumn = Expression<Int64>("ChatId")
    static let userIdColumn = Expression<Int64>("UserId")
    static let nameColumn = Expression<String>("Name")
    static let urlColumn = Expression<String>("Url")

    init() {
        ...
        // ------ They're used in constructor: ------
        guard let chat = db.pluckItem(T.table, T.chatIdColumn, chatId)
            else { …
Run Code Online (Sandbox Code Playgroud)

static multithreading global-variables swift swift2

4
推荐指数
1
解决办法
962
查看次数

将位索引数组转换为 OptionSet

我正在尝试编写一个辅助函数,它将把位索引数组转换为符合 OptionSet 的类。

func getOptionSet<T: OptionSet>(bitIndexes: [Int64]) -> T {
    var result: Int64 = 0
    for index in bitIndexes {
        result |= 1 << index
    }
    return T(rawValue: result) // error
}
Run Code Online (Sandbox Code Playgroud)

这无法编译:

Cannot invoke initializer for type 'T' with an argument list of type '(rawValue: Int64)'
Run Code Online (Sandbox Code Playgroud)

我也尝试过使用 RawValue:

func getOptionSet<T: OptionSet>(bitIndexes: [T.RawValue]) {
    var result = T.RawValue()  // error
Run Code Online (Sandbox Code Playgroud)

这也不起作用:

Cannot invoke value of type 'T.RawValue.Type' with argument list '()'
Run Code Online (Sandbox Code Playgroud)

这可以做到吗?我需要对 T 添加额外的约束吗?

我知道可以重写这个函数以使用具体类型,但如果可能的话我想保持它的通用性。

generics bitvector bit-fields swift swift3

2
推荐指数
1
解决办法
1192
查看次数