在 Swift 中哪里可以找到 setValue 函数的定义键

Where to find defined keys for setValue func in Swift

在尝试通过 UIActivityViewController 设置电子邮件主题和内容时,我在 Swift 中使用了 .setValue 函数。设置主题的key很好找,但是我找不到设置内容的key

activityViewController.setValue("Subject", forKey: "Subject")

//Key "Content" is not defined
activityViewController.setValue("Content", forKey: "Content"

在这种情况下,我用所有可能的键搜索了 "list",但我找不到任何东西(即使在来自 Apple API 的文档 https://developer.apple.com/documentation/objectivec/nsobject/1415969-setvalue 中)。所以我想问一下一般在哪里可以找到这样的列表,独立于这种特殊情况。

您正在访问 UIActivityViewController 的私人内部详细信息。不知道 ivar 的用途是什么,在什么条件下设置它是安全的。 setValue(_:forKey:) 是一种动态方法,可让您访问任意内部结构,但这并不意味着您应该这样做。

出于探索目的,您可以使用 class-dump or Hopper 等工具对 class 进行逆向工程,或者您可以在运行时像这样查询它:

let cls = UIActivityViewController.self

var count: UInt32 = 0
let ivars = class_copyIvarList(cls, &count)!
for i in 0..<count {
    let ivar = ivars[Int(i)]
    let name = ivar_getName(ivar)!
    print(String(cString: name))
}

print("---")

let properties = class_copyPropertyList(cls, &count)!
for i in 0..<count {
    let property = properties[Int(i)]
    let name = property_getName(property)
    print(String(cString: name))
}

这将打印所有 ivar 和属性的列表,这是 setValue(_:forKey:) 在当前 class 上默认可以访问的大部分内容。它不会包含来自 superclass 或非 属性 访问器的属性。为此,您必须更深入。 (但同样,这不是 setValue(_:forKey:) 的使用方式。您可以通过阅读 class 的文档来使用它,而不仅仅是四处寻找。

使用 class-dump,您会看到 UIActivityViewController 的以下内容:

class-dump -C '^UIActivityViewController$' /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot/System/Library/PrivateFrameworks/UIKitCore.framework/UIKitCore

///// ... HEADER OMITTED ....

//
// File: /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot/System/Library/PrivateFrameworks/UIKitCore.framework/UIKitCore
// UUID: 2DB941E0-513E-3750-9278-C8AFB85CB3C0
//
//                           Arch: x86_64
//                Current version: 61000.0.0
//          Compatibility version: 1.0.0
//                 Source version: 3698.29.8.0.0
//
// Objective-C Garbage Collection: Unsupported
//

@interface UIActivityViewController : UIViewController <UIAlertControllerContaining, UIAlertControllerVisualStyleProviding, UIViewControllerRestoration, UIActionSheetPresentationControllerDelegate, _UIActivityHelperDelegate, _UIShareExtensionHost>
{
    _Bool _waitingForInitialShareServicePreferredContentSize;
    _Bool _shareServicePreferredContentSizeIsValid;
    _Bool __viewServiceBeganConnecting;
    _Bool _dismissalDetectionOfViewControllerForSelectedActivityShouldAutoCancel;
    _Bool _willDismissActivityViewController;
    _Bool _performActivityForStateRestoration;
    _Bool _shouldMatchOnlyUserElectedExtensions;
    _Bool _hasPerformedInitialPresentation;
    _Bool _isPerformingPresentation;
    _Bool _allowsEmbedding;
    _Bool _showKeyboardAutomatically;
    _Bool _sourceIsManaged;
    CDUnknownBlockType _completionHandler;
    CDUnknownBlockType _completionWithItemsHandler;
    NSArray *_excludedActivityTypes;
    _UIShareExtensionRemoteViewController *_remoteContentViewController;
    NSExtension *_shareExtension;
    id <NSCopying> _extensionRequestIdentifier;
    id <_UIShareExtensionService> _shareExtensionService;
    UISUIActivityViewControllerConfiguration *_activityViewControllerConfiguration;
    _UIActivityGroupListViewController *_placeholderViewController;
    NSArray *_activityItems;
    NSArray *_applicationActivities;
    NSMutableDictionary *_activitiesByUUID;
    _UIActivityHelper *_activityHelper;
    long long _originalPopoverBackgroundStyle;
    Class _originalPopoverBackgroundViewClass;
    CDUnknownBlockType __popoverDismissalAction;
    CDUnknownBlockType _activityPresentationCompletionHandler;
    UIAlertController *_activityAlertController;
    _UIAlertControllerShimPresenter *_activityAlertControllerShimPresenter;
    UIAlertAction *_activityAlertCancelAction;
    NSArray *_activityItemProviderOperations;
    NSOperationQueue *_activityItemProviderOperationQueue;
    long long _totalProviderCount;
    long long _completedProviderCount;
    unsigned long long _backgroundTaskIdentifier;
    NSString *_subject;
    unsigned long long _clientAttemptedInitialPresentationOrEmbeddingTimestamp;
    unsigned long long _beginPerformingActivityTimestamp;
    unsigned long long _viewWillAppearTimestamp;
    unsigned long long _readyToInteractTimestamp;
    NSArray *_activityTypesToCreateInShareService;
    NSArray *_resolvedActivityItemsForCurrentActivity;
    CDUnknownBlockType _shareSheetReadyToInteractHandler;
    CDUnknownBlockType _preCompletionHandler;
    NSArray *_includedActivityTypes;
    long long _excludedActivityCategories;
    NSArray *_activityTypeOrder;
    UIActivity *_activity;
    UIViewController *_activityViewController;
    id <UIActivityViewControllerDelegate> _airDropDelegate;
}

+ (id)viewControllerWithRestorationIdentifierPath:(id)arg1 coder:(id)arg2;
+ (double)_asyncPresentationTimeout;
+ (_Bool)_popoverPresentationUsesModernPresentation;
+ (_Bool)_usesActionSheetPresentationController;
@property(nonatomic) __weak id <UIActivityViewControllerDelegate> airDropDelegate; // @synthesize airDropDelegate=_airDropDelegate;
@property(retain, nonatomic) UIViewController *activityViewController; // @synthesize activityViewController=_activityViewController;
@property(retain, nonatomic) UIActivity *activity; // @synthesize activity=_activity;
@property(nonatomic) _Bool sourceIsManaged; // @synthesize sourceIsManaged=_sourceIsManaged;
@property(nonatomic) _Bool showKeyboardAutomatically; // @synthesize showKeyboardAutomatically=_showKeyboardAutomatically;
@property(nonatomic) _Bool allowsEmbedding; // @synthesize allowsEmbedding=_allowsEmbedding;
@property(copy, nonatomic) NSArray *activityTypeOrder; // @synthesize activityTypeOrder=_activityTypeOrder;
@property(nonatomic) long long excludedActivityCategories; // @synthesize excludedActivityCategories=_excludedActivityCategories;
@property(copy, nonatomic) NSArray *includedActivityTypes; // @synthesize includedActivityTypes=_includedActivityTypes;
@property(copy, nonatomic) CDUnknownBlockType preCompletionHandler; // @synthesize preCompletionHandler=_preCompletionHandler;
@property(copy, nonatomic, getter=_shareSheetReadyToInteractHandler, setter=_setShareSheetReadyToInteractHandler:) CDUnknownBlockType shareSheetReadyToInteractHandler; // @synthesize shareSheetReadyToInteractHandler=_shareSheetReadyToInteractHandler;
@property(readonly, nonatomic) NSArray *resolvedActivityItemsForCurrentActivity; // @synthesize resolvedActivityItemsForCurrentActivity=_resolvedActivityItemsForCurrentActivity;
@property(retain, nonatomic) NSArray *activityTypesToCreateInShareService; // @synthesize activityTypesToCreateInShareService=_activityTypesToCreateInShareService;
@property(nonatomic, getter=_readyToInteractTimestamp, setter=_setReadyToInteractTimestamp:) unsigned long long readyToInteractTimestamp; // @synthesize readyToInteractTimestamp=_readyToInteractTimestamp;
@property(nonatomic, getter=_viewWillAppearTimestamp, setter=_setViewWillAppearTimestamp:) unsigned long long viewWillAppearTimestamp; // @synthesize viewWillAppearTimestamp=_viewWillAppearTimestamp;
@property(nonatomic, getter=_beginPerformingActivityTimestamp, setter=_setBeginPerformingActivityTimestamp:) unsigned long long beginPerformingActivityTimestamp; // @synthesize beginPerformingActivityTimestamp=_beginPerformingActivityTimestamp;
@property(nonatomic, getter=_clientAttemptedInitialPresentationOrEmbeddingTimestamp, setter=_setClientAttemptedInitialPresentationOrEmbeddingTimestamp:) unsigned long long clientAttemptedInitialPresentationOrEmbeddingTimestamp; // @synthesize clientAttemptedInitialPresentationOrEmbeddingTimestamp=_clientAttemptedInitialPresentationOrEmbeddingTimestamp;
@property(nonatomic, getter=_isPerformingPresentation, setter=_setIsPerformingPresentation:) _Bool isPerformingPresentation; // @synthesize isPerformingPresentation=_isPerformingPresentation;
@property(nonatomic, getter=_hasPerformedInitialPresentation, setter=_setHasPerformedInitialPresentation:) _Bool hasPerformedInitialPresentation; // @synthesize hasPerformedInitialPresentation=_hasPerformedInitialPresentation;
@property(nonatomic) _Bool shouldMatchOnlyUserElectedExtensions; // @synthesize shouldMatchOnlyUserElectedExtensions=_shouldMatchOnlyUserElectedExtensions;
@property(nonatomic) _Bool performActivityForStateRestoration; // @synthesize performActivityForStateRestoration=_performActivityForStateRestoration;
@property(copy, nonatomic) NSString *subject; // @synthesize subject=_subject;
@property(nonatomic) unsigned long long backgroundTaskIdentifier; // @synthesize backgroundTaskIdentifier=_backgroundTaskIdentifier;
@property(nonatomic) long long completedProviderCount; // @synthesize completedProviderCount=_completedProviderCount;
@property(nonatomic) long long totalProviderCount; // @synthesize totalProviderCount=_totalProviderCount;
@property(retain, nonatomic) NSOperationQueue *activityItemProviderOperationQueue; // @synthesize activityItemProviderOperationQueue=_activityItemProviderOperationQueue;
@property(retain, nonatomic) NSArray *activityItemProviderOperations; // @synthesize activityItemProviderOperations=_activityItemProviderOperations;
@property(retain, nonatomic) UIAlertAction *activityAlertCancelAction; // @synthesize activityAlertCancelAction=_activityAlertCancelAction;
@property(retain, nonatomic) _UIAlertControllerShimPresenter *activityAlertControllerShimPresenter; // @synthesize activityAlertControllerShimPresenter=_activityAlertControllerShimPresenter;
@property(retain, nonatomic) UIAlertController *activityAlertController; // @synthesize activityAlertController=_activityAlertController;
@property(copy, nonatomic, getter=_activityPresentationCompletionHandler, setter=_setActivityPresentationCompletionHandler:) CDUnknownBlockType activityPresentationCompletionHandler; // @synthesize activityPresentationCompletionHandler=_activityPresentationCompletionHandler;
@property(nonatomic) _Bool willDismissActivityViewController; // @synthesize willDismissActivityViewController=_willDismissActivityViewController;
@property(nonatomic) _Bool dismissalDetectionOfViewControllerForSelectedActivityShouldAutoCancel; // @synthesize dismissalDetectionOfViewControllerForSelectedActivityShouldAutoCancel=_dismissalDetectionOfViewControllerForSelectedActivityShouldAutoCancel;
@property(copy, nonatomic) CDUnknownBlockType _popoverDismissalAction; // @synthesize _popoverDismissalAction=__popoverDismissalAction;
@property(retain, nonatomic) Class originalPopoverBackgroundViewClass; // @synthesize originalPopoverBackgroundViewClass=_originalPopoverBackgroundViewClass;
@property(nonatomic) long long originalPopoverBackgroundStyle; // @synthesize originalPopoverBackgroundStyle=_originalPopoverBackgroundStyle;
@property(retain, nonatomic) _UIActivityHelper *activityHelper; // @synthesize activityHelper=_activityHelper;
@property(retain, nonatomic) NSMutableDictionary *activitiesByUUID; // @synthesize activitiesByUUID=_activitiesByUUID;
@property(copy, nonatomic) NSArray *applicationActivities; // @synthesize applicationActivities=_applicationActivities;
@property(copy, nonatomic) NSArray *activityItems; // @synthesize activityItems=_activityItems;
@property(retain, nonatomic, getter=_placeholderViewController, setter=_setPlaceholderViewController:) _UIActivityGroupListViewController *placeholderViewController; // @synthesize placeholderViewController=_placeholderViewController;
@property(nonatomic) _Bool _viewServiceBeganConnecting; // @synthesize _viewServiceBeganConnecting=__viewServiceBeganConnecting;
@property(nonatomic) _Bool shareServicePreferredContentSizeIsValid; // @synthesize shareServicePreferredContentSizeIsValid=_shareServicePreferredContentSizeIsValid;
@property(nonatomic) _Bool waitingForInitialShareServicePreferredContentSize; // @synthesize waitingForInitialShareServicePreferredContentSize=_waitingForInitialShareServicePreferredContentSize;
@property(retain, nonatomic) UISUIActivityViewControllerConfiguration *activityViewControllerConfiguration; // @synthesize activityViewControllerConfiguration=_activityViewControllerConfiguration;
@property(retain, nonatomic) id <_UIShareExtensionService> shareExtensionService; // @synthesize shareExtensionService=_shareExtensionService;
@property(copy, nonatomic) id <NSCopying> extensionRequestIdentifier; // @synthesize extensionRequestIdentifier=_extensionRequestIdentifier;
@property(retain, nonatomic) NSExtension *shareExtension; // @synthesize shareExtension=_shareExtension;
@property(retain, nonatomic) _UIShareExtensionRemoteViewController *remoteContentViewController; // @synthesize remoteContentViewController=_remoteContentViewController;
@property(copy, nonatomic) NSArray *excludedActivityTypes; // @synthesize excludedActivityTypes=_excludedActivityTypes;
@property(copy, nonatomic) CDUnknownBlockType completionWithItemsHandler; // @synthesize completionWithItemsHandler=_completionWithItemsHandler;
@property(copy, nonatomic) CDUnknownBlockType completionHandler; // @synthesize completionHandler=_completionHandler;
- (void).cxx_destruct;
- (void)shareExtensionServiceAirDropActivityDidSuccessfullyCompleteTransfer;
- (void)shareExtensionServiceAirDropActivityDidSuccessfullyStartTransfer;
- (void)_willPerformInServiceActivityType:(id)arg1 activitySpecificMetadata:(id)arg2;
- (void)shareExtensionServiceRequestPerformActivityInHostForExtensionActivityWithBundleIdentifier:(id)arg1;
- (void)shareExtensionServiceRequestPerformActivityInHostForActivityUUID:(id)arg1;
- (void)shareExtensionServiceDidFinishPerformingInServiceActivityWithUUID:(id)arg1 responseData:(id)arg2;
- (void)shareExtensionServiceWillPerformInServiceActivityWithDataRequest:(id)arg1 dismissPresentation:(_Bool)arg2 completion:(CDUnknownBlockType)arg3;
- (void)shareExtensionServiceDisableSheetAvoidsKeyboardUntilContentSizeUpdate;
- (void)shareExtensionServiceChangeSheetDismissButtonHidden:(_Bool)arg1;
- (void)shareExtensionServiceChangeSheetDismissButtonTitle:(id)arg1;
- (void)_shareExtensionServicePreferredContentSizeUpdated:(struct CGSize)arg1;
- (_Bool)_shouldShowSystemActivityType:(id)arg1;
- (_Bool)activityHelper:(id)arg1 matchingWithContext:(id)arg2 shouldIncludeSystemActivityType:(id)arg3;
- (id)_configurationForActivity:(id)arg1;
- (id)_activityConfigurationsForActivities:(id)arg1;
- (id)_newShareUIConfigurationWithMatchingResults:(id)arg1;
- (id)_newShareUIConfigurationForCurrentState;
- (void)_loadActivityViewControllerConfiguration;
- (void)_preheatActivityViewControllerConfiguration;
- (void)_insertIntoActivitiesByUUID:(id)arg1;
- (void)_removeFromActivitiesByUUID:(id)arg1;
- (id)_activityWithActivityUUID:(id)arg1;
- (void)decodeRestorableStateWithCoder:(id)arg1;
- (void)encodeRestorableStateWithCoder:(id)arg1;
- (void)actionSheetPresentationControllerDidDismissActionSheet:(id)arg1;
- (id)visualStyleForAlertControllerStyle:(long long)arg1 traitCollection:(id)arg2 descriptor:(id)arg3;
- (void)presentViewController:(id)arg1 animated:(_Bool)arg2 completion:(CDUnknownBlockType)arg3;
- (void)_cancel;
- (void)_didResignContentViewControllerOfPopover:(id)arg1;
- (void)_setPopoverController:(id)arg1;
- (void)observeValueForKeyPath:(id)arg1 ofObject:(id)arg2 change:(id)arg3 context:(void *)arg4;
- (void)_changeActionSheetAvoidsKeyboardDisabledUntilNextUpdatePreferredContentSize:(_Bool)arg1;
- (void)_changeActionPresentationDismissButtonHidden:(_Bool)arg1;
- (void)_changeActionPresentationDismissButtonTitle:(id)arg1;
- (void)_endDismissalDetectionOfViewControllerForSelectedActivityShouldAutoCancel;
- (void)_presentationControllerDismissalTransitionDidEndNotification:(id)arg1;
- (void)_beginDismissalDetectionOfViewControllerForSelectedActivityShouldAutoCancel;
- (void)_endInProgressActivityExecutionForcedStrongReference;
- (void)_beginInProgressActivityExecutionForcedStrongReference;
- (_Bool)_queueBackgroundOperationsForActivityItems:(id)arg1 activityBeingPerformed:(id)arg2;
- (void)_performActivity:(id)arg1;
- (_Bool)_shouldExecuteItemOperation:(id)arg1 forActivity:(id)arg2;
- (void)_performActivityOfType:(id)arg1 executionEnvironment:(long long)arg2;
- (void)_prepareActivity:(id)arg1 completion:(CDUnknownBlockType)arg2;
- (void)_prepareActivity:(id)arg1;
- (id)_titleForActivity:(id)arg1;
- (void)_resetAfterActivity:(_Bool)arg1;
- (void)_executeActivity;
- (void)_cleanupActivityWithSuccess:(_Bool)arg1;
- (void)_cleanupActivityWithSuccess:(_Bool)arg1 items:(id)arg2 error:(id)arg3;
- (void)_emitInteractionTelemetry:(_Bool)arg1 error:(id)arg2;
- (void)_clearActivity;
- (void)_performDismissWithCompletionHandler:(CDUnknownBlockType)arg1;
- (void)_updateSourceIsManagedForURLs;
- (_Bool)shouldAutorotateToInterfaceOrientation:(long long)arg1;
- (void)viewWillTransitionToSize:(struct CGSize)arg1 withTransitionCoordinator:(id)arg2;
- (void)dismissViewControllerAnimated:(_Bool)arg1 completion:(CDUnknownBlockType)arg2;
- (void)setModalPresentationStyle:(long long)arg1;
- (id)_presentationControllerForPresentedController:(id)arg1 presentingController:(id)arg2 sourceController:(id)arg3;
- (_Bool)_requiresCustomPresentationController;
- (void)_updatePlaceholderPreferredContentSize;
- (void)preferredContentSizeDidChangeForChildContentContainer:(id)arg1;
- (void)viewSafeAreaInsetsDidChange;
- (void)viewDidLayoutSubviews;
- (void)__viewControllerWillBePresented:(_Bool)arg1;
- (void)viewWillDisappear:(_Bool)arg1;
- (void)viewDidAppear:(_Bool)arg1;
- (void)viewWillAppear:(_Bool)arg1;
- (double)_displayHeight;
- (void)_presentationOrEmbeddingDidBegin:(_Bool)arg1;
- (void)_createAndInstallPlaceholderViewControllerIfNeeded;
- (_Bool)_isActionRowExcluded;
- (_Bool)_isSharingRowExcluded;
- (_Bool)_isAirDropExcludedWithActivityItemValues:(id)arg1;
- (_Bool)_shouldIncludeTagsUIPlaceholderWithActivityItemValues:(id)arg1;
- (id)_containedAlertController;
- (void)_shareSheetReadyToInteractAfterCACommit:(_Bool)arg1;
- (void)_removePlaceholderViewControllerIfNeeded;
- (void)_installViewController:(id)arg1;
- (void)_embedRemoteContentViewControllerAndPerformAfterCompletingFencedCommit:(CDUnknownBlockType)arg1;
- (void)viewDidLoad;
- (void)_updateActivityViewControllerConfiguration;
- (void)_updateActivityItems:(id)arg1;
- (id)_newActivityMatchingContext;
- (id)_availableActivities;
- (id)_activityItemValues;
- (id)_securityScopedURLsForMatching;
- (id)_activityItemURLValuesForMatching;
- (id)_placeholderActivityItemValues;
- (void)dealloc;
- (void)_setupLegacyAlertPresentationControllers;
- (void)_preheatActivitiesIfNeeded;
- (void)_shareServiceFinishedInitialPreferredContentSizeUpdate;
- (void)_sendInitialShareServiceConfigurationAndUpdatePreferredContentSize;
- (void)_retryRemoteViewServiceConnectionIfPossibleWithPriming:(_Bool)arg1 previousAttempts:(long long)arg2;
- (void)_connectToRemoteViewServiceOnceWithPriming:(_Bool)arg1 previousAttempts:(long long)arg2;
- (void)_primeExtensionDiscovery;
- (void)_preloadInitialConfigurationLocallyIfNeeded;
- (id)initWithActivityItems:(id)arg1 applicationActivities:(id)arg2;
- (id)initWithCoder:(id)arg1;
- (id)initWithNibName:(id)arg1 bundle:(id)arg2;
- (id)init;
@property(copy, nonatomic) CDUnknownBlockType dismissCompletionHandler;

// Remaining properties
@property(readonly, copy) NSString *debugDescription;
@property(readonly, copy) NSString *description;
@property(readonly) unsigned long long hash;
@property(readonly) Class superclass;

@end

但同样,这只是为了探索。您永远不应依赖此信息来获取生产代码。 (例如,/System/iOSSupport/System/Library/PrivateFrameworks/ 中的 UIKitCore 版本有一个较小的不包含 subject 的 ivars 列表,因此这甚至可能不适用于所有 UIKit 平台。)

不相关的注释:属性 的实际名称是 subject,而不是 Subject。因为 setValue(_:forKey:) 自动将第一个字母大写并构造 setSubject:,所以您可以逃脱惩罚。有关其工作原理的更多详细信息,请参阅 Key-Value Coding Programming Guide。一般来说,在Swift中直接使用KVC并不常用,在Swift中一般应避免使用setValue(_:forKey:)和其他KVC方法,除非你知道自己在做什么。它们不是类型安全的。