ios iCloud 基础知识和代码示例

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7795629/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 21:54:17  来源:igfitidea点击:

iCloud basics and code sample

iphoneobjective-cioscocoa-touchicloud

提问by n.evermind

As a beginner, I'm struggling with iCloud. There are some samples, but they are usually quite detailed (on the developer forum there is one for iCloud and CoreData which is massive). The apple docsare OK, but I still can't see the big picture. So please bear with me, some of these questions are quite fundamental, but possibly easy to answer.

作为初学者,我正在为 iCloud 苦苦挣扎。有一些示例,但它们通常非常详细(在开发者论坛上,有一个针对 iCloud 和 CoreData 的示例,数量很大)。在苹果的文档都OK,但我仍然无法看到大局。所以请耐心等待,其中一些问题非常基本,但可能很容易回答。

Context:I have a very simple iCloud app running (full sample code below). There is only one UITextView shown to the user and his/her input is saved in a file called text.txt.

上下文:我有一个非常简单的 iCloud 应用程序正在运行(完整的示例代码如下)。只有一个 UITextView 显示给用户,他/她的输入保存在一个名为 text.txt 的文件中。

enter image description here

在此处输入图片说明

The txt file is pushed to the cloud and made available to all devices. Works perfectly, but:

txt 文件被推送到云端并可供所有设备使用。完美运行,但是:

Main problem: What about users who do not use iCloud?

主要问题:不使用iCloud的用户怎么办?

When I launch my app (see code below), I check if the user has iCloud enabled. If iCloud is enabled, everything is fine. The app goes ahead and looks for text.txt in the cloud. If found, it will load it and display it to the user. If text.txt is not found in the cloud, it will simply create a new text.txt and will display that to the user.

当我启动我的应用程序时(见下面的代码),我检查用户是否启用了 iCloud。如果启用了 iCloud,一切都很好。该应用程序继续在云中查找 text.txt。如果找到,它将加载它并将其显示给用户。如果在云中找不到 text.txt,它只会创建一个新的 text.txt 并将其显示给用户。

If the user does not have iCloud enabled, nothing will happen. How will I make it possible that non-iCloud users can still work with my text app? Or do I simply ignore them? Would I need to write separate functions for non-iCloud users? I.e. functions in which I simply load a text.txt from the documents folder?

如果用户没有启用 iCloud,则什么都不会发生。我将如何让非 iCloud 用户仍然可以使用我的文本应用程序?或者我只是忽略它们?我需要为非 iCloud 用户编写单独的函数吗?即我只是从文档文件夹中加载一个 text.txt 的函数?

Apple writes:

苹果写道

Treat files in iCloud the same way you treat all other files in your app sandbox.

像对待应用程序沙箱中的所有其他文件一样对待 iCloud 中的文件。

However, in my case there is no 'normal' app sandbox anymore. It's in the cloud. Or do I always load my text.txt from disk first and then check with iCloud if there is something more up-to-date?

但是,就我而言,不再有“正常”的应用程序沙箱。它在云端。还是我总是先从磁盘加载我的 text.txt,然后再通过 iCloud 检查是否有更新的内容?

Related problem: File structure - Sandbox vs. Cloud

相关问题:文件结构——沙盒 vs. 云

Perhaps my main problem is a fundamental misunderstanding of how iCloud is supposed to work. When I create a new instance of an UIDocument, I'll have to overwrite two methods. First - (BOOL)loadFromContents:(id)contents ofType:(NSString *)typeName error:(NSError **)outErrorto get files from the cloud and then -(id)contentsForType:(NSString *)typeName error:(NSError **)outErrorto get files into the cloud.

也许我的主要问题是对 iCloud 应该如何工作的根本误解。当我创建一个 UIDocument 的新实例时,我将不得不覆盖两个方法。首先- (BOOL)loadFromContents:(id)contents ofType:(NSString *)typeName error:(NSError **)outError从云端获取文件,然后-(id)contentsForType:(NSString *)typeName error:(NSError **)outError将文件放入云端。

