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:
class CLBeaconExtender: CLBeacon{
var id: String!
}
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?
i think the error is caused by this line:
beacon_manager = beacons as! [CLBeaconExtender]
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
}
}
}
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.