我是 ios 开发的新手。
我已经构建了将数据保存在核心数据中的应用程序。我想做的是与我的 Ipad 或我的孩子 Iphone 共享这些数据。
设备不在同一网络上或彼此关闭,因此共享过程将通过电子邮件或 Imessage。
该应用程序将安装在所有设备上,以便发送/接收数据。
我想确定唯一的方法是使用 UIActivityViewController。
我还没有开始编码部分(分享部分),我还在做一些研究和一些好的建议。
谢谢你的帮忙
// 完整代码
经过大量搜索后,这里是我的代码,我不知道是否有更好的方法来做到这一点,但这是我解决的方法:
1 - 创建一个 Json 字符串
let savedData = ["Something": 1]
let jsonObject: [String: Any] = [
"type_id": 1,
"model_id": true,
"Ok": [
"startDate": "10-04-2015 12:45",
"endDate": "10-04-2015 16:00"
],
"custom": savedData
]
2 - 保存为文件
let objectsToShare = [jsonObject as AnyObject]
let data: Data? = try? JSONSerialization.data(withJSONObject: objectsToShare, options: .prettyPrinted)
let filePath = NSTemporaryDirectory() + "/" + NSUUID().uuidString + ".kis"
do
{
try data?.write(to: URL(fileURLWithPath: filePath))
}
catch {
}
print (filePath)
// create activity view controller
let activityItem:NSURL = NSURL(fileURLWithPath:filePath)
let activityViewController = UIActivityViewController(activityItems: [activityItem], applicationActivities: nil)
self.present(activityViewController, animated: true, completion: nil)
3 - 更新 info.plist
<key>CFBundleDocumentTypes</key>
<array>
<dict>
<key>LSItemContentTypes</key>
<array>
<string>XXXSharingData.kis</string>
</array>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>CFBundleTypeName</key>
<string>kis file</string>
<key>LSHandlerRank</key>
<string>Owner</string>
</dict>
</array>
<key>UTExportedTypeDeclarations</key>
<array>
<dict>
<key>UTTypeConformsTo</key>
<array>
<string>public.data</string>
</array>
<key>UTTypeIdentifier</key>
<string>XXXSharingData.kis</string>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.mime-type</key>
<string>application/pry</string>
<key>public.filename-extension</key>
<string>kis</string>
</dict>
</dict>
</array>
最后,当通过电子邮件将文件作为附件发送/接收并在我的应用程序中打开时:打开方法 appdelegate,我能够看到 Json 字符串
func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {
do
{
let dictionary = try NSString(contentsOf: url, encoding: String.Encoding.utf8.rawValue)
print (dictionary)
}
catch {
}
return true
}
总的来说,总体上有 2 个原则。您要么不想发送数据差异,要么不想发送整个数据本身。
首先,我只会按需发送整个数据包,因为差异意味着目标设备需要首先报告它所处的状态。
因此,要传输整个核心数据,我想应该可以简单地压缩存储数据库的整个文件夹,将 zip 扩展名更改为某个自定义名称,然后简单地发送此文件。然后把另一边的这个文件解压到对应的位置。
但这并不是很好,因为它不能移植到任何其他系统(Android、远程存储...)并且会有版本控制问题:如果更新数据模型,那么在导入旧数据库时,新应用程序将崩溃。
所以我会说发送任何标准数据块都是最好的:只需将所有核心数据实体转换为字典,然后将这些数据序列化为 JSON。因此像这样:
var JSONDictionary: [String: Any] = [String: Any]()
JSONDictionary["users"] = User.fetchAll().map { $0.toDictionary() }
JSONDictionary["tags"] = Tag.fetchAll().map { $0.toDictionary() }
JSONDictionary["notifications"] = Notification.fetchAll().map { $0.toDictionary() }
let data: Data? = try? JSONSerialization.data(withJSONObject: JSONDictionary, options: .prettyPrinted)
let filePath = NSTemporaryDirectory() + "/" + NSUUID().uuidString + ".myApplicationFileExtension"
Data().write(to: URL(fileURLWithPath: filePath))
因此,此时您的文件很容易共享,并且可以在另一侧反转。然后您可以选择合并数据,覆盖它...
编辑:从评论和更新的问题中添加更多描述
我不确定你的数据结构是什么,但似乎我期望的是:
class MyObject {
enum ObjectType {
case a,b,c
var id: String {
switch self {
case .a: return "1"
case .b: return "2"
case .c: return "3"
}
}
static let supportedValues: [ObjectType] = [.a, .b, .c]
}
var savedData: [String: Any]?
var type: ObjectType = .a
var isModel: Bool = false
var startDate: Date?
var endDate: Date?
func toDictionary() -> [String: Any] {
var dictionary: [String: Any] = [String: Any]()
dictionary["custom"] = savedData
dictionary["type_id"] = type.id
dictionary["model_id"] = isModel
dictionary["startDate"] = startDate?.timeIntervalSince1970
dictionary["endDate"] = endDate?.timeIntervalSince1970
return dictionary
}
func loadWithDescriptor(_ descriptor: Any?) {
if let dictionary = descriptor as? [String: Any] {
savedData = dictionary["custom"] as? [String: Any]
type = ObjectType.supportedValues.first(where: { $0.id == dictionary["type_id"] as? String }) ?? .a
isModel = dictionary["model_id"] as? Bool ?? false
startDate = {
guard let interval = dictionary["startDate"] as? TimeInterval else {
return nil
}
return Date(timeIntervalSince1970: interval)
}()
endDate = {
guard let interval = dictionary["endDate"] as? TimeInterval else {
return nil
}
return Date(timeIntervalSince1970: interval)
}()
}
}
}
因此,现在这将使您能够在字典(不是 JSON)之间进行转换。
活动控制器不是问题,保存到文件似乎也不是什么大问题。我不确定一些属性,但它应该看起来像这样:
func saveToTemporaryFile(myConcreteObjects: [MyObject]) -> String {
let dictionaryObjects: [[String: Any]] = myConcreteObjects.map { $0.toDictionary() }
let path = NSTemporaryDirectory() + "/" + NSUUID().uuidString + ".kis"
let data: Data? = try? JSONSerialization.data(withJSONObject: dictionaryObjects, options: .prettyPrinted)
try? data?.write(to: URL(fileURLWithPath: path))
return path
}
如果碰巧你有不同的对象,那么这个方法应该接受Any
应该构造为的对象:
var myDataObject: [String: Any] = [String: Any]()
myDataObject["myObjects"] = myConcreteObjects.map { $0.toDictionary() }
...
要从 URL 加载您的 JSON,您只需要构建您的数据。既然你得到了 URL,就不要理会字符串:
func loadItemsFrom(url: URL) -> [MyObject]? {
guard let data = try? Data(contentsOf: url) else {
// Error, could not load data
return nil
}
guard let array = (try? JSONSerialization.jsonObject(with: data, options: .allowFragments)) as? [Any] else {
// Error, could not convert to JSON or invalid type
return nil
}
return array.map { descriptor in
let newItem = MyObject()
newItem.loadWithDescriptor(descriptor)
return newItem
}
}
这个从 URL 获取数据的构造函数非常强大。如果您可以访问互联网/网络,它甚至可以与远程服务器一起使用。因此,在这些情况下,请确保您在单独的线程上执行此操作,否则您的 UI 可能会被阻止,直到收到数据。
我希望这可以清除一些事情......
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句