将 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 中可拖动按钮的位置保存到核心数据中的主要内容,如果未能解决你的问题,请参考以下文章

powerpoint中可输入文本的工具

php页面刷新时Mysql可拖动位置重置

可拖动数据库 PHP 和 MYSQL

如何拖动 UIView 元素并更改位置?

重新排序时无法从当前位置拖动 UITableViewCell

保存位置的JQuery可拖动图像