有没有办法将 Swift 枚举类型的变量分配给 NSObject 类型的变量?

问题描述

在下面发布的我的程序代码中,我需要将一个 Swift 枚举类型的变量分配给一个 NSObject 类型的变量。但是,编译器不允许这样做。我知道这是不允许的。所以,我想知道是否有办法以某种方式更改枚举,以便将其分配给 NSObject 变量。谢谢!

照片+CoreDataClass.swift

import Foundation
import CoreData

@objc(Photo)
public class Photo: NSManagedObject {

}

照片+CoreDataProperties.swift

import Foundation
import CoreData


extension Photo {

    @nonobjc public class func fetchRequest() -> NSFetchRequest<Photo> {
        return NSFetchRequest<Photo>(entityName: "Photo")
    }

    @NSManaged public var datetaken: String?
    @NSManaged public var datetakengranularity: NSObject?
    @NSManaged public var datetakenunknow: String?
    @NSManaged public var farm: Int32
    @NSManaged public var heightZ: Int32
    @NSManaged public var photoID: String?
    @NSManaged public var isfamily: Int32
    @NSManaged public var isfriend: Int32
    @NSManaged public var ispublic: Int32
    @NSManaged public var owner: String?
    @NSManaged public var secret: String?
    @NSManaged public var server: String?
    @NSManaged public var title: String?
    @NSManaged public var urlZ: String?
    @NSManaged public var widthZ: Int32

}

extension Photo : Identifiable {

}

FlickrPhoto.swift

import Foundation

// MARK: - Photo
struct FlickrPhoto: Codable {
    let photoID,owner,secret,server: String
    let farm: Int
    let title: String
    let ispublic,isfriend,isfamily: Int
    let datetaken: String
    let datetakengranularity: Datetakengranularity
    let datetakenunknown: String
    let urlZ: String?
    let heightZ,widthZ: Int?

    enum CodingKeys: String,CodingKey {
        case owner,server,farm,title,ispublic,isfamily,datetaken,datetakengranularity,datetakenunknown
        case photoID = "id"
        case urlZ = "url_z"
        case heightZ = "height_z"
        case widthZ = "width_z"
    }
}
enum Datetakengranularity: Codable {
    case integer(Int)
    case string(String)

    init(from decoder: Decoder) throws {
        let container = try decoder.singleValueContainer()
        if let x = try? container.decode(Int.self) {
            self = .integer(x)
            return
        }
        if let x = try? container.decode(String.self) {
            self = .string(x)
            return
        }
        throw DecodingError.typeMismatch(Datetakengranularity.self,DecodingError.Context(codingPath: decoder.codingPath,debugDescription: "Wrong type for Datetakengranularity"))
    }

    func encode(to encoder: Encoder) throws {
        var container = encoder.singleValueContainer()
        switch self {
        case .integer(let x):
            try container.encode(x)
        case .string(let x):
            try container.encode(x)
        }
    }
}

extension FlickrPhoto: Equatable {
    static func == (lhs: FlickrPhoto,rhs: FlickrPhoto) -> Bool {
        // Two Photos are the same if they have the same photoID
        return lhs.photoID == rhs.photoID
    }
}

PhotoStore.swift

import UIKit
import CoreData

