将 UIView 中可拖动按钮的位置保存到核心数据中
Posted
技术标签:
【中文标题】将 UIView 中可拖动按钮的位置保存到核心数据中【英文标题】:Saving Placement of a Draggable Button within the UIView into Core Data 【发布时间】:2016-02-15 16:28:47 【问题描述】:我希望能够将用户单击添加按钮(在导航栏中)创建的 UIView 中可拖动按钮的位置保存到核心数据中,以便用户保存数据并调用从核心数据创建的表格视图单元格中可以看出它与用户保存它的位置相同。我已经设置了我的核心数据,我只想知道我应该使用 NSKeyedArchiver 还是其他东西来解决这个问题的最佳方法是什么。这是我的代码,这里有一些图片以便更好地理解。
图表.m
@interface ChartViewController ()
@end
@implementation ChartViewController
-(void)viewDidLoad
[super viewDidLoad];
self.title = @"Chart";
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event
UITouch *aTouch = [touches anyObject];
CGRect buttonRect = self.buttonField.frame;
CGPoint point = [aTouch locationInView:self.buttonField.superview];
if (!CGRectContainsPoint(buttonRect, point))
_buttonField.layer.borderColor = [UIColor blackColor].CGColor;
_draggedView.layer.borderColor = [UIColor blackColor].CGColor;
for (_buttonField in self.view.subviews)
_buttonField.layer.borderColor = [UIColor blackColor].CGColor;
- (void)longPress:(UILongPressGestureRecognizer*)gesture
if ( gesture.state == UIGestureRecognizerStateBegan )
gesture.view.layer.borderColor = [UIColor whiteColor].CGColor;
UIAlertController * alert= [UIAlertController
alertControllerWithTitle:@"Would you like to delete the selected rep(s)?"
message:nil
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* deleteButton = [UIAlertAction
actionWithTitle:@"Delete"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action)
for (_buttonField in self.view.subviews)
if ([[UIColor colorWithCGColor:_buttonField.layer.borderColor] isEqual:[UIColor whiteColor]])
[_buttonField removeFromSuperview];
[alert dismissViewControllerAnimated:YES completion:nil];
];
UIAlertAction* cancelButton = [UIAlertAction
actionWithTitle:@"Cancel"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action)
[alert dismissViewControllerAnimated:YES completion:nil];
];
[alert addAction:deleteButton];
[alert addAction:cancelButton];
[self presentViewController:alert animated:YES completion:nil];
- (void)panWasRecognized:(UIPanGestureRecognizer *)panner
panner.view.layer.borderColor = [UIColor whiteColor].CGColor;
_draggedView = panner.view;
CGPoint offset = [panner translationInView:_draggedView.superview];
CGPoint center = _draggedView.center;
_draggedView.center = CGPointMake(center.x + offset.x, center.y + offset.y);
_draggedView.layer.masksToBounds =YES;
_buttonField.layer.borderWidth = 3.0f;
// Reset translation to zero so on the next `panWasRecognized:` message, the
// translation will just be the additional movement of the touch since now.
[panner setTranslation:CGPointZero inView:_draggedView.superview];
-(void)buttonTouched:(UIButton*)sender forEvent:(id)tap
NSSet *touches = [tap allTouches];
UITouch *touch = [touches anyObject];
touch.view.layer.borderColor = [UIColor whiteColor
].CGColor;
-(void)doubleTapped:(UIButton*)sender forEvent:(id)twoTaps
NSSet *touches = [twoTaps allTouches];
UITouch *touch = [touches anyObject];
touch.view.layer.borderColor = [UIColor blackColor].CGColor;
- (IBAction)saveButton:(UIBarButtonItem*)saveRep
saveCount ++;
if (saveCount == 1)
self.title = @"Chart";
for (_buttonField in self.view.subviews)
_buttonField.userInteractionEnabled = NO;
_buttonField.layer.borderColor = [UIColor blackColor].CGColor;
saveCount = 0;
- (IBAction)editButton:(UIBarButtonItem*)editRep
editCount ++;
if (editCount == 1)
self.title = @"Edit Mode";
for (_buttonField in self.view.subviews)
_buttonField.userInteractionEnabled = YES;
editCount = 0;
- (IBAction)addRepButton:(UIBarButtonItem *)newRep
self.labelCounter++;
buttonCount ++;
if (buttonCount > 0 )
_buttonField = [[UIButton alloc]initWithFrame:CGRectMake(300, 300, 28, 28)];
[_buttonField setTitle:[NSString stringWithFormat:@"%i", self.labelCounter]forState:UIControlStateNormal];
_buttonField.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter;
_buttonField.userInteractionEnabled = YES;
_buttonField.layer.cornerRadius = 14;
_buttonField.layer.borderColor = [UIColor blackColor].CGColor;
_buttonField.layer.borderWidth = 3.0f;
_buttonField.titleLabel.font = [UIFont boldSystemFontOfSize:13];
[_buttonField setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
_buttonField.layer.backgroundColor = [UIColor blackColor].CGColor;
_buttonField.layer.masksToBounds = YES;
//Pan gesture declared in button
UIPanGestureRecognizer *panner = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panWasRecognized:)];
[_buttonField addGestureRecognizer:panner];
//Long Press gesture declared in button
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPress:)];
[self.buttonField addGestureRecognizer:longPress];
//Touch down inside declared in button
[self.buttonField addTarget:self action:@selector(buttonTouched:forEvent:) forControlEvents:UIControlEventTouchDown];
//Double Tap inside declared in button
[self.buttonField addTarget:self action:@selector(doubleTapped:forEvent:) forControlEvents:UIControlEventTouchDownRepeat];
[self.view addSubview:(_buttonField)];
- (void) saveData
NSMutableDictionary *dataDict = [[NSMutableDictionary alloc] initWithCapacity:3];
if (_buttonField != nil)
[dataDict setObject:_buttonField forKey:@"placement"]; // save the placement array
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectoryPath = [paths objectAtIndex:0];
NSString *filePath = [documentsDirectoryPath stringByAppendingPathComponent:@"Rep"];
[NSKeyedArchiver archiveRootObject:dataDict toFile:filePath];
Picture of ViewController
当用户按下完成时,我想将其从那里保存到核心数据中。谢谢!!
【问题讨论】:
这是如此少量的数据,我不会为 CoreData 的开销而烦恼。我只想将NSValue
保存到NSUserDefaults
。更简单。
我之所以要使用核心数据,是因为我希望该特定对象与存储在核心数据字符串中的特定数据相关联。我知道这很令人困惑。
【参考方案1】:
对于CGRect
,还有一个简单的方法是使用一个字符串,它已经是 Core Data 中的标准数据类型。
// Swift and Objective-C
object.rect = NSStringFromCGRect(frame)
view.frame = CGRectFromString(object.rect)
虽然NSValue
也是一个不错的选择,但它也非常可读。
【讨论】:
【参考方案2】:在您的数据模型中添加一个名为 boundingRect 的可转换对象。然后,当您的用户完成拖动按钮时,请说出以下内容:
managedObject.boundingRect = [NSValue valueWithCGRect:button.frame];
然后当你想从数据库中读取它时说:
UIButton *button = [[UIButton alloc]initWithFrame: [managedObject.boundingRect CGRectValue]];
【讨论】:
以上是关于将 UIView 中可拖动按钮的位置保存到核心数据中的主要内容,如果未能解决你的问题,请参考以下文章