sorting - AVPlayer not working correct w/ my array - swift -
i have ui collection retrieves data camera roll load videos collection. attempting when select video in collection, play in custom uiview avplayer; works great, except when play video not play correct video in array have appended video urls in to. play random video library , crash app pointing appending video urls , saying "fatal out of range". can't seem figure out why occurring. correctly printing out values of array count; think has how retrieving video.
here fetching video:
let requestoptions = phimagerequestoptions() requestoptions.issynchronous = true requestoptions.deliverymode = .highqualityformat let fetchoptions = phfetchoptions() fetchoptions.sortdescriptors = [nssortdescriptor(key: "creationdate", ascending: false)] if let fetchresult : phfetchresult = phasset.fetchassets(with: .video, options: fetchoptions) { if fetchresult.count > 0 { in 0..<fetchresult.count{ //used fetch image// imgmanager.requestimage(for: fetchresult.object(at: i) phasset , targetsize: cgsize(width: 200, height: 200), contentmode: .aspectfit, options: requestoptions, resulthandler: { image, error in let imageofvideo = image! uiimage self.imagearray.append(imageofvideo) }) //used fetch video// imgmanager.requestavasset(forvideo: fetchresult.object(at: i) phasset, options: phvideorequestoptions(), resulthandler: {(avasset, audiomix, info) -> void in if let asset = avasset as? avurlasset { let videodata = nsurl(string: "\(asset.url)") let duration : cmtime = asset.duration let durationinsecond = cmtimegetseconds(duration) print(durationinsecond) self.videoarray.append(videodata!) print(self.videoarray) } }) } } else{ //showallerttoimportimage()//a function show alert } } }
the loading of each cell -> don't think matter though
func collectionview(_ collectionview: uicollectionview, cellforitemat indexpath: indexpath) -> uicollectionviewcell { let cell = collectionview.dequeuereusablecell(withreuseidentifier: cellid, for: indexpath) as! videoselectioncvcell cell.uploadedfile.image = imagearray[indexpath.row] return cell }
the didselect: ->> think issue is
func collectionview(_ collectionview: uicollectionview, didselectitemat indexpath: indexpath) { displayview.frame = cgrect(x: self.view.frame.size.width / 2, y: self.view.frame.size.height / 2, width:self.view.frame.size.width / 1.15, height: self.view.frame.size.height / 1.3) displayview.center = view.center displayview.backgroundcolor = uicolor.clear displayview.layer.cornerradius = displayview.layer.frame.size.width / 10 displayview.layer.bordercolor = uicolor.black.cgcolor displayview.layer.borderwidth = 4 //displayview.avplayerlayer.cornerradius = displayview.avplayerlayer.frame.size.width/10 displayview.url = videoarray[indexpath.row] }
the count
func collectionview(_ collectionview: uicollectionview, numberofitemsinsection section: int) -> int { return imagearray.count }
the custom player:
class videoplayback: uiview { var url: nsurl! var avplayer: avplayer! var avplayerlayer: avplayerlayer! var cancelbutton: uibutton! // empty implementation adversely affects performance during animation. override func draw(_ rect: cgrect) { self.backgroundcolor = uicolor.black avplayer = avplayer(url: url! url) avplayer.actionatitemend = avplayeractionatitemend.none avplayerlayer = avplayerlayer(player: avplayer) notificationcenter.default.addobserver(self, selector: #selector(playeritemdidreachend(_:)), name: nsnotification.name.avplayeritemdidplaytoendtime, object: avplayer.currentitem) avplayerlayer.frame = cgrect(x: 0, y: 0, width: self.frame.width, height: self.frame.height) //avplayerlayer.frame = self.layer.bounds self.layer.addsublayer(avplayerlayer) avplayer.play() } func playeritemdidreachend(_ notification: notification) { let playeritem = notification.object as! avplayeritem playeritem.seek(to: kcmtimezero) } }
here full collection view class in case.
again, think has how appending , retrieving videos.
instead of having 2 arrays, believe safer create small class or struct (i.e. media) hold image , video , create media array use collection view. because 2 methods fetching asynchronous never know index video/image combo assigned to. also, try nesting async calls same media instance used both calls keep data consistency.
here non tested example:
struct media { var image:uiimage? var videourl:url? } var mediaarray = [media]() in 0..<fetchresult.count{ let mediaitem = media() //used fetch image// imgmanager.requestimage(for: fetchresult.object(at: i) phasset , targetsize: cgsize(width: 200, height: 200), contentmode: .aspectfit, options: requestoptions, resulthandler: { image, error in let imageofvideo = image! uiimage mediaitem.image = imageofvideo; //used fetch video// imgmanager.requestavasset(forvideo: fetchresult.object(at: i) phasset, options: phvideorequestoptions(), resulthandler: {(avasset, audiomix, info) -> void in if let asset = avasset as? avurlasset { let videodata = url(string: "\(asset.url)") let duration : cmtime = asset.duration let durationinsecond = cmtimegetseconds(duration) print(durationinsecond) mediaitem.videourl = videodata! self.mediaarray.append(mediaitem) } }) }) }
then use media array populate collectionview. don't forget unwrap data. don't use force unwrapping , (almost) never have crashes
Comments
Post a Comment