class PhotoStore {
    private let session: URLSession = {
        let config = URLSessionConfiguration.default
        return URLSession(configuration: config)
    }()
    let imageStore = ImageStore()
    let persistenContainer: NSPersistentContainer = {
        let container = NSPersistentContainer(name: "Photorama")
        container.loadPersistentStores { (description,error) in
            if let error = error {
                print("Error setting up Core Data (\(error))")
            }
        }
        return container
    }()
    private func processPhotosRequest (data: Data?,error: Error?) ->
    Result<[FlickrPhoto],Error> {
        guard let jsonData = data else {
            return .failure(error!)
        }
        //return FlickrAPI.photos(fromJSON: jsonData)
        let context = persistenContainer.viewContext
        
        switch FlickrAPI.photos(fromJSON: jsonData) {
        case let .success(flickrPhotos):
            let _ = flickrPhotos.map { flickrPhoto -> Photo in
                let fetchRequest: NSFetchRequest<Photo> = Photo.fetchRequest()
                let predicate = NSPredicate(format: "\(#keyPath(Photo.photoID)) == \(flickrPhoto.photoID)")
                fetchRequest.predicate = predicate
                var photo: Photo!
                context.performAndWait {
                        photo = Photo(context: context)
                        photo.photoID = flickrPhoto.photoID
                        photo.owner = flickrPhoto.owner
                        photo.secret = flickrPhoto.secret
                        photo.server = flickrPhoto.server
                        photo.farm = Int32(flickrPhoto.farm)
                        photo.title = flickrPhoto.title
                        photo.ispublic = Int32(flickrPhoto.ispublic)
                        photo.isfriend = Int32(flickrPhoto.isfriend)
                        photo.isfamily = Int32(flickrPhoto.isfamily)
                        photo.datetaken = flickrPhoto.datetaken
                        photo.datetakengranularity = flickrPhoto.datetakengranularity // The compiler reports error here: 
                             // Cannot assign value of type 'Datetakengranularity' to type 'NSObject?'
                        photo.datetakenunknow = flickrPhoto.datetakenunknown
                        photo.urlZ = flickrPhoto.urlZ
                        photo.heightZ = Int32(flickrPhoto.heightZ!)
                        photo.widthZ = Int32(flickrPhoto.widthZ!)
                }
                return photo
            }
            return .success(flickrPhotos)
        case let .failure(error):
            return .failure(error)
        }
    }
    func fetchAllPhotos (completion: @escaping (Result<[Photo],Error>) -> Void) -> Void {
        let fetchRequest: NSFetchRequest<Photo> = Photo.fetchRequest()
        let sortByDataTaken = NSSortDescriptor(key: #keyPath(Photo.datetaken),ascending: true)
        fetchRequest.sortDescriptors = [sortByDataTaken]
        let viewContext = persistenContainer.viewContext
        viewContext.perform {
            do {
                let allPhotos = try viewContext.fetch(fetchRequest)
                completion(.success(allPhotos))
            } catch {
                completion(.failure(error))
            }
        }
    }
    func fetchRecentPhotos (completion: @escaping (Result<[FlickrPhoto],Error>) -> Void) {
        let url = FlickrAPI.interestingPhotoURL
        let request = URLRequest(url: url)
        let task = session.dataTask(with: request) {
            (data,response,error) in
            
            var result = self.processPhotosRequest(data: data,error: error)
            if case .success = result {
                do {
                    try self.persistenContainer.viewContext.save()
                } catch {
                    result = .failure(error)
                }
            }
            OperationQueue.main.addOperation {
                completion(result)
            }
        }
        task.resume()
    }
    func fetchImage (for photo: Photo,completion: @escaping (Result<UIImage,Error>) -> Void) {
        
        let photoKey = photo.photoID
        if let image = imageStore.image(forKey: photoKey!) {
            OperationQueue.main.addOperation {
                completion(.success(image))
            }
            return
        }
        guard let photoURL = photo.urlZ else { return }
        guard let requestURL = URL(string: photoURL)  else {
            completion(.failure(PhotoError.missingImageURL))
            return
        }
        let request = URLRequest(url: requestURL)
        let task = session.dataTask(with: request) {
            (data,error) in
            let result = self.processImageRequest(data: data,error: error)
            if case let .success(image) = result {
                self.imageStore.setImage(image,forKey: photoKey!)
            }
            OperationQueue.main.addOperation {
                completion(result)
            }
        }
        task.resume()
    }
    private func processImageRequest (data: Data?,error: Error?) -> Result<UIImage,Error> {
        guard let imageData = data,let image = UIImage(data: imageData) else {
            // Couldn't create an image
            if data == nil {
                return .failure(error!)
            } else {
                return .failure(PhotoError.imageCreationError)
            }
        }
        return .success(image)
    }
}

enum PhotoError: Error {
    case imageCreationError
    case missingImageURL
}

Photorama.xcdatamodeld 界面的快照如下所示:

enter image description here

如有必要,将提供更多代码。非常感谢!

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)