0

i want to pass some extra information through CLBeacon so i create a subclass of it called CLBeaconExtender. the problem is while executing the code, it give me this error

NSArray element failed to match the Swift Array Element type

this is the code:


Subclass of CLBeacon

class CLBeaconExtender: CLBeacon{
    var id: String!
}

MainClass

class beaconController_1: UIViewController, CLLocationManagerDelegate {

    var beacon_collection: UICollectionView!
    var location_manager = CLLocationManager()
    var beacon_manager = [CLBeaconExtender]()
    var beacon_region = [CLBeaconRegion]()

  // Other code that i don't paste

  func locationManager(_ manager: CLLocationManager, didRangeBeacons beacons: [CLBeacon], in region: CLBeaconRegion) {
        if !beacons.isEmpty {
            beacon_manager = beacons as! [CLBeaconExtender]
            beacon_manager[0].id = "hello world"  // here appear the error
            beacon_collection.reloadData()
        }
        else{
            if beacon_manager.count != 0 {
                beacon_manager = beacons as! [CLBeaconExtender]
                beacon_collection.reloadData()
            }
        }
    }

can anyone solve me this problem or show me an example?

Edit

i think the error is caused by this line:

beacon_manager = beacons as! [CLBeaconExtender]

Edit 2

Sorry for my english, my goal is to create a collectionview that display all the beacons around me, and update the list every time that didRangBeacons is called, in addition every collectionviewcell should contain a specific file audio referring to the respective beacon. So when i tap a specific cell of a specific beacon it start to play a specific sound. My problem is handle the beacon_manager array. In the first cycle of didRangeBeacons everything goes fine because !beacon_manager.indices.contains(i) return !false so it will execute the if condition, and it will populate all the beacon_manager. than in the second cycle of didRangeBeacons the if condition will return !true so the code executed will be the else condition. here the system will crash executing beacon_manager.remove(at: i) where i is 0 and beacon_manager[0] exist.

the crash show me the AppDelegate class with the error:

EXEC_BAD_ACCESS code=1 address= 0x8

Hope you'll understand it now.

   func locationManager(_ manager: CLLocationManager, didRangeBeacons beacons: [CLBeacon], in region: CLBeaconRegion) {
    if !beacons.isEmpty {
        var i = 0
        for beacon in beacons {
            let bx = CLBeaconExtender(b: beacon, sID: "hello world")
            if(!beacon_manager.indices.contains(i)){  //check if beacon_manager array exist at i if no create it, if yes update it
                beacon_manager.insert(bx, at: i)
            }
            else{
                beacon_manager.remove(at: i)
                beacon_manager.insert(bx, at: i)

            }
            print(beacon_manager[i].id)
            i+=1
        }

        print(beacon_manager.count,beacons.count)
        beacon_collection.reloadData()
    }
    else{
        if beacon_manager.count != 0 {
            //do other things
        }
    }
}
Fiorelo Odobashi
  • 121
  • 1
  • 1
  • 11

2 Answers2

0

The problem with the type:-

1) Array is a struct, therefore, it is a value type in Swift.

2) NSArray is an immutable Objective-C class therefore, it is a referenced type.

Salman Ghumsani
  • 3,647
  • 2
  • 21
  • 34
0

You cannot simply say "this object is now another type" and magically change the object. For example:

    let x = UIView()
    let y = x as! UIImageView

If you tried to run those two lines, you'd get an error like:

Could not cast value of type 'UIView' (0x107fa44c0) to 'UIImageView' (0x107fa5c08).

So, that's what you are trying to do here:

beacon_manager = beacons as! [CLBeaconExtender]

You are saying "I declare this NSArray of CLBeacon objects is now an Array of CLBeaconExtender objects!" and things just don't work like that.

One approach to what you're trying to do would be to define your CLBeaconExtender class as:

class CLBeaconExtender: CLBeacon {
    var id: String!
    var bcn: CLBeacon!

    convenience init(b: CLBeacon, sID: String) {
        self.init()
        bcn = b
        id = sID
    }
}

Then, in your didRangeBeacons function:

func locationManager(_ manager: CLLocationManager, didRangeBeacons beacons: [CLBeacon], in region: CLBeaconRegion) {

    for beacon in beacons {
        let bx = CLBeaconExtender(b: beacon, sID: "hello world")
        beacon_manager.append(bx)
    }

    // other code...
}

Of course, you won't want to do that, as you'd end up appending lots of the same beacon object, all with the id of "hello world". But, hopefully that helps you understand the error you were getting, and gets you on your way to fixing it.

DonMag
  • 69,424
  • 5
  • 50
  • 86
  • ok, that's really helpful. i have another question: i setup this function to add or replace items in beacon_manager, the first cycle work fine because i have only to insert items, but in the second cycle (of didrangbeacons) when it goes to the else condition give me EXEC_BAD_ACCES while removing items code------> if(!beacon_manager.indices.contains(i)){ beacon_manager.insert(bx_m, at: i) } else{ beacon_manager.remove(at: 0) beacon_manager.insert(bx_m, at: 0) } – Fiorelo Odobashi May 16 '17 at 18:18
  • look at EDIT 2 on the top – Fiorelo Odobashi May 16 '17 at 18:20
  • Sorry, I'm not following that... maybe edit your question again, but add a few comments so it's obvious what you are trying to do. – DonMag May 16 '17 at 18:30
  • You probably need to post this as a new question -- there is too much going on for continued comments. What you are asking now is, essentially, "How do I track objects in an array?" – DonMag May 16 '17 at 19:52
  • ok i think you're right. let me ask you the last question (maybe i can solve in a different way). Does exist a way to overwrite the elements of array[i] with new elements ( taking in consideration that the new element might be less, equal, or more than the old element). Using .insert or .append etc will only ADD items. i don't want to add, i want to replace it – Fiorelo Odobashi May 16 '17 at 20:12