Dav*_*e G 3 core-data uitableview swift
当前行为
我的核心数据跟踪UITableView列表的值.每行都有标题和说明.我的核心数据用于追加新记录,然后删除它们.核心数据也非常适合编辑现有记录的内容.
问题/疑问
我刚刚在表格中添加了拖放功能.从表面上看,它完美无缺.我可以将顶部项目拖动到底部,从中间到顶部等.但是,由于核心数据记录未更新,因此新的列表顺序在应用程序关闭后不会保留.
我找到了一些关于此的教程,但似乎没有一个与我的代码一起使用.我还花了几个小时试图使用和调整我当前的核心数据技能集(更新,删除,编辑)来发明一个解决方案.我没有甜蜜的动作或代码功夫.
如果您选择接受此任务,以下是您可能需要的详细信息和代码.
信息
在Swift中编码
使用X-Code 6.4
核心数据信息:
文件名是:CD_Model
实体名称:TodayTask
属性名称:"name"和"desc"
码:
主列表变量:
var todayTaskList = [NSManagedObject]()
Run Code Online (Sandbox Code Playgroud)
使用UITableView的主列表页面的ViewDidLoad
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
//Break
//Load the list from Core Data
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let managedContext = appDelegate.managedObjectContext!
let fetchRequest = NSFetchRequest(entityName:"TodayTask")
var error: NSError?
let fetchedResults = managedContext.executeFetchRequest(fetchRequest, error: &error) as? [NSManagedObject]
if let results = fetchedResults {
todayTaskList = results
} else {
println("Could not fetch \(error), \(error!.userInfo)")
}
//Break
//This provides a variable height for each row
tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 80.0
//Break
//Part of code for cell drag and drop functionality
let longpress = UILongPressGestureRecognizer(target: self, action: "longPressGestureRecognized:")
tableView.addGestureRecognizer(longpress)
}
Run Code Online (Sandbox Code Playgroud)
表设置
//***** ----- ***** ------ ***** ----- ***** ----- *****
//Table View & Cell Setup
//***** ----- ***** ------ ***** ----- ***** ----- *****
@IBOutlet weak var name_Label: UILabel!
@IBOutlet weak var desc_Label: UILabel!
//Tells the table how many rows it should render
//*Looks to the Core Data NSObject to count tasks
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return todayTaskList.count
}
//Creates the individual cells. If the above function returns 3, this runs 3 times
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
//Setup variables
let cellIdentifier = "BasicCell"
let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as! CustomTableViewCell
let task = todayTaskList[indexPath.row]
//Create table cell with values from Core Data attribute lists
cell.nameLabel!.text = task.valueForKey("name") as? String
cell.descLabel!.text = task.valueForKey("desc") as? String
//Make sure the row heights adjust properly
tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 80.0
return cell
}
Run Code Online (Sandbox Code Playgroud)
这就是我的问题所在,拖放.此代码有效,但缺少重新排列核心数据的代码.如果没有该代码,当我缩小差距时,任何拖放重新排序都会重置:
//This function initiates the Drag & Drop code.
func longPressGestureRecognized(gestureRecognizer: UIGestureRecognizer) {
let longPress = gestureRecognizer as! UILongPressGestureRecognizer
let state = longPress.state
var locationInView = longPress.locationInView(tableView)
var indexPath = tableView.indexPathForRowAtPoint(locationInView)
struct My {
static var cellSnapshot : UIView? = nil
}
struct Path {
static var initialIndexPath : NSIndexPath? = nil
}
let currentCell = tableView.cellForRowAtIndexPath(indexPath!) as! CustomTableViewCell;
var dragCellName = currentCell.nameLabel!.text
var dragCellDesc = currentCell.descLabel.text
//Steps to take a cell snapshot. Function to be called in switch statement
func snapshopOfCell(inputView: UIView) -> UIView {
UIGraphicsBeginImageContextWithOptions(inputView.bounds.size, false, 0.0)
inputView.layer.renderInContext(UIGraphicsGetCurrentContext())
let image = UIGraphicsGetImageFromCurrentImageContext() as UIImage
UIGraphicsEndImageContext()
let cellSnapshot : UIView = UIImageView(image: image)
cellSnapshot.layer.masksToBounds = false
cellSnapshot.layer.cornerRadius = 0.0
cellSnapshot.layer.shadowOffset = CGSizeMake(-5.0, 0.0)
cellSnapshot.layer.shadowRadius = 5.0
cellSnapshot.layer.shadowOpacity = 0.4
return cellSnapshot
}
switch state {
case UIGestureRecognizerState.Began:
//Calls above function to take snapshot of held cell, animate pop out
//Run when a long-press gesture begins on a cell
if indexPath != nil {
Path.initialIndexPath = indexPath
let cell = tableView.cellForRowAtIndexPath(indexPath!) as UITableViewCell!
My.cellSnapshot = snapshopOfCell(cell)
var center = cell.center
My.cellSnapshot!.center = center
My.cellSnapshot!.alpha = 0.0
tableView.addSubview(My.cellSnapshot!)
UIView.animateWithDuration(0.25, animations: { () -> Void in
center.y = locationInView.y
My.cellSnapshot!.center = center
My.cellSnapshot!.transform = CGAffineTransformMakeScale(1.05, 1.05)
My.cellSnapshot!.alpha = 0.98
cell.alpha = 0.0
}, completion: { (finished) -> Void in
if finished {
cell.hidden = true
}
})
}
case UIGestureRecognizerState.Changed:
//Runs when the user "lets go" of the cell
//Sets CG Y-Coordinate of snapshot cell to center of current location in table (snaps into place)
//If the indexPath is not 0 AND is not the same as it began (didn't move)...
//Update array and table row order
var center = My.cellSnapshot!.center
center.y = locationInView.y
My.cellSnapshot!.center = center
if ((indexPath != nil) && (indexPath != Path.initialIndexPath)) {
swap(&todayTaskList[indexPath!.row], &todayTaskList[Path.initialIndexPath!.row])
tableView.moveRowAtIndexPath(Path.initialIndexPath!, toIndexPath: indexPath!)
Path.initialIndexPath = indexPath
}
default:
//Runs continuously as there's a long press recognized?
//Animates cell movement
//Completion block:
//Removes snapshot of cell, cleans everything up
let cell = tableView.cellForRowAtIndexPath(Path.initialIndexPath!) as UITableViewCell!
cell.hidden = false
cell.alpha = 0.0
UIView.animateWithDuration(0.25, animations: { () -> Void in
My.cellSnapshot!.center = cell.center
My.cellSnapshot!.transform = CGAffineTransformIdentity
My.cellSnapshot!.alpha = 0.0
cell.alpha = 1.0
}, completion: { (finished) -> Void in
if finished {
Path.initialIndexPath = nil
My.cellSnapshot!.removeFromSuperview()
My.cellSnapshot = nil
}
})
}
Run Code Online (Sandbox Code Playgroud)
我很确定我需要的代码会进入第二个case语句:
case UIGestureRecognizerState.Changed:
Run Code Online (Sandbox Code Playgroud)
我也认为我需要的代码会从......开始.
var appDel: AppDelegate = (UIApplication.sharedApplication().delegate as! AppDelegate)
var context: NSManagedObjectContext = appDel.managedObjectContext!
Run Code Online (Sandbox Code Playgroud)
但是有没有特殊的重新安排代码?我是否必须删除并插入?如果是这样,怎么样?
非常感谢能够帮助解决这个问题的任何人!
首先,您可能会发现为每个实体创建类更容易,这样您就不必使用模糊键入NSManagedObject或读取和转换的对象valueForKey(_:).在下面的解决方案中,我已经包含了代码示例.
因此,要解决您的订单问题,您可以做两件事:
1)添加定义Task实体顺序的属性.这可以是一个简单的NSNumber被叫displayOrder.然后,您的提取请求可以根据该属性对结果进行排序.然后,在重新排列表格单元格时,遍历任务列表并更新displayOrder每个任务的属性以反映它们的显示顺序.保存您的托管对象上下文,下次加载请求时,它会相应地对它们进行排序.
class Task: NSManagedObject {
@NSManaged var name: NSString
@NSManaged var desc: NSString
@NSManaged var displayOrder: NSNumber
}
let fetchRequest = NSFetchRequest()
let sortDescriptor = NSSortDescriptor(key: "displayOrder", ascending: true )
fetchRequest.sortDescriptors = [ sortDescriptor ]
Run Code Online (Sandbox Code Playgroud)
2)创建一个CoreData实体,该实体表示具有多对多关系的列表,该关系将每个任务实体存储在有序集中.然后,当您向集合添加任务时,它们将按照您添加它们的顺序保存.
class TaskList: NSManagedObject {
@NSManaged var tasks: NSOrderedSet?
}
class Task: NSManagedObject {
@NSManaged var name: NSString
@NSManaged var desc: NSString
@NSManaged var parentList: TaskList?
}
Run Code Online (Sandbox Code Playgroud)
更新以回答剩余的问题:
我强烈建议您使用自己的自定义类而不是NSManagedObject,但直到您在这里找到该部分,您可以对代码执行的操作.
在重新排列或删除后更新显示顺序:
func updateDisplayOrder() {
for i in 0..<todayTaskList.count {
let task = todayTaskList[i]
task.setValue( i, forKey: "displayOrder" )
}
}
Run Code Online (Sandbox Code Playgroud)
要附加新任务:
func addTask( task: NSManagedObject, displayOrder: Int ) {
todayTaskList.insert( task, atIndex: displayOrder )
updateDisplayOrder()
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1315 次 |
| 最近记录: |