Do I have to incorporate separate functions which will also save a local copy of text.txt into my sandbox? Will this work for non-iCloud users? As I understand iCloud, it will save a local copy of text.txt automatically. So there shouldn't be any need for me save anything into the 'old' sandbox of my app (i.e. as it used to be in the old, pre-iCloud days). Right now, my sandbox is totally empty, but I don't know if this is correct. Should I keep another copy of text.txt in there? This feels like cluttering my data structure... as there is one text.txt in the cloud, one in the iCloud sandbox on my device (which will work even if I am offline), and a third one in the good old sandbox of my app...

我是否必须合并单独的函数来将 text.txt 的本地副本保存到我的沙箱中?这对非 iCloud 用户有用吗?据我了解 iCloud,它会自动保存 text.txt 的本地副本。因此,我不需要将任何内容保存到我的应用程序的“旧”沙箱中(即它曾经是在旧的、前 iCloud 时代)。现在,我的沙箱完全是空的,但我不知道这是否正确。我应该在那里保留另一个 text.txt 副本吗?这感觉就像我的数据结构混乱......因为云中有一个 text.txt,一个在我设备上的 iCloud 沙箱中(即使我离线也能工作),第三个在旧的沙箱中我的应用...



MY CODE: A simple iCloud sample code

我的代码:一个简单的 iCloud 示例代码

This is loosely based on an example I found in the developer forum and on the WWDC session video. I stripped it down to the bare minimum. I'm not sure that my MVC structure is any good. The model is in the AppDelegate which isn't ideal. Any suggestions to make it better are welcome.

这大致基于我在开发者论坛和 WWDC 会议视频中找到的示例。我把它精简到最低限度。我不确定我的 MVC 结构有什么好处。该模型位于 AppDelegate 中,这并不理想。欢迎任何改进它的建议。



EDIT: I tried to extract the main question and posted it [here].4

编辑:我试图提取主要问题并将其发布 [here]。4



OVERVIEW:

概述:

Overview

概述

The most important bit which loads the text.txt from the cloud:

从云端加载 text.txt 的最重要的一点:

//  AppDelegate.h
//  iCloudText

#import <UIKit/UIKit.h>

@class ViewController;
@class MyTextDocument;

@interface AppDelegate : UIResponder <UIApplicationDelegate> {
    NSMetadataQuery *_query;
}

@property (strong, nonatomic) UIWindow *window;
@property (strong, nonatomic) ViewController *viewController;
@property (strong, nonatomic) MyTextDocument *document;

@end

//  AppDelegate.m
//  iCloudText

#import "AppDelegate.h"
#import "MyTextDocument.h"
#import "ViewController.h"

@implementation AppDelegate

@synthesize window = _window;
@synthesize viewController = _viewController;
@synthesize document = _document;

- (void)dealloc
{
    [_window release];
    [_viewController release];
    [super dealloc];
}

- (void)loadData:(NSMetadataQuery *)query {

    // (4) iCloud: the heart of the load mechanism: if texts was found, open it and put it into _document; if not create it an then put it into _document

    if ([query resultCount] == 1) {
        // found the file in iCloud
        NSMetadataItem *item = [query resultAtIndex:0];
        NSURL *url = [item valueForAttribute:NSMetadataItemURLKey];

        MyTextDocument *doc = [[MyTextDocument alloc] initWithFileURL:url];
        //_document = doc;
        doc.delegate = self.viewController;
        self.viewController.document = doc;

        [doc openWithCompletionHandler:^(BOOL success) {
            if (success) {
                NSLog(@"AppDelegate: existing document opened from iCloud");
            } else {
                NSLog(@"AppDelegate: existing document failed to open from iCloud");
            }
        }];
    } else {
        // Nothing in iCloud: create a container for file and give it URL
        NSLog(@"AppDelegate: ocument not found in iCloud.");

        NSURL *ubiq = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil];
        NSURL *ubiquitousPackage = [[ubiq URLByAppendingPathComponent:@"Documents"] URLByAppendingPathComponent:@"text.txt"];

        MyTextDocument *doc = [[MyTextDocument alloc] initWithFileURL:ubiquitousPackage];
        //_document = doc;
        doc.delegate = self.viewController;
        self.viewController.document = doc;

        [doc saveToURL:[doc fileURL] forSaveOperation:UIDocumentSaveForCreating completionHandler:^(BOOL success) {
            NSLog(@"AppDelegate: new document save to iCloud");
            [doc openWithCompletionHandler:^(BOOL success) {
                NSLog(@"AppDelegate: new document opened from iCloud");
            }];
        }];
    }
}

