I have used SVGkit and my code have a error.
When I exec the app, the images load but the xCode shows the error and it close my app.
When I exec the app, the images load but the xCode shows the error and it close my app.
When I exec the app, the images load but the xCode shows the error and it close my app.
tableview function
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as? TableViewCell
// else {
// return UITableViewCell()
// }
//print("cantidad: \(self.banderas.count)")
DispatchQueue.global().async {
if !self.banderas.isEmpty {
if !indexPath.isEmpty{
//print(self.banderas[indexPath.row].bandera)
if self.banderas[indexPath.row].bandera != ""{
let url = URL(string: ("\(self.banderas[indexPath.row].bandera)"))
if url != nil {
let data = try? Data(contentsOf: url!)
DispatchQueue.main.async {
guard let anSVGImage: SVGKImage = SVGKImage(data: data!) else {
return
}
cell?.labelNombre.text = "\(self.banderas[indexPath.row].nombre)"
cell?.labelIdioma.text = "\(self.banderas[indexPath.row].idioma)"
cell?.labelMoneda.text = "\(self.banderas[indexPath.row].moneda)"
cell?.imageCell.image = anSVGImage.uiImage
}
}
}
}
}
}
return cell!
}
CARGAR FUNCTION.
func cargar(){
let url = "https://restcountries.eu/rest/v2/all"
Alamofire.request(url).responseJSON { (response) in
//let result = response.data
if let value = response.result.value {
let json = JSON(value)
self.totalCountries = json.count
var contador = 0
let jsonArray = json.arrayValue
for arr in jsonArray{
let nombre = arr["name"].stringValue
let banderaUrl = arr["flag"].stringValue
var moneda = ""
var idioma = ""
contador = 0
for item in arr["currencies"].arrayValue {
if contador == 0{
moneda = item["code"].stringValue
}
contador += 1
}
contador = 0
for item in arr["languages"].arrayValue {
if contador == 0{
idioma = item["nativeName"].stringValue
}
contador += 1
}
let banderaIndividual = Banderas(nombre: nombre, idioma: idioma, moneda: moneda, bandera: banderaUrl)
self.banderas.append(banderaIndividual)
}
}
self.banderasBuscar = self.banderas
self.tabla.reloadData()
}
// print(self.countriesLista.first?.bandera)
}
This is my code, the error is:
NSAssert( linkedElement != nil, #"Found an SVG <use> tag that points to a non-existent element. Missing element: id = %#", linkHref );
I don't know what happen, please help.
Related
I am developing Instagram-like an app that has insta reels-like UI where videos are played in the list but what happens now is when cell comes on scree video buffers or loads and it takes 1-2 sec to load because of that uicollectionview scroll lags.
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let currentItem = appData[indexPath.item]
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "swipablePostCollectionViewCell", for: indexPath) as! swipablePostCollectionViewCell
preFetchNextItems(currentIndexPath: indexPath)
if currentItem["video_url"] != "" && currentItem["video_url"] != nil {
cell.postVideoView.isHidden = false
cell.postImageView.isHidden = true
cell.postVideoView.tag = indexPath.item
DispatchQueue.main.async {
if let imageURL: URL = URL(string: currentItem["video_url"]!) {
if indexPath.item == 0 {
let item = VersaPlayerItem(url: imageURL)
cell.postVideoView.set(item: item)
cell.postVideoView.play()
} else {
if let newItem = self.prefetchedData[indexPath.item - 1] as? VersaPlayerItem {
cell.postVideoView.set(item: newItem)
}
}
cell.postVideoView.controls?.behaviour.shouldHideControls = false
cell.postVideoView.isPipModeEnabled = false
cell.postVideoView.autoplay = false
cell.postVideoView.renderingView.playerLayer.videoGravity = AVLayerVideoGravity.resizeAspect
cell.postVideoView.layer.backgroundColor = UIColor.black.cgColor
cell.postVideoView.use(controls: cell.controls)
cell.postVideoView.playbackDelegate?.startBuffering(player: cell.postVideoView.player)
cell.tag = indexPath.item
}
}
return cell
} else {
cell.postVideoView.isHidden = true
cell.postImageView.isHidden = false
if let imageURL: URL = URL(string: currentItem["image_url"] ?? "") {
cell.postImageView.sd_setImage(with: imageURL, placeholderImage: UIImage(named: "error"), options: .delayPlaceholder, context: nil)
cell.postImageView.contentMode = .scaleAspectFill
cell.postImageView.clipsToBounds = true
}
return cell
}
}
And for prefetch
func preFetchNextItems(currentIndexPath: IndexPath?) {
if currentIndexPath?.item == 0 {
for i in 1...4 {
let indexP = IndexPath(item: i, section: 0)
arrFetchedIndexPaths.append(indexP)
lastFetchedIndexPath = indexP
GetDataForPrefetchIndexPath()
}
} else {
let newIndePath = IndexPath(item: lastFetchedIndexPath!.item + 1, section: lastFetchedIndexPath!.section)
arrFetchedIndexPaths.append(newIndePath)
lastFetchedIndexPath = newIndePath
GetDataForPrefetchIndexPath()
}
print("Prefetch indexpath - ", arrFetchedIndexPaths)
}
func GetDataForPrefetchIndexPath() {
if appData.count > lastFetchedIndexPath!.item {
let currentItem = appData[lastFetchedIndexPath!.item]
if currentItem["video_url"] != "" && currentItem["video_url"] != nil {
if let imageURL: URL = URL(string: currentItem["video_url"]!) {
let newItem = VersaPlayerItem(url: imageURL)
prefetchedData.append(newItem)
}
} else {
if let imageURL: URL = URL(string: currentItem["image_url"] ?? "") {
// let newImage = sd_setImage(with: imageURL, placeholderImage: UIImage(named: "error"), options: .delayPlaceholder, context: nil)
prefetchedData.append(imageURL)
}
}
for item in prefetchedData {
print(item)
}
}
}
What i need is on first cell next 4 cell video should preloaded and after user scrolls next cell video should load
so that when user scrolls to next cell video will be preloaded and played without buffer.
In this table view i had three sections but for third section i am loading the data using second url and passing dynamic height and will set height depending on array count here sometimes i was getting height and sometimes i was getting nill value can anyone help me how to resolve this ?
The code for this is shown below
self.shippingmethodURL()
self.shippingaddressURL()
func shippingmethodURL() {
guard let url = URL(string: self.shippingMethodURl) else {return}
URLSession.shared.dataTask(with: url, completionHandler: {(data, response, error) -> Void in
if let data = data, let jsonObj = (try? JSONSerialization.jsonObject(with: data, options: .allowFragments)) as? [String:Any] {
self.arrayss = jsonObj as [String : AnyObject]
for value in jsonObj.values {
if let array = value as? [[String:Any]] {
for element in array {
if (element["name"] as? String) != nil {
self.totalCount += 1
}
}
}
}
DispatchQueue.main.async {
let sectionHeight = self.arrayss.count * 31
let cellHeight = self.totalCount * 44
self.heightStart = sectionHeight + cellHeight
}
}
}).resume()
}
func shippingaddressURL() {
let url = NSURL(string: self.url)
URLSession.shared.dataTask(with: (url as URL?)!, completionHandler: {(data, response, error) -> Void in
if let data = data, let jsonObj = try? JSONSerialization.jsonObject(with: data, options: .allowFragments) as? NSDictionary {
self.shippingArray = (jsonObj!.value(forKey: "address") as? [[String: AnyObject]])!
let key = "default"
for obj in self.shippingArray {
if let dict = obj[key] {
self.defaultArray.append(dict as! Int)
}
}
if self.defaultArray.contains(1) {
self.addressSelected = true
self.selected = false
} else {
//item could not be found
}
OperationQueue.main.addOperation({
self.tableDetails.reloadData()
})
}
}).resume()
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if ((addressSelected == true || checkIsPaymentRadioSelect == true) && selected == false){
if (indexPath.section == 0) {
return UITableViewAutomaticDimension
}
else if (indexPath.section == 1) {
return 62
}
else {
if height == 0 {
if heightStart == nil {
shippingmethodURL()
}
return CGFloat(heightStart!)
}
else{
return CGFloat(self.height)
}
}
}
else{
if (indexPath.section == 0){
return UITableViewAutomaticDimension
}
else if (indexPath.section == 1){
return 62
}
else {
return 0
}
}
}
This question already has an answer here:
Asynchronously load image in uitableviewcell
(1 answer)
Closed 5 years ago.
I have a problem with the image in table view cell
The images are downloaded form the Google Firebase and in every cell there is one of that
But when I scroll up or down the images change automatically the index
Here is my code, someone can help me? thanks a lot!
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if postsArray[indexPath.row].imageNoImage == true{
let cell = tableView.dequeueReusableCell(withIdentifier: "imageLook", for: indexPath) as! imageLookTableViewCell
cell.authorLabel.text = self.postsArray[indexPath.row].author
cell.likesCountLabel.text = "\(self.postsArray[indexPath.row].likes!)"
cell.postID = postsArray[indexPath.row].postId
cell.textViewPost.text = self.postsArray[indexPath.row].textPost
let url = URL(string: postsArray[indexPath.row].pathToImage as! String)
if url != nil {
DispatchQueue.global().async {
let data = try? Data(contentsOf: url!)
DispatchQueue.main.async {
if data != nil {
cell.imagePost.image = UIImage(data:data!)
}else{
}
}
}
}
for person in self.postsArray[indexPath.row].peopleWhoLike {
if person == FIRAuth.auth()!.currentUser!.uid {
cell.likesBtn.isHidden = false
break
}
}
return cell
}
Your question is not very descriptive/well written, but I think your problem is that you are not caching your images.
Try this:
let imageCache = NSCache()
let cell = tableView.dequeueReusableCell(withIdentifier: "imageLook", for: indexPath) as! imageLookTableViewCell
cell.authorLabel.text = self.postsArray[indexPath.row].author
cell.likesCountLabel.text = "\(self.postsArray[indexPath.row].likes!)"
cell.postID = postsArray[indexPath.row].postId
cell.textViewPost.text = self.postsArray[indexPath.row].textPost
let url = URL(string: postsArray[indexPath.row].pathToImage as! String)
if url != nil {
if let cachedImage = imageCache.objectForKey(url) as? UIImage {
cell.imagePost.image = cachedImage
return
}
DispatchQueue.global().async {
let data = try? Data(contentsOf: url!)
DispatchQueue.main.async {
if data != nil {
if let myImageName = UIImage(data:data!){
imageCache.setObject(myImageName, forKey: url)
}
cell.imagePost.image = UIImage(data:data!)
}else{
}
}
}
}
for person in self.postsArray[indexPath.row].peopleWhoLike {
if person == FIRAuth.auth()!.currentUser!.uid {
cell.likesBtn.isHidden = false
break
}
}
return cell
}
My images dont load into the imageview until you scroll the cell off the table and back on, or go to another view and come back to the the view (redraws the cell).
How do I make them load in correctly?
/////////
My viewDidLoad has this in it:
tableView.delegate = self
tableView.dataSource = self
DispatchQueue.global(qos: .background).async {
self.getBusinesses()
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
I call the function download the image here in the .getBusinesses function called in viewDidLoad:
func getBusinesses() -> Array<Business> {
var businessList = Array<Business>()
//let id = 1
let url = URL(string: "**example**")!
let data = try? Data(contentsOf: url as URL)
var isnil = false
if data == nil{
isnil = true
}
print("is nill is \(isnil)")
if(data == nil){
print("network error")
businessList = []
return businessList
}
else{
values = try! JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions.mutableContainers) as! NSDictionary
}
let json = JSON(values)
var i = 0;
for (key, values) in json {
var businessReceived = json[key]
let newBusiness = Business(id: "18", forename: "", surname: "", email: "", password: "", business: true, level: 1, messageGroups: [], problems: [])
newBusiness.name = businessReceived["name"].stringValue
newBusiness.description = businessReceived["description"].stringValue
newBusiness.rating = Int(businessReceived["rating"].doubleValue)
newBusiness.category = businessReceived["category"].intValue
newBusiness.distance = Double(arc4random_uniform(198) + 1)
newBusiness.image_url = businessReceived["image"].stringValue
newBusiness.url = businessReceived["url"].stringValue
newBusiness.phone = businessReceived["phone"].stringValue
newBusiness.postcode = businessReceived["postcode"].stringValue
newBusiness.email = businessReceived["email"].stringValue
newBusiness.id = businessReceived["user_id"].stringValue
if(newBusiness.image_url == ""){
newBusiness.getImage()
}
else{
newBusiness.image = #imageLiteral(resourceName: "NoImage")
}
if(businessReceived["report"].intValue != 1){
businessList.append(newBusiness)
}
}
businesses = businessList
print(businesses.count)
holdBusinesses = businessList
return businessList
}
Here in the business object i have this method to download the image from the url and store it in the business object's image property:
func getImage(){
if(self.image_url != ""){
print("runs imageeee")
var storage = FIRStorage.storage()
// This is equivalent to creating the full reference
let storagePath = "http://firebasestorage.googleapis.com\(self.image_url)"
var storageRef = storage.reference(forURL: storagePath)
// Download in memory with a maximum allowed size of 1MB (1 * 1024 * 1024 bytes)
storageRef.data(withMaxSize: 30 * 1024 * 1024) { data, error in
if let error = error {
// Uh-oh, an error occurred!
} else {
// Data for "images/island.jpg" is returned
self.image = UIImage(data: data!)!
print("returned image")
}
}
}
else{
self.image = #imageLiteral(resourceName: "NoImage")
}
}
I then output it in the tableview here:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = self.tableView.dequeueReusableCell(withIdentifier: "Cell", for : indexPath) as! BusinessesViewCell
cell.businessImage.image = businesses[(indexPath as NSIndexPath).row].image
//.............
return cell
}
self.image = UIImage(data: data!)!
should become
DispatchQueue.main.async {
self.image = UIImage(data: data!)!
}
Inside
storageRef.data(withMaxSize: 30 * 1024 * 1024) { data, error in
EDIT: My initial thought was the download logic was inside the cell, now I know its not.
you either need to call reloadData() on the tableView each time you get to
self.image = UIImage(data: data!)!
or better yet find out which index you just updated, then called
tableView.reloadRows:[IndexPath]
You can use
cell.businessImage.setNeedsLayout()
EDIT 1: Revised code - still does not work.
I've got two custom cells.
The first cell (and only the first cell) will be of type CurrentIssueFrontCoverTableViewCell, and the rest of the cells will be of type CurrentIssueArticlesTableViewCell. I am getting the error, described in the title, when declaring my cellForRowAtIndexPath function. Any idea of to fix this ? Why is it not detecting that I'm returning the cell in my "if" loop ?
override func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell {
let row = indexPath.row
if indexPath.row == 0 {
let cellWithCoverImage = tableView.dequeueReusableCellWithIdentifier(CurrentIssueFrontCoverTableCellIdentifier, forIndexPath: indexPath) as! CurrentIssueFrontCoverTableViewCell
if let currentIssueFrontCoverObject = currentIssueObjects.objectAtIndex(indexPath.row) as? IssueElement {
let title = currentIssueFrontCoverObject.title ?? ""
let timeStampDateObject = NSDate(timeIntervalSince1970: NSTimeInterval(currentIssueFrontCoverObject.timeStamp))
let timeStampDateString = dateFormatter.stringFromDate(timeStampDateObject)
let issueNumber = currentIssueFrontCoverObject.issueNumber ?? ""
let volumeNumber = currentIssueFrontCoverObject.volumeNumber ?? ""
let nodeID = currentIssueFrontCoverObject.nodeID ?? 0
let imageURL = currentIssueFrontCoverObject.imageURL ?? ""
cellWithCoverImage.request?.cancel()
if let coverImage = self.imageCache.objectForKey(imageURL) as? UIImage {
cellWithCoverImage.currentIssueFrontCoverImageView.image = coverImage
} else {
cellWithCoverImage.currentIssueFrontCoverImageView.image = nil
cellWithCoverImage.request = Alamofire.request(.GET, imageURL).responseImage() { response in
if let coverImage = response.result.value {
self.imageCache.setObject(response.result.value!, forKey: imageURL)
cellWithCoverImage.currentIssueFrontCoverImageView.image = coverImage
} else {
}
}
}
} else {
}
return cellWithCoverImage
// Populating data in the "Articles" type cells
} else if indexPath.row >= 1 {
let cellWithoutCoverImage = tableView.dequeueReusableCellWithIdentifier(CurrentIssueArticlesTableCellIdentifier, forIndexPath: indexPath) as! CurrentIssueArticlesTableViewCell
if let currentIssueArticleObject = currentIssueObjects.objectAtIndex(indexPath.row) as? IssueElement {
let title = currentIssueArticleObject.title ?? ""
let timeStampDateObject = NSDate(timeIntervalSince1970: NSTimeInterval(currentIssueArticleObject.timeStamp))
let timeStampDateString = dateFormatter.stringFromDate(timeStampDateObject)
let author = currentIssueArticleObject.author ?? ""
let issueNumber = currentIssueArticleObject.issueNumber ?? ""
let volumeNumber = currentIssueArticleObject.volumeNumber ?? ""
let articleContent = currentIssueArticleObject.articleContent ?? ""
let nodeID = currentIssueArticleObject.nodeID ?? 0
cellWithoutCoverImage.currentIssueArticlesHeadlineLabel.font = UIFont.preferredFontForTextStyle(UIFontTextStyleHeadline)
cellWithoutCoverImage.currentIssueArticlesHeadlineLabel.text = title
cellWithoutCoverImage.currentIssueArticlesAuthorLabel.font = UIFont.preferredFontForTextStyle(UIFontTextStyleSubheadline)
cellWithoutCoverImage.currentIssueArticlesAuthorLabel.text = author
cellWithoutCoverImage.currentIssueArticlesPublishDateLabel.font = UIFont.preferredFontForTextStyle(UIFontTextStyleSubheadline)
cellWithoutCoverImage.currentIssueArticlesPublishDateLabel.text = timeStampDateString
return cellWithoutCoverImage
} else {
}
}
else {
}
}
EDIT 1: Revised code - still does not work
override func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell {
let row = indexPath.row
switch(row) {
case 0:
let cellWithCoverImage = tableView.dequeueReusableCellWithIdentifier(CurrentIssueFrontCoverTableCellIdentifier, forIndexPath: indexPath) as! CurrentIssueFrontCoverTableViewCell
if let currentIssueFrontCoverObject = currentIssueObjects.objectAtIndex(indexPath.row) as? IssueElement {
let title = currentIssueFrontCoverObject.title ?? ""
let timeStampDateObject = NSDate(timeIntervalSince1970: NSTimeInterval(currentIssueFrontCoverObject.timeStamp))
let timeStampDateString = dateFormatter.stringFromDate(timeStampDateObject)
let issueNumber = currentIssueFrontCoverObject.issueNumber ?? ""
let volumeNumber = currentIssueFrontCoverObject.volumeNumber ?? ""
let nodeID = currentIssueFrontCoverObject.nodeID ?? 0
let imageURL = currentIssueFrontCoverObject.imageURL ?? ""
cellWithCoverImage.request?.cancel()
if let coverImage = self.imageCache.objectForKey(imageURL) as? UIImage {
cellWithCoverImage.currentIssueFrontCoverImageView.image = coverImage
} else {
cellWithCoverImage.currentIssueFrontCoverImageView.image = nil
cellWithCoverImage.request = Alamofire.request(.GET, imageURL).responseImage() { response in
if let coverImage = response.result.value {
self.imageCache.setObject(response.result.value!, forKey: imageURL)
cellWithCoverImage.currentIssueFrontCoverImageView.image = coverImage
} else {
return
}
}
}
} else {
break
}
return cellWithCoverImage;
// Populating data in the "Articles" type cells
default:
let cellWithoutCoverImage = tableView.dequeueReusableCellWithIdentifier(CurrentIssueArticlesTableCellIdentifier, forIndexPath: indexPath) as! CurrentIssueArticlesTableViewCell
if let currentIssueArticleObject = currentIssueObjects.objectAtIndex(indexPath.row) as? IssueElement {
let title = currentIssueArticleObject.title ?? ""
let timeStampDateObject = NSDate(timeIntervalSince1970: NSTimeInterval(currentIssueArticleObject.timeStamp))
let timeStampDateString = dateFormatter.stringFromDate(timeStampDateObject)
let author = currentIssueArticleObject.author ?? ""
let issueNumber = currentIssueArticleObject.issueNumber ?? ""
let volumeNumber = currentIssueArticleObject.volumeNumber ?? ""
let articleContent = currentIssueArticleObject.articleContent ?? ""
let nodeID = currentIssueArticleObject.nodeID ?? 0
cellWithoutCoverImage.currentIssueArticlesHeadlineLabel.font = UIFont.preferredFontForTextStyle(UIFontTextStyleHeadline)
cellWithoutCoverImage.currentIssueArticlesHeadlineLabel.text = title
cellWithoutCoverImage.currentIssueArticlesAuthorLabel.font = UIFont.preferredFontForTextStyle(UIFontTextStyleSubheadline)
cellWithoutCoverImage.currentIssueArticlesAuthorLabel.text = author
cellWithoutCoverImage.currentIssueArticlesPublishDateLabel.font = UIFont.preferredFontForTextStyle(UIFontTextStyleSubheadline)
cellWithoutCoverImage.currentIssueArticlesPublishDateLabel.text = timeStampDateString
return cellWithoutCoverImage;
} else {
break
}
}
}
You need to remove the last else in your code cose it's empty. Also you could use a switch like:
switch(row){
case 0:{
// code with the CurrentIssueFrontCoverTableViewCell
....
return cellWithCoverImage;
}
default:{
// code with the CurrentIssueArticlesTableViewCell
...
return cellWithoutCoverImage;
}
}
The comment from Victor is correct. Because if you were to step through every possible outcome of the function, you could possibly reach the end of it without returning anything. You will need to provide a return statement for every possible outcome, including inside all of the 'else' blocks at the end that are currently empty.
Your problem is this:
} else {
return
}
You can't have empty returns in a method expecting a return type, you need to return something here.
Every code path in your method must end in a return that returns a UITableViewCell. Anything that does not will make the compiler complain.