mirror of
https://github.com/MacPass/MacPass.git
synced 2025-12-18 11:09:24 +00:00
Added copy button to attribute editor to remove need for in-view drawing in NSTextField
This commit is contained in:
@@ -257,6 +257,7 @@
|
||||
4CC59C2721AF0893005E8D6B /* MPPathControl.m in Sources */ = {isa = PBXBuildFile; fileRef = 4CC59C2621AF0893005E8D6B /* MPPathControl.m */; };
|
||||
4CC663E7216F7A7100E33965 /* MPPluginRepositoryBrowserViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4CC663E5216F7A7100E33965 /* MPPluginRepositoryBrowserViewController.m */; };
|
||||
4CC6DB7A17D23719002C6091 /* KPKNode+IconImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 4CC6DB7917D23719002C6091 /* KPKNode+IconImage.m */; };
|
||||
4CC91B6B27D7E7E6001E9517 /* MPInspectorEditorView.m in Sources */ = {isa = PBXBuildFile; fileRef = 4CC91B6A27D7E7E6001E9517 /* MPInspectorEditorView.m */; };
|
||||
4CCA8E9B18D91ED9001A6754 /* Quartz.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CCA8E9A18D91ED9001A6754 /* Quartz.framework */; };
|
||||
4CCCE8011D75CA48006AA951 /* MPArrayController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4CCCE8001D75CA48006AA951 /* MPArrayController.m */; };
|
||||
4CCEDE2A179F203B008402BE /* MPOutlineView.m in Sources */ = {isa = PBXBuildFile; fileRef = 4CCEDE29179F203B008402BE /* MPOutlineView.m */; };
|
||||
@@ -848,6 +849,8 @@
|
||||
4CC663E5216F7A7100E33965 /* MPPluginRepositoryBrowserViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MPPluginRepositoryBrowserViewController.m; sourceTree = "<group>"; };
|
||||
4CC6DB7817D23719002C6091 /* KPKNode+IconImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "KPKNode+IconImage.h"; sourceTree = "<group>"; };
|
||||
4CC6DB7917D23719002C6091 /* KPKNode+IconImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "KPKNode+IconImage.m"; sourceTree = "<group>"; };
|
||||
4CC91B6927D7E7E6001E9517 /* MPInspectorEditorView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MPInspectorEditorView.h; sourceTree = "<group>"; };
|
||||
4CC91B6A27D7E7E6001E9517 /* MPInspectorEditorView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MPInspectorEditorView.m; sourceTree = "<group>"; };
|
||||
4CCA7EEC1797866F00B0B55E /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/GeneralPreferences.strings; sourceTree = "<group>"; };
|
||||
4CCA8E9A18D91ED9001A6754 /* Quartz.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Quartz.framework; path = System/Library/Frameworks/Quartz.framework; sourceTree = SDKROOT; };
|
||||
4CCCE7FF1D75CA48006AA951 /* MPArrayController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPArrayController.h; sourceTree = "<group>"; };
|
||||
@@ -1275,6 +1278,8 @@
|
||||
4CFC53BE16E94729007396BE /* MPShadowBox.m */,
|
||||
4C4A100D176286FD00BBF2CA /* MPTableView.h */,
|
||||
4C4A100E176286FD00BBF2CA /* MPTableView.m */,
|
||||
4CC91B6927D7E7E6001E9517 /* MPInspectorEditorView.h */,
|
||||
4CC91B6A27D7E7E6001E9517 /* MPInspectorEditorView.m */,
|
||||
);
|
||||
name = Views;
|
||||
sourceTree = "<group>";
|
||||
@@ -2266,6 +2271,7 @@
|
||||
4CBA2ABA17074C07006D8139 /* MPSettingsHelper.m in Sources */,
|
||||
4C77E37A15B84A240093A587 /* MPAppDelegate.m in Sources */,
|
||||
3C0CDED821D28BF700B2A10B /* MPTouchBarButtonCreator.m in Sources */,
|
||||
4CC91B6B27D7E7E6001E9517 /* MPInspectorEditorView.m in Sources */,
|
||||
4C37A84015B8B474005EF8EE /* MPOutlineDataSource.m in Sources */,
|
||||
4CA0B2F915BCAF6700654E32 /* MPGeneralPreferencesController.m in Sources */,
|
||||
4C8F0C791FD05A6A00BE157F /* NSString+MPPrettyPasswordDisplay.m in Sources */,
|
||||
|
||||
@@ -23,9 +23,9 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
@property (strong) IBOutlet HNHUISecureTextField *valueTextField;
|
||||
@property (strong) IBOutlet NSButton *toggleProtectedButton;
|
||||
@property (strong) IBOutlet NSButton *removeButton;
|
||||
@property (strong) IBOutlet NSButton *actionButton;
|
||||
|
||||
- (void)updateValues;
|
||||
- (void)updateEditing;
|
||||
- (void)updateValuesAndEditing;
|
||||
|
||||
|
||||
@end
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#import <HNHUi/HNHUi.h>
|
||||
#import <KeePassKit/KeePassKit.h>
|
||||
#import "MPPasteBoardController.h"
|
||||
#import "MPInspectorEditorView.h"
|
||||
|
||||
NSString *nameForDefaultKey(NSString *key) {
|
||||
static NSDictionary *mapping;
|
||||
@@ -51,6 +52,10 @@ NSString *nameForDefaultKey(NSString *key) {
|
||||
|
||||
- (void)viewDidLoad {
|
||||
[super viewDidLoad];
|
||||
|
||||
[NSNotificationCenter.defaultCenter addObserver:self selector:@selector(_didEnterMouse:) name:MPInspectorEditorViewMouseEnteredNotification object:self.view];
|
||||
[NSNotificationCenter.defaultCenter addObserver:self selector:@selector(_didExitMouse:) name:MPInspectorEditorViewMouseExitedNotification object:self.view];
|
||||
|
||||
NSString *placeHolder = NSLocalizedString(@"NONE", "Placeholder text for input fields if no entry or group is selected");
|
||||
self.keyTextField.placeholderString = placeHolder;
|
||||
self.valueTextField.placeholderString = placeHolder;
|
||||
@@ -58,17 +63,11 @@ NSString *nameForDefaultKey(NSString *key) {
|
||||
self.toggleProtectedButton.action = @selector(toggleDisplay:);
|
||||
self.toggleProtectedButton.target = self.valueTextField;
|
||||
|
||||
[self updateValues];
|
||||
[self updateEditing];
|
||||
self.actionButton.action = @selector(_copyText:);
|
||||
self.actionButton.target = self;
|
||||
self.actionButton.hidden = YES;
|
||||
|
||||
__weak MPEntryAttributeViewController *welf = self;
|
||||
self.valueTextField.buttonTitle = NSLocalizedString(@"COPY", "Button to copy the value of an Attribute");
|
||||
self.valueTextField.buttonActionBlock = ^void(NSTextField *tf) {
|
||||
NSText *text = [welf.view.window fieldEditor:NO forObject:welf.valueTextField];
|
||||
if([text isKindOfClass:NSTextView.class]) {
|
||||
[welf textField:welf.valueTextField textView:(NSTextView *)text performAction:@selector(copy:)];
|
||||
}
|
||||
};
|
||||
[self updateValuesAndEditing];
|
||||
}
|
||||
|
||||
- (KPKAttribute *)representedAttribute {
|
||||
@@ -80,7 +79,7 @@ NSString *nameForDefaultKey(NSString *key) {
|
||||
|
||||
- (void)setIsEditor:(BOOL)isEditor {
|
||||
_isEditor = isEditor;
|
||||
[self updateEditing];
|
||||
[self updateValuesAndEditing];
|
||||
}
|
||||
|
||||
- (void)setRepresentedObject:(id)representedObject {
|
||||
@@ -101,8 +100,14 @@ NSString *nameForDefaultKey(NSString *key) {
|
||||
|
||||
}
|
||||
_isDefaultAttribute = self.representedAttribute.isDefault;
|
||||
[self updateEditing];
|
||||
[self updateValues];
|
||||
[self updateValuesAndEditing];
|
||||
}
|
||||
|
||||
- (void)_copyText:(id)sender {
|
||||
NSText *text = [self.view.window fieldEditor:NO forObject:self.valueTextField];
|
||||
if([text isKindOfClass:NSTextView.class]) {
|
||||
[self textField:self.valueTextField textView:(NSTextView *)text performAction:@selector(copy:)];
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)textField:(NSTextField *)textField textView:(NSTextView *)textView performAction:(SEL)action {
|
||||
@@ -145,10 +150,11 @@ NSString *nameForDefaultKey(NSString *key) {
|
||||
}
|
||||
|
||||
- (void)_didChangeAttribute:(NSNotification *)notification {
|
||||
[self updateValues];
|
||||
[self updateValuesAndEditing];
|
||||
}
|
||||
|
||||
- (void)updateValues {
|
||||
- (void)updateValuesAndEditing {
|
||||
/* values */
|
||||
self.view.hidden = self.isEditor ? NO : self.representedAttribute.value.length == 0;
|
||||
|
||||
NSString *localizedKey = nameForDefaultKey(self.representedAttribute.key);
|
||||
@@ -162,15 +168,14 @@ NSString *nameForDefaultKey(NSString *key) {
|
||||
|
||||
self.valueTextField.stringValue = self.representedAttribute.value ? self.representedAttribute.value : @"";
|
||||
self.valueTextField.showPassword = !self.representedAttribute.protect;
|
||||
}
|
||||
|
||||
- (void)updateEditing {
|
||||
self.view.hidden = self.isEditor ? NO : self.representedAttribute.value.length == 0;
|
||||
|
||||
/* editor */
|
||||
self.keyTextField.editable = !_isDefaultAttribute && self.isEditor;
|
||||
self.valueTextField.editable = self.isEditor;
|
||||
self.keyTextField.selectable = YES;
|
||||
self.valueTextField.selectable = YES;
|
||||
self.toggleProtectedButton.hidden = _isDefaultAttribute;
|
||||
|
||||
self.removeButton.hidden = !self.isEditor ? YES : _isDefaultAttribute;
|
||||
|
||||
// set draws background first, since bezeld might have side effects
|
||||
@@ -179,6 +184,14 @@ NSString *nameForDefaultKey(NSString *key) {
|
||||
self.valueTextField.bezeled = self.isEditor;
|
||||
}
|
||||
|
||||
- (void)_didEnterMouse:(NSNotification *)notification {
|
||||
self.actionButton.hidden = self.isEditor;
|
||||
}
|
||||
|
||||
- (void)_didExitMouse:(NSNotification *)notification {
|
||||
self.actionButton.hidden = YES;
|
||||
}
|
||||
|
||||
-(void)commitChanges {
|
||||
if(!self.isEditor) {
|
||||
// do not commit changes if we are no editor!
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
<objects>
|
||||
<customObject id="-2" userLabel="File's Owner" customClass="MPEntryAttributeViewController">
|
||||
<connections>
|
||||
<outlet property="actionButton" destination="gab-tS-gBb" id="gvk-hn-Erc"/>
|
||||
<outlet property="keyTextField" destination="m8q-FN-S8D" id="HzJ-cd-ifA"/>
|
||||
<outlet property="removeButton" destination="Nmx-gC-8rG" id="eRy-l0-u0E"/>
|
||||
<outlet property="toggleProtectedButton" destination="hAk-oD-dCj" id="js9-Hx-ycS"/>
|
||||
@@ -17,7 +18,7 @@
|
||||
</customObject>
|
||||
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
|
||||
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
|
||||
<customView id="Hz6-mo-xeY">
|
||||
<customView id="Hz6-mo-xeY" customClass="MPInspectorEditorView">
|
||||
<rect key="frame" x="0.0" y="0.0" width="251" height="43"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<subviews>
|
||||
@@ -32,11 +33,11 @@
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<stackView distribution="fill" orientation="horizontal" alignment="top" spacing="5" horizontalStackHuggingPriority="249.99998474121094" verticalStackHuggingPriority="249.99998474121094" detachesHiddenViews="YES" translatesAutoresizingMaskIntoConstraints="NO" id="LBt-0e-cUK">
|
||||
<stackView distribution="fill" orientation="horizontal" alignment="centerY" spacing="5" horizontalStackHuggingPriority="249.99998474121094" verticalStackHuggingPriority="249.99998474121094" detachesHiddenViews="YES" translatesAutoresizingMaskIntoConstraints="NO" id="LBt-0e-cUK">
|
||||
<rect key="frame" x="0.0" y="0.0" width="251" height="21"/>
|
||||
<subviews>
|
||||
<textField horizontalHuggingPriority="249" verticalHuggingPriority="750" horizontalCompressionResistancePriority="249" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="HZM-H4-dB4" customClass="HNHUISecureTextField">
|
||||
<rect key="frame" x="0.0" y="0.0" width="181" height="21"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="132" height="21"/>
|
||||
<textFieldCell key="cell" lineBreakMode="truncatingTail" truncatesLastVisibleLine="YES" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" drawsBackground="YES" usesSingleLineMode="YES" id="sO3-xr-VwO">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
@@ -47,29 +48,38 @@
|
||||
</connections>
|
||||
</textField>
|
||||
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="hAk-oD-dCj">
|
||||
<rect key="frame" x="179" y="-6" width="44" height="32"/>
|
||||
<rect key="frame" x="130" y="-6" width="44" height="32"/>
|
||||
<buttonCell key="cell" type="push" bezelStyle="rounded" image="NSLockLockedTemplate" imagePosition="only" alignment="center" alternateImage="NSLockUnlockedTemplate" lineBreakMode="truncatingTail" borderStyle="border" inset="2" id="f80-K9-DO7">
|
||||
<behavior key="behavior" lightByBackground="YES" lightByGray="YES" changeBackground="YES" changeGray="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
</button>
|
||||
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="Nmx-gC-8rG">
|
||||
<rect key="frame" x="214" y="-6" width="44" height="32"/>
|
||||
<rect key="frame" x="165" y="-6" width="44" height="32"/>
|
||||
<buttonCell key="cell" type="push" bezelStyle="rounded" image="NSRemoveTemplate" imagePosition="only" alignment="center" state="on" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="179-uk-89S">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
</button>
|
||||
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="gab-tS-gBb">
|
||||
<rect key="frame" x="201" y="-4" width="56" height="27"/>
|
||||
<buttonCell key="cell" type="push" title="Copy" bezelStyle="rounded" alignment="center" controlSize="small" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="0GH-rx-Fg4">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="smallSystem"/>
|
||||
</buttonCell>
|
||||
</button>
|
||||
</subviews>
|
||||
<visibilityPriorities>
|
||||
<integer value="1000"/>
|
||||
<integer value="1000"/>
|
||||
<integer value="1000"/>
|
||||
<integer value="1000"/>
|
||||
</visibilityPriorities>
|
||||
<customSpacing>
|
||||
<real value="3.4028234663852886e+38"/>
|
||||
<real value="3.4028234663852886e+38"/>
|
||||
<real value="3.4028234663852886e+38"/>
|
||||
<real value="3.4028234663852886e+38"/>
|
||||
</customSpacing>
|
||||
</stackView>
|
||||
</subviews>
|
||||
|
||||
@@ -343,6 +343,7 @@ typedef NS_ENUM(NSUInteger, MPEntryTab) {
|
||||
self.passwordEditorViewController.isEditor = !self.passwordEditorViewController.isEditor;
|
||||
self.urlEditorViewController.isEditor = !self.urlEditorViewController.isEditor;
|
||||
self.expiresEditorViewController.isEditor = !self.expiresEditorViewController.isEditor;
|
||||
self.iconViewController.isEditor = !self.iconViewController.isEditor;
|
||||
//self.totpViewController.isEditor = !self.totpViewController.isEditor;
|
||||
}
|
||||
|
||||
|
||||
@@ -37,16 +37,13 @@
|
||||
};
|
||||
}
|
||||
|
||||
- (void)updateValues {
|
||||
- (void)updateValuesAndEditing {
|
||||
self.view.hidden = (!self.isEditor && self.representedAttribute.value.length == 0);
|
||||
self.passwordTextField.stringValue = self.representedAttribute.value ? self.representedAttribute.value : @"";
|
||||
}
|
||||
|
||||
- (void)updateEditing {
|
||||
/* editor */
|
||||
self.generatePasswordButton.hidden = !self.isEditor;
|
||||
self.passwordTextField.editable = self.isEditor;
|
||||
self.passwordTextField.selectable = YES;
|
||||
}
|
||||
|
||||
|
||||
@end
|
||||
|
||||
21
MacPass/MPInspectorEditorView.h
Normal file
21
MacPass/MPInspectorEditorView.h
Normal file
@@ -0,0 +1,21 @@
|
||||
//
|
||||
// MPInspectorEditorView.h
|
||||
// MacPass
|
||||
//
|
||||
// Created by Michael Starke on 08.03.22.
|
||||
// Copyright © 2022 HicknHack Software GmbH. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
FOUNDATION_EXPORT NSString *const MPInspectorEditorViewMouseEnteredNotification;
|
||||
FOUNDATION_EXPORT NSString *const MPInspectorEditorViewMouseExitedNotification;
|
||||
|
||||
|
||||
@interface MPInspectorEditorView : NSView
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
37
MacPass/MPInspectorEditorView.m
Normal file
37
MacPass/MPInspectorEditorView.m
Normal file
@@ -0,0 +1,37 @@
|
||||
//
|
||||
// MPInspectorEditorView.m
|
||||
// MacPass
|
||||
//
|
||||
// Created by Michael Starke on 08.03.22.
|
||||
// Copyright © 2022 HicknHack Software GmbH. All rights reserved.
|
||||
//
|
||||
|
||||
#import "MPInspectorEditorView.h"
|
||||
|
||||
NSString *const MPInspectorEditorViewMouseEnteredNotification = @"com.hicknhacksoftware.macpass.MPInspectorEditorViewMouseEnteredNotification";
|
||||
NSString *const MPInspectorEditorViewMouseExitedNotification = @"com.hicknhacksoftware.macpass.MPInspectorEditorViewMouseExitedNotification";
|
||||
|
||||
@interface MPInspectorEditorView ()
|
||||
|
||||
@property (strong) NSTrackingArea *trackingArea;
|
||||
|
||||
@end
|
||||
|
||||
@implementation MPInspectorEditorView
|
||||
|
||||
- (void)mouseEntered:(NSEvent *)event {
|
||||
[NSNotificationCenter.defaultCenter postNotificationName:MPInspectorEditorViewMouseEnteredNotification object:self];
|
||||
}
|
||||
|
||||
- (void)mouseExited:(NSEvent *)event {
|
||||
[NSNotificationCenter.defaultCenter postNotificationName:MPInspectorEditorViewMouseExitedNotification object:self];
|
||||
}
|
||||
|
||||
- (void)updateTrackingAreas {
|
||||
[super updateTrackingAreas];
|
||||
[self removeTrackingArea:self.trackingArea];
|
||||
self.trackingArea = [[NSTrackingArea alloc] initWithRect:self.bounds options:NSTrackingActiveAlways|NSTrackingMouseEnteredAndExited owner:self userInfo:nil];
|
||||
[self addTrackingArea:self.trackingArea];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -14,6 +14,8 @@
|
||||
@interface MPNodeIconViewController ()
|
||||
@property (strong) IBOutlet NSImageView *imageView;
|
||||
@property (strong) IBOutlet NSTextField *textField;
|
||||
@property (copy) NSUUID *iconUUID;
|
||||
@property NSUInteger iconId;
|
||||
@end
|
||||
|
||||
@implementation MPNodeIconViewController
|
||||
@@ -27,7 +29,6 @@
|
||||
}
|
||||
|
||||
- (void)setRepresentedObject:(id)representedObject {
|
||||
// FIXME: register for correct notifications
|
||||
if(self.representedNode) {
|
||||
KPKNode *node = self.representedNode;
|
||||
if(node.asEntry) {
|
||||
@@ -57,7 +58,7 @@
|
||||
NSLog(@"Inconsitant state for notification handling");
|
||||
}
|
||||
}
|
||||
[self _updateValues];
|
||||
[self _updateValueAndEditing];
|
||||
}
|
||||
|
||||
- (KPKNode *)representedNode {
|
||||
@@ -67,31 +68,30 @@
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (void)_updateValues {
|
||||
- (void)setIsEditor:(BOOL)isEditor {
|
||||
_isEditor = isEditor;
|
||||
[self _updateValueAndEditing];
|
||||
}
|
||||
|
||||
- (void)_updateValueAndEditing {
|
||||
self.imageView.enabled = self.isEditor;
|
||||
self.iconUUID = self.representedNode.iconUUID;
|
||||
self.iconId = self.representedNode.iconId;
|
||||
self.imageView.image = self.representedNode.iconImage;
|
||||
self.textField.stringValue = self.representedNode.title.length > 0 ? self.representedNode.title : @"";
|
||||
}
|
||||
|
||||
- (void)commitChanges {
|
||||
// fixme
|
||||
self.representedNode.iconUUID = self.iconUUID;
|
||||
self.representedNode.iconId = self.iconId;
|
||||
}
|
||||
|
||||
|
||||
- (void)_willChangeNode:(NSNotification *)notification {
|
||||
|
||||
}
|
||||
|
||||
- (void)_didChangeNode:(NSNotification *)notification {
|
||||
[self _updateValues];
|
||||
[self _updateValueAndEditing];
|
||||
}
|
||||
/*
|
||||
- (BOOL)commitEditingAndReturnError:(NSError *__autoreleasing _Nullable * _Nullable)error {
|
||||
<#code#>
|
||||
}
|
||||
|
||||
- (void)encodeWithCoder:(nonnull NSCoder *)coder {
|
||||
<#code#>
|
||||
}
|
||||
*/
|
||||
|
||||
@end
|
||||
|
||||
Reference in New Issue
Block a user