- (void)queryDidFinishGathering:(NSNotification *)notification {

    // (3) if Query is finished, this will send the result (i.e. either it found our text.dat or it didn't) to the next function

    NSMetadataQuery *query = [notification object];
    [query disableUpdates];
    [query stopQuery];

    [self loadData:query];

    [[NSNotificationCenter defaultCenter] removeObserver:self name:NSMetadataQueryDidFinishGatheringNotification object:query];
    _query = nil; // we're done with it
}

-(void)loadDocument {

    // (2) iCloud query: Looks if there exists a file called text.txt in the cloud

    NSMetadataQuery *query = [[NSMetadataQuery alloc] init];
    _query = query;
    //SCOPE
    [query setSearchScopes:[NSArray arrayWithObject:NSMetadataQueryUbiquitousDocumentsScope]];
    //PREDICATE
    NSPredicate *pred = [NSPredicate predicateWithFormat: @"%K == %@", NSMetadataItemFSNameKey, @"text.txt"];
    [query setPredicate:pred];
    //FINISHED?
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(queryDidFinishGathering:) name:NSMetadataQueryDidFinishGatheringNotification object:query];
    [query startQuery];

}

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    NSLog(@"AppDelegate: app did finish launching");
    self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];

    // Override point for customization after application launch.
    if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
        self.viewController = [[[ViewController alloc] initWithNibName:@"ViewController_iPhone" bundle:nil] autorelease];
    } else {
        self.viewController = [[[ViewController alloc] initWithNibName:@"ViewController_iPad" bundle:nil] autorelease];
    }

    self.window.rootViewController = self.viewController;
    [self.window makeKeyAndVisible];

    // (1) iCloud: init

    NSURL *ubiq = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil];
    if (ubiq) {
        NSLog(@"AppDelegate: iCloud access!");
        [self loadDocument];
    } else {
        NSLog(@"AppDelegate: No iCloud access (either you are using simulator or, if you are on your phone, you should check settings");
    }


    return YES;
}

@end


The UIDocument

用户界面文档

//  MyTextDocument.h
//  iCloudText

#import <Foundation/Foundation.h>
#import "ViewController.h"

@interface MyTextDocument : UIDocument {

    NSString *documentText;
    id delegate;

}

@property (nonatomic, retain) NSString *documentText;
@property (nonatomic, assign) id delegate;

@end

//  MyTextDocument.m
//  iCloudText

#import "MyTextDocument.h"
#import "ViewController.h"

@implementation MyTextDocument

@synthesize documentText = _text;
@synthesize delegate = _delegate;

// ** READING **

- (BOOL)loadFromContents:(id)contents ofType:(NSString *)typeName error:(NSError **)outError
{
    NSLog(@"UIDocument: loadFromContents: state = %d, typeName=%@", self.documentState, typeName);

    if ([contents length] > 0) {
        self.documentText = [[NSString alloc] initWithBytes:[contents bytes] length:[contents length] encoding:NSUTF8StringEncoding];
    }
    else {
        self.documentText = @"";
    }

    NSLog(@"UIDocument: Loaded the following text from the cloud: %@", self.documentText);


    // update textView in delegate...
    if ([_delegate respondsToSelector:@selector(noteDocumentContentsUpdated:)]) {
        [_delegate noteDocumentContentsUpdated:self];
    }

    return YES;

}

// ** WRITING **

-(id)contentsForType:(NSString *)typeName error:(NSError **)outError
{
    if ([self.documentText length] == 0) {
        self.documentText = @"New Note";
    }

    NSLog(@"UIDocument: Will save the following text in the cloud: %@", self.documentText);

    return [NSData dataWithBytes:[self.documentText UTF8String] length:[self.documentText length]];
}
@end


