Micheal
Micheal

Reputation: 305

Look through all records for a specific attribute and see the highest value

Ok, so I have an app that is designed for roleplaying. I have a guide that guides the user to creating the character. So the first thing the user has to do is put the character number. So I want it to search all the records for the attribute I have called characternumber and see what the largest number is.

Example: Lets say I have 5 characters. with character numbers 1,2,3,4,5. I want to cycle through all the records and see that 5 is the biggest number than automatically place a 6 in the character number text field.

This is what I have so far:

 @IBOutlet var societyNumberTxt: UITextField!
    @IBOutlet var characterNumberTxt: UITextField!

    let managedObjectContext = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext

    var characters: [NSManagedObject] = []
    var societyNum: [NSManagedObject] = []
    var charNum: [String] = []

    override func viewDidLoad()
    {
        super.viewDidLoad()

        //1
        guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else {
            return
        }

        let managedContext = appDelegate.persistentContainer.viewContext

        //2
        let fetchRequest = NSFetchRequest<NSManagedObject>(entityName: "Characters")

        //3
        do {
            societyNum = try managedContext.fetch(fetchRequest)

            let entityDescription = NSEntityDescription.entity(forEntityName: "Characters", in: managedObjectContext)

            let request: NSFetchRequest<Characters> = Characters.fetchRequest()
            request.entity = entityDescription

            var results = try managedObjectContext.fetch(request as! NSFetchRequest<NSFetchRequestResult>)

            if societyNum.count > 0
            {
                let match = results[0] as! NSManagedObject
                societyNumberTxt.text = (match.value(forKey: "societynumber") as? String)!
                print(match)

                if (match.value(forKey: "characternumber") != nil)
                {
                    self.charNum = match.value(forKey: "characternumber") as! [String]
                    print(self.charNum)
                }
                else
                {
                    print("empty array")
                    characterNumberTxt.text = "1"
                }
            }
            else
            {
                societyNumberTxt.placeholder = "Society # not set"
            }

        } catch let error as NSError {
            print("Could not fetch. \(error), \(error.userInfo)")
        }

    }

I am not sure how to cycle through every record and check the attribute and place in the array. I have tried something like this:

var i = 0

for i in results
{
    var match = results[i] as? NSManagedObject
    charNum[i] = match
}

I get the error:
cannot subscript a value of type '[Any]' with an index of type 'Any'

Now to test my code for the if statement:

if (match.value(forKey: "characternumber") != nil)
{
    self.charNum = match.value(forKey: "characternumber") as! [String]
    print(self.charNum)
}

It returned and error:
Could not cast value of type 'NSTaggedPointerString' (0x108578d10) to 'NSArray' (0x108578dd8).

Am I even on the right past?

Upvotes: 0

Views: 52

Answers (1)

shallowThought
shallowThought

Reputation: 19602

Adjust your fetch request with a SortDescriptor instead of finding the highest characterNumber manually:

...

//2
// get all characters ...
let fetchRequest = NSFetchRequest<NSManagedObject>(entityName: "Characters")

// ... sorted by characternumber in acending order
let sortDescriptor = NSSortDescriptor(key: "characternumber", ascending: true)
let sortDescriptors = [sortDescriptor]
fetchRequest.sortDescriptors = sortDescriptors

//3
do {
    let characters = try managedContext.fetch(fetchRequest) as! [Characters]
    if let  highestCharacterNumber = characters.last?.characternumber {
        characterNumberTxt.text = String(highestCharacterNumber + 1) // assuming characternumber is of type Int
    } else {
        characterNumberTxt.text = "1"
    }
} ...

Upvotes: 2

Related Questions