THE VIEWCONTROLLER

视图控制器

//
//  ViewController.h
//  iCloudText

#import <UIKit/UIKit.h>

@class MyTextDocument;

@interface ViewController : UIViewController <UITextViewDelegate> {

    IBOutlet UITextView *textView;

}

@property (nonatomic, retain) UITextView *textView;
@property (strong, nonatomic) MyTextDocument *document;

-(void)noteDocumentContentsUpdated:(MyTextDocument *)noteDocument;

@end

//  ViewController.m
//  iCloudText

#import "ViewController.h"
#import "MyTextDocument.h"

@implementation ViewController

@synthesize textView = _textView;
@synthesize document = _document;

-(IBAction)dismissKeyboard:(id)sender {

    [_textView resignFirstResponder];

}

-(void)noteDocumentContentsUpdated:(MyTextDocument *)noteDocument
{
    NSLog(@"VC: noteDocumentsUpdated");
    _textView.text = noteDocument.documentText;
}

-(void)textViewDidChange:(UITextView *)theTextView {

     NSLog(@"VC: textViewDidChange");
    _document.documentText = theTextView.text;
    [_document updateChangeCount:UIDocumentChangeDone];

}

采纳答案by n.evermind

I just re-read the docs and it appears that my general approach is wrong. I should first create the file in the sandbox and then move it to the cloud. In other words, Apple seems to suggest that I should have three versions of the same file at all times: one in the directory of my app, one in the iCloud demon directory of my device (which is also accessible if offline) and one in the cloud:

我只是重新阅读了文档,看来我的一般方法是错误的。我应该首先在沙箱中创建文件,然后将其移动到云中。换句话说,Apple 似乎建议我应该始终拥有同一个文件的三个版本:一个在我的应用程序目录中,一个在我设备的 iCloud 恶魔目录中(如果离线也可以访问),一个在云端:

Apps use the same technologies to manage files and directories in iCloud that they do for local files and directories. Files and directories in iCloud are still just files and directories. You can open them, create them, move them, copy them, read and write from them, delete them, or any of the other operations you might want to do. The only differences between local files and directories and iCloud files and directories is the URL you use to access them. Instead of URLs being relative to your app's sandbox, URLs for iCloud files and directories are relative to the corresponding iCloud container directory.

To move a file or directory to iCloud:

Create the file or directory locally in your app sandbox.While in use, the file or directory must be managed by a file presenter, such as a UIDocument object.

Use the URLForUbiquityContainerIdentifier: method to retrieve a URL for the iCloud container directory in which you want to store the item. Use the container directory URL to build a new URL that specifies the item's location in iCloud. Call the setUbiquitous:itemAtURL:destinationURL:error: method of NSFileManager to move the item to iCloud. Never call this method from your app's main thread; doing so could block your main thread for an extended period of time or cause a deadlock with one of your app's own file presenters. When you move a file or directory to iCloud, the system copies that item out of your app sandbox and into a private local directory so that it can be monitored by the iCloud daemon. Even though the file is no longer in your sandbox, your app still has full access to it. Although a copy of the file remains local to the current device, the file is also sent to iCloud so that it can be distributed to other devices. The iCloud daemon handles all of the work of making sure that the local copies are the same. So from the perspective of your app, the file just is in iCloud.

All changes you make to a file or directory in iCloud must be made using a file coordinator object. These changes include moving, deleting, copying, or renaming the item. The file coordinator ensures that the iCloud daemon does not change the file or directory at the same time and ensures that other interested parties are notified of the changes you make.

应用程序使用与管理本地文件和目录相同的技术来管理 iCloud 中的文件和目录。iCloud 中的文件和目录仍然只是文件和目录。您可以打开它们、创建它们、移动它们、复制它们、从它们读取和写入、删除它们或您可能想要执行的任何其他操作。本地文件和目录与 iCloud 文件和目录之间的唯一区别是您用来访问它们的 URL。iCloud 文件和目录的 URL 相对于相应的 iCloud 容器目录,而不是相对于应用程序沙箱的 URL。

将文件或目录移动到 iCloud:

在您的应用沙箱中本地创建文件或目录。在使用时,文件或目录必须由文件展示器管理,例如 UIDocument 对象。

使用 URLForUbiquityContainerIdentifier: 方法检索要存储项目的 iCloud 容器目录的 URL。使用容器目录 URL 构建一个新 URL,指定项目在 iCloud 中的位置。调用 NSFileManager 的 setUbiquitous:itemAtURL:destinationURL:error: 方法将项目移动到 iCloud。切勿从应用程序的主线程调用此方法;这样做可能会在很长一段时间内阻塞您的主线程或导致与您的应用程序自己的文件展示器之一发生死锁。当您将文件或目录移动到 iCloud 时,系统会将该项目从您的应用沙箱中复制到一个私有的本地目录中,以便 iCloud 守护程序可以对其进行监控。即使文件不再在您的沙箱中,您的应用程序仍然可以完全访问它。尽管该文件的副本保留在当前设备的本地,但该文件也会发送到 iCloud,以便可以将其分发到其他设备。iCloud 守护进程处理确保本地副本相同的所有工作。因此,从您的应用程序的角度来看,该文件只是在 iCloud 中。

您对 iCloud 中的文件或目录所做的所有更改都必须使用文件协调器对象进行。这些更改包括移动、删除、复制或重命名项目。文件协调器确保 iCloud 守护程序不会同时更改文件或目录,并确保将您所做的更改通知其他相关方。

However, if you dig a little deeper into the docs concerning setUbiquitous, you'll find:

但是,如果您深入了解有关 setUbiquitous 的文档,您会发现:

Use this method to move a file from its current location to iCloud. For files located in an application's sandbox, this involves physically removing the file from the sandbox directory. (The system extends your application's sandbox privileges to give it access to files it moves to iCloud.) You can also use this method to move files out of iCloud and back into a local directory.

使用此方法将文件从其当前位置移动到 iCloud。对于位于应用程序沙箱中的文件这涉及从沙箱目录中物理删除文件。(系统扩展了您的应用程序的沙箱权限,使其能够访问它移动到 iCloud 的文件。)您还可以使用此方法将文件移出 iCloud 并移回本地目录。

So this appears to mean that a file / directory gets deleted form the local sandbox and moved into the cloud.

所以这似乎意味着文件/目录从本地沙箱中删除并移动到云中。

回答by earnshavian

I've been using your example and I like it for helping me grasp the basics of iCloud. Now I'm wrangling with your question for my own app which has to support existing users of the app with locally stored content who may or may not be using iCloud creating these cases as far as I can tell:

我一直在使用你的例子,我喜欢它帮助我掌握 iCloud 的基础知识。现在我正在为我自己的应用程序争论你的问题,该应用程序必须支持应用程序的现有用户本地存储的内容,据我所知,这些用户可能会或可能不会使用 iCloud 创建这些案例:

Cases:

案例:

  1. New user
    • has icloud - create documents in icloud
    • no icloud - create documents locally
  2. Existing user
    • has icloud
      • just added - migrate local docs to icloud
      • not just added - open/save docs to icloud
    • no icloud
      • just removed - migrate former icloud docs to local
      • not just removed - open/save docs to local
  1. 新用户
    • has icloud - 在 icloud 中创建文档
    • 没有 icloud - 在本地创建文档
  2. 现有用户
    • 有 icloud
      • 刚刚添加 - 将本地文档迁移到 icloud
      • 不只是添加 - 打开/保存文档到 icloud
    • 没有icloud
      • 刚刚删除 - 将以前的 icloud 文档迁移到本地
      • 不只是删除 - 打开/保存文档到本地

If someone removes iCloud - wouldn't the calls to ubiquitous URL return nil? If that's the case how do I migrate the docs back to local storage? I'll create a user pref for now but seems a bit of a workaround.

如果有人删除了 iCloud - 对无处不在的 URL 的调用不会返回 nil 吗?如果是这种情况,我该如何将文档迁移回本地存储?我现在将创建一个用户偏好,但似乎有点解决方法。

I feel like I'm missing something obvious here so if anyone can see it, please chime in.

我觉得我在这里遗漏了一些明显的东西,所以如果有人能看到它,请插话。

回答by Jonathan Watmough

If you want users to be able to share text between devices that are pre-iOS 5.0, you are going to have to do what everyone had to do before iCloud and move information to your own server.

如果您希望用户能够在 iOS 5.0 之前的设备之间共享文本,您将不得不执行 iCloud 之前每个人都必须做的事情,并将信息移动到您自己的服务器。

All you really need is a server somewhere that lets your app save its text files and associate them with a user account.

您真正需要的只是一个服务器,它可以让您的应用程序保存其文本文件并将它们与用户帐户相关联。

You'll need users to create an account and you'll need to manage the process yourself, of moving new information on one device into your own 'cloud'.

您需要用户创建一个帐户,并且您需要自己管理将一台设备上的新信息移动到您自己的“云”中的过程。

Users will register with the same account on other devices and you'll need to take care of detecting when another device has moved data onto your own cloud, and update the current device with the new info.

用户将在其他设备上使用同一帐户注册,您需要注意检测其他设备何时将数据移动到您自己的云上,并使用新信息更新当前设备。

Obviously, for iOS 5.0 devices, you'll probably want to detect changed files for pre-iOS 5.0 devices in your own cloud, and also be able to talk to iCloud.

显然,对于 iOS 5.0 设备,您可能希望在自己的云中检测 iOS 5.0 之前设备的更改文件,并且还能够与 iCloud 对话。

回答by Michael

It doesn't seem that you are struggling with a iCloud/notICloud issue as much as a iOS5/notIOS5 issue.

您似乎并没有像 iOS5/notIOS5 问题那样为 iCloud/notiCloud 问题苦苦挣扎。

If your deployment target is iOS5, then simply always use the UIDocument structure. If it is ubiquitous, then your NSMetaDataQuery will find it in the cloud; if not it will find it on the device.

如果您的部署目标是 iOS5,那么只需始终使用 UIDocument 结构。如果它无处不在,那么你的 NSMetaDataQuery 会在云端找到它;如果没有,它会在设备上找到它。

If, on the other hand, you want to provide pre 5.0 access to your app, then you will need to conditionally check to see if if the running iOS is 5.0 or greater. If it is then use UIDocument; if not then read/write data the old way.

另一方面,如果您想为您的应用程序提供 5.0 之前的访问权限,那么您需要有条件地检查正在运行的 iOS 是否为 5.0 或更高版本。如果是,则使用 UIDocument; 如果不是,则以旧方式读/写数据。

My approach was to write a conditional saveData method that checks for iOS5. If it exists I update the change count (or use an undo manager). In your case the textViewDidChange would call this method. If not, then it saves to disk the old way. On loading, the opposite happens.

我的方法是编写一个检查 iOS5 的条件 saveData 方法。如果存在,我更新更改计数(或使用撤消管理器)。在您的情况下, textViewDidChange 将调用此方法。如果没有,则以旧方式保存到磁盘。在加载时,情况正好相反。

回答by Jesper

You are befuddled by "Treat files in iCloud the same way you treat all other files in your app sandbox." This holds true for something like Keynote and Numbers where you keep a bunch of files, and if you have iCloud, they start syncing magically.

您对“像对待应用沙箱中的所有其他文件一样对待 iCloud 中的文件”感到困惑。这适用于 Keynote 和 Numbers 之类的东西,你可以保存一堆文件,如果你有 iCloud,它们就会开始神奇地同步。

However, you're building something that depends on iCloud-like functionality. You can't hold onto that statement because your app depends on iCloud to be present for anything to work the way it's meant to. You will either have to close your app down and simply say "please setup iCloud for this to work" or duplicate iCloud-like functionality (your own or someone else's) that you can always use, regardless.

但是,您正在构建的东西依赖于类似 iCloud 的功能。你不能坚持这个说法,因为你的应用程序依赖于 iCloud 的存在,任何东西都可以按预期的方式工作。您要么必须关闭您的应用程序,然后简单地说“请设置 iCloud 以使其正常工作”,要么复制您始终可以使用的类似 iCloud 的功能(您自己的或其他人的),无论如何。