I'm working with a collectionView right now and when I activate the refresh control, it adds a duplicate picture to the data source set for every picture in the set, and then makes it disappear and things go back to normal by the time the refresh control is done. Here's a YouTube video I uploaded to clearly show you what is going on.
https://youtu.be/Q9ZFd-7tSRw
It would seem logical that the data source set would be getting the same data from the API I am using, then displaying it, the duplicate data then getting deleting from the array, and then the collection view being reloaded once more before the refresh control goes away. That's not how I want it to work obviously, but perhaps I have coded it wrong.
viewDidLoad:
override func viewDidLoad() {
super.viewDidLoad()
self.collectionView!.registerClass(PhotoBrowserCollectionViewCell.self, forCellWithReuseIdentifier: PhotoBrowserCellIdentifier)
self.cellLoadingIndicator.backgroundColor = goldenWordsYellow
self.cellLoadingIndicator.hidesWhenStopped = true
if self.revealViewController() != nil {
revealViewControllerIndicator = 1
menuButton.target = self.revealViewController()
menuButton.action = "revealToggle:"
self.view.addGestureRecognizer(self.revealViewController().panGestureRecognizer())
}
self.revealViewController().rearViewRevealWidth = 280
collectionView!.delegate = self
collectionView!.dataSource = self
goldenWordsRefreshControl = UIRefreshControl()
goldenWordsRefreshControl.backgroundColor = goldenWordsYellow
goldenWordsRefreshControl.tintColor = UIColor.whiteColor()
self.collectionView!.addSubview(goldenWordsRefreshControl)
navigationController?.setNavigationBarHidden(false, animated: true)
navigationItem.title = "Pictures"
setupView()
populatePhotos()
self.dateFormatter.dateFormat = "dd/MM/yy"
self.cellLoadingIndicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyle.Gray
self.cellLoadingIndicator.color = goldenWordsYellow
self.cellLoadingIndicator.center = (self.collectionView?.center)!
self.collectionView!.addSubview(cellLoadingIndicator)
self.collectionView!.bringSubviewToFront(cellLoadingIndicator)
/*
self.dateFormatter.dateStyle = NSDateFormatterStyle.ShortStyle
self.dateFormatter.timeStyle = NSDateFormatterStyle.ShortStyle
let currentDateAndTime = NSDate()
let updateString = "Last updated at " + self.dateFormatter.stringFromDate(currentDateAndTime)
self.goldenWordsRefreshControl.attributedTitle = NSAttributedString(string: updateString)
*/
}
populatePhotos:
func populatePhotos() {
if populatingPhotos {
return
}
populatingPhotos = true
self.cellLoadingIndicator.startAnimating()
self.temporaryPictureObjects.removeAllObjects()
Alamofire.request(GWNetworking.Router.Pictures(self.currentPage)).responseJSON() { response in
if let JSON = response.result.value {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0)) {
var nodeIDArray : [Int]
if (JSON .isKindOfClass(NSDictionary)) {
for node in JSON as! Dictionary<String, AnyObject> {
let nodeIDValue = node.0
var lastItem : Int = 0
self.nodeIDArray.addObject(nodeIDValue)
if let pictureElement : PictureElement = PictureElement(title: "Picture", nodeID: 0, timeStamp: 0, imageURL: "http://goldenwords.ca/sites/all/themes/custom/gw/logo.png", author: "Staff", issueNumber: "Issue # error", volumeNumber: "Volume # error") {
pictureElement.title = node.1["title"] as! String
pictureElement.nodeID = Int(nodeIDValue)!
let timeStampString = node.1["revision_timestamp"] as! String
pictureElement.timeStamp = Int(timeStampString)!
if let imageURL = node.1["image_url"] as? String {
pictureElement.imageURL = imageURL
}
if let author = node.1["author"] as? String {
pictureElement.author = author
}
if let issueNumber = node.1["issue_int"] as? String {
pictureElement.issueNumber = issueNumber
}
if let volumeNumber = node.1["volume_int"] as? String {
pictureElement.volumeNumber = volumeNumber
}
lastItem = self.temporaryPictureObjects.count // Using a temporary set to not handle the dataSource set directly (safer).
self.temporaryPictureObjects.addObject(pictureElement)
let indexPaths = (lastItem..<self.temporaryPictureObjects.count).map { NSIndexPath(forItem: $0, inSection: 0) }
}
}
/* Sorting the elements in order of newest to oldest (as the array index increases] */
let timeStampSortDescriptor = NSSortDescriptor(key: "timeStamp", ascending: false)
self.pictureObjects.sortUsingDescriptors([timeStampSortDescriptor])
}
dispatch_async(dispatch_get_main_queue()) {
self.pictureObjects = self.temporaryPictureObjects
self.collectionView!.reloadData()
self.cellLoadingIndicator.stopAnimating()
self.currentPage++
self.populatingPhotos = false
}
}
}
}
}
handleRefresh:
func handleRefresh() {
goldenWordsRefreshControl.beginRefreshing()
self.pictureObjects.removeAllObjects()
self.currentPage = 0
self.cellLoadingIndicator.startAnimating()
self.picturesCollectionView.bringSubviewToFront(cellLoadingIndicator)
self.populatingPhotos = false
populatePhotos()
self.cellLoadingIndicator.stopAnimating()
goldenWordsRefreshControl.endRefreshing()
}
cellForItemAtIndexPath:
override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier(PhotoBrowserCellIdentifier, forIndexPath: indexPath) as! PhotoBrowserCollectionViewCell
if let pictureObject = pictureObjects.objectAtIndex(indexPath.row) as? PictureElement {
let title = pictureObject.title ?? "" // if pictureObject.title == nil, then we return an empty string
let timeStampDateObject = NSDate(timeIntervalSince1970: NSTimeInterval(pictureObject.timeStamp))
let timeStampDateString = dateFormatter.stringFromDate(timeStampDateObject)
let author = pictureObject.author ?? ""
let issueNumber = pictureObject.issueNumber ?? ""
let volumeNumber = pictureObject.volumeNumber ?? ""
let nodeID = pictureObject.nodeID ?? 0
let imageURL = pictureObject.imageURL ?? "http://goldenwords.ca/sites/all/themes/custom/gw/logo.png"
cell.request?.cancel()
if let image = self.imageCache.objectForKey(imageURL) as? UIImage {
cell.imageView.image = image
} else {
cell.imageView.image = nil
cell.request = Alamofire.request(.GET, imageURL).responseImage() { response in
if let image = response.result.value {
self.imageCache.setObject(response.result.value!, forKey: imageURL)
if cell.imageView.image == nil {
cell.imageView.image = image
}
}
}
}
}
return cell
}
Related
I have used tableView to show the post and when I am scrolling my page sometimes it crashes and throws error as: Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid update: invalid number of rows in section 0. The number of rows contained in an existing section after the update (119) must be equal to the number of rows contained in that section before the update (105), plus or minus the number of rows inserted or deleted from that section (1 inserted, 1 deleted) and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out).' I am unable to find out the reason why it's happening
func getFeeds(){
DispatchQueue.main.async {
if(self.isCommentsOpened == false && self.spinner == nil && !self.isPaginating && self.isScrollingUp == false){
self.spinner = CommonUtils.showLoader(view: self)
}
}
var paramsDictionary = [String:Any]()
let xAuthToken:String=UserDefaults.standard.string(forKey: JsonContants.X_AUTH_TOKEN)!
let entityId:String=UserDefaults.standard.string(forKey: JsonContants.ENTITY_ID)!
var apiUrl=domains.global+Apis.feedQueryApi
apiUrl=apiUrl.replacingOccurrences(of: "{entity_id}", with: entityId)
if(isPaginating && pageNo<totalPages){
paramsDictionary[JsonContants.PAGE_NO] = pageNo+1
paramsDictionary[JsonContants.PAGE_SIZE] = pageSize
}else{
paramsDictionary[JsonContants.PAGE_NO] = 1
paramsDictionary[JsonContants.PAGE_SIZE] = pageSize
}
HttpClientApi.instance().makeAPICall(token: xAuthToken,refreshToken: "",url: apiUrl, params:paramsDictionary, method: .POST, success: { (data, response, error) in
do {
if let json = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? [String: Any] {
let httpStatus=response as HTTPURLResponse!
let statusCode=httpStatus?.statusCode
let pageDetails = json[JsonContants.PAGE_DETAILS] as! [String:Any]
if(pageDetails.count>0){
self.pageNo = pageDetails[JsonContants.PAGE_NO] as! Int
self.pageSize = pageDetails[JsonContants.PAGE_SIZE] as! Int
self.totalPages = pageDetails[JsonContants.TOTAL_PAGES] as! Int
}
let feedsArray = json[JsonContants.FEEDS] as! Array<Dictionary<String, Any>>
if(!self.isPaginating){
self.feedsJsonArray = feedsArray
self.feedIdsArray = [String]()
self.feedIdUserIdDict = [String:String]()
self.userIdUserJsonDict = [String:[String:Any]]()
self.imagesJsonArray = []
self.feedIdActivityJsonDict = [String:[[String:Any]]]()
}else{
self.paginationFeedIdsArray = [String]()
self.feedsJsonArray.append(contentsOf: feedsArray)
}
var paginationUserIdDict = [String]()
for object:Dictionary<String,Any> in feedsArray{
let feedId=object[JsonContants.FEED_ID] as? String
self.feedIdsArray.append(feedId!)
let userId = object[JsonContants.USER_ID] as? String
self.feedIdUserIdDict[feedId!] = userId
if(self.isPaginating){
paginationUserIdDict.append(userId!)
self.paginationFeedIdsArray.append(feedId!)
}
}
DispatchQueue.main.async {
if(!self.isPaginating){
self.getUserList(userIds: Array(self.feedIdUserIdDict.values))
self.dismissLoader()
}else{
self.getUserList(userIds: paginationUserIdDict)
self.dismissLoader()
}
}
}
} catch let error {
print(error.localizedDescription)
DispatchQueue.main.async {
if(self.spinner != nil){
self.spinner!.dismissLoader()
self.spinner = nil
}
if((self.topScrollSpinnerContainerView.isHidden == false) || (self.downScrollSpinnerContainerView.isHidden == false)){
self.scrollSpinner!.dismissLoader2()
self.topScrollSpinnerContainerView.isHidden = true
self.downScrollSpinnerContainerView.isHidden = true
}
}
}
}, failure: { (data, response, error) in
DispatchQueue.main.async {
if(self.spinner != nil){
self.spinner!.dismissLoader()
self.spinner = nil
}
if((self.topScrollSpinnerContainerView.isHidden == false) || (self.downScrollSpinnerContainerView.isHidden == false)){
self.scrollSpinner!.dismissLoader2()
self.topScrollSpinnerContainerView.isHidden = true
self.downScrollSpinnerContainerView.isHidden = true
}
}
print(error?.localizedDescription as Any)
})
}
func showSmallLoaderAtBottom(view: UIView) -> UIView {
var spinnerView = UIView(frame: CGRect(x: 0, y: 0, width: 50, height:50))
let spinner = MDCActivityIndicator(frame: CGRect(x: 0, y: 0, width: 50, height:50))
spinner.cycleColors = [UIColor(named: AppColors.appSkyBlue.rawValue)!, UIColor(named: AppColors.appSkyBlue.rawValue)!,UIColor(named: AppColors.appSkyBlue.rawValue)!,UIColor(named: AppColors.appSkyBlue.rawValue)!]
spinnerView.addSubview(spinner)
view.addSubview(spinnerView)
spinner.startAnimating()
return spinnerView
}
func getMoreData(){
if(self.pageNo < self.totalPages){
scrollSpinner = showSmallLoaderAtBottom(view: downScrollSpinnerContainerView)
downScrollSpinnerContainerView.isHidden = false
isPaginating = true
self.getFeeds()
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
self.currentRow = indexPath.row
let cell=tableView.dequeueReusableCell(withIdentifier: "feed_tvcell", for: indexPath) as! FeedTableViewCell
cell.selectionStyle = .none
cell.feedViewController = self
cell.feedsStackView.translatesAutoresizingMaskIntoConstraints = false
let feedJson = self.feedsJsonArray[indexPath.row]
cell.messageTextLabel.numberOfLines = 0
cell.messageTextLabel.lineBreakMode = .byWordWrapping
cell.messageTextLabel.sizeToFit()
if(feedJson[JsonContants.CONTENT] != nil && !(feedJson[JsonContants.CONTENT] as! String).elementsEqual(JsonContants.NA)){
cell.feedMessageView.isHidden = false
cell.messageTextLabel.text = (feedJson[JsonContants.CONTENT] as! String).decodeEmoji
}else{
cell.feedMessageView.isHidden = true
}
let feedId = feedJson[JsonContants.FEED_ID] as! String
let userId = feedIdUserIdDict[feedId] as! String
let userJson = userIdUserJsonDict[userId] as? [String:Any]
var userTitle:[[String:Any]]?
var lastName:String?
var firstName:String?
if(userJson != nil){
userTitle = userJson![JsonContants.USER_TITLE] as? [[String:Any]]
lastName = userJson![JsonContants.LAST_NAME] as? String
firstName = userJson![JsonContants.FIRST_NAME] as? String
}
var roles = self.appDefaults.value(forKey: JsonContants.ROLE) as! [String]
if(firstName != nil){
cell.feeUserName.text = (firstName as! String)
}
if(lastName != nil){
cell.feeUserName.text = cell.feeUserName.text!+" "+(lastName as! String)
}
hideAndShowFeedDeleteButton(roles, cell, userId)
addActionTargetsToCellButtons(cell)
var time = feedJson[JsonContants.LAST_ACTIVITY_TIME] as! Int64
var timeDiff = CommonUtils.getSystemTimeInMillis() - time
cell.feedTime.text = CommonUtils.getStringValueOfTimeDiff(timeDiff: timeDiff)
setCountZero(cell)
setLikeCount(feedId, cell, feedJson)
var feedType = feedJson[JsonContants.TYPE] as! String
let feedCommentCount = feedJson[JsonContants.FEED_COMMENT_COUNT] as! Int
cell.commentCountLabel.text = String(feedCommentCount)
if(userJson != nil){
let userId = userJson![JsonContants.USER_ID] as? String
var cachedMediaId:UIImage?
let userJsonFromDb = CoreDataDatabaseManager.coreDataDatabaseManager.getUser(id: userId!)
if(userJsonFromDb != nil && userJsonFromDb.count>0){
let imageId = userJsonFromDb[JsonContants.IMAGE_ID] as? String
if(userId != nil && imageId != nil){
cachedMediaId = self.getSavedImage(named : imageId!+"."+"png")
}
}
if(cachedMediaId == nil){
cell.feedUserImage.image = #imageLiteral(resourceName: "user_default_round")
getUserImages(userIds: [userId!],cell: cell)
}else{
cell.feedUserImage.image = cachedMediaId
}
}else{
cell.feedUserImage.image = #imageLiteral(resourceName: "user_default_round")
}
if(userJson != nil && userJson![JsonContants.RESIDENT_DETAILS] != nil){
let residentDetails = userJson![JsonContants.RESIDENT_DETAILS] as! [String:Any]
let buildingName = residentDetails[JsonContants.BUILDING_NAME] as! String
let flatName = residentDetails[JsonContants.FLAT_NAME] as! String
let feedUserName:String = cell.feeUserName.text!
if(buildingName.count>0 && flatName.count>0){
cell.feeUserName.text = feedUserName+" - "+buildingName+"("+flatName+")"
}
}else if(userTitle != nil && userTitle!.count>0) {
let titleDict = userTitle![0]
let name = cell.feeUserName.text
if(titleDict.count>0){
var title = titleDict[JsonContants.TITLE] as! String
if(title.elementsEqual(JsonContants.ADMINISTRATOR)){
cell.feeUserName.text = name!+" - "+"Admin"
}
}
}
if(feedType.elementsEqual(JsonContants.SURVEY)){
let options = feedJson[JsonContants.OPTIONS] as! [[String:Any]]
setSurveyData(cell, options, feedId, feedJson,indexPath: indexPath)
}else{
if(feedJson[JsonContants.MEDIA_INFO] != nil && (feedJson[JsonContants.MEDIA_INFO] as! [String:Any]) != nil &&
(feedJson[JsonContants.MEDIA_INFO] as! [String:Any]).count>0){
let mediaJson = feedJson[JsonContants.MEDIA_INFO] as! [String:Any]
let mediaType = mediaJson[JsonContants.MEDIA_TYPE] as! String
cell.optionsTableView.isHidden = true
cell.surveyTotalVotesLabel.isHidden = true
cell.surveyTotalVotesLabelContainer.isHidden = true
cell.feedVideoView.isHidden = true
cell.feedImageView.isHidden = true
if(mediaType.elementsEqual(JsonContants.IMAGE)){
configureFeedImageViewAndSetImage(cell, mediaJson, feedId,indexPath)
}else{
configureFeedMediaViewAndSetVideo(cell, mediaJson, indexPath)
}
}else{
cell.mediaType = "TEXT"
hideFeedMediaViews(cell)
cell.layoutIfNeeded()
}
}
if(indexPath.row == (self.feedsJsonArray.count-2)){
DispatchQueue.main.async{
self.getMoreData()
}
}
cell.layoutIfNeeded()
return cell
}
This kind of error is seen when you explicitly insert or delete cells or sections into or from a TableView and do not simultaneously readjust your row or section counts to match. In your case the error message is telling you exactly what the count mismatch is. The code you posted is not showing any inserts or deletes of rows from the TableView so it must be happening somewhere else in your code, maybe in your getFeeds() method?
There are users being downloaded from firebase and displayed on a UITableView where the cells are selectable and once selected will have a check mark. So from firebase is it is asynchronously downloaded so I think this could be the start of me solving the problem but not sure. When selecting lets say two cells when the view appears and then you begin scrolling through the list other cells will appear to be selected when the user did not select them. Below will be code and pictures of the occurrence.
Firebase Call
func getTableViewData() {
Database.database().reference().child("Businesses").queryOrdered(byChild: "businessName").observe(.childAdded, with: { (snapshot) in
let key = snapshot.key
if(key == self.loggedInUser?.uid) {
print("Same as logged in user, so don't show!")
} else {
if let locationValue = snapshot.value as? [String: AnyObject] {
let lat = Double(locationValue["businessLatitude"] as! String)
let long = Double(locationValue["businessLongitude"] as! String)
let businessLocation = CLLocation(latitude: lat!, longitude: long!)
let latitude = self.locationManager.location?.coordinate.latitude
let longitude = self.locationManager.location?.coordinate.longitude
let userLocation = CLLocation(latitude: latitude!, longitude: longitude!)
let distanceInMeters: Double = userLocation.distance(from: businessLocation)
let distanceInMiles: Double = distanceInMeters * 0.00062137
let distanceLabelText = String(format: "%.2f miles away", distanceInMiles)
var singleChildDictionary = locationValue
singleChildDictionary["distanceLabelText"] = distanceLabelText as AnyObject
singleChildDictionary["distanceInMiles"] = distanceInMiles as AnyObject
self.usersArray.append(singleChildDictionary as NSDictionary)
self.usersArray = self.usersArray.sorted {
!($0?["distanceInMiles"] as! Double > $1?["distanceInMiles"] as! Double)
}
}
//insert the rows
//self.followUsersTableView.insertRows(at: [IndexPath(row:self.usersArray.count-1,section:0)], with: UITableViewRowAnimation.automatic)
self.listedBusiness.reloadData()
}
}) { (error) in
print(error.localizedDescription)
}
}
TableView Setup
// MARK: - Table view data source
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if searchController.isActive && searchController.searchBar.text != ""{
return filteredUsers.count
}
return self.usersArray.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! CustomerAddSelectedBusinessesCell
var user : NSDictionary?
if searchController.isActive && searchController.searchBar.text != ""{
user = filteredUsers[indexPath.row]
} else {
user = self.usersArray[indexPath.row]
}
if cell.isSelected == true {
var user = self.usersArray[indexPath.row]
if CLLocationManager.locationServicesEnabled() {
switch(CLLocationManager.authorizationStatus()) {
case .notDetermined, .restricted, .denied:
print("No access")
cell.businessName.text = String(user?["businessName"] as! String)
cell.businessStreet.text = String(user?["businessStreet"] as! String)
cell.businessCity.text = String(user?["businessCity"] as! String)
//cell.selectedCell.image = UIImage(named: "cellSelected")
let businessProfilePicture = String(user?["profPicString"] as! String)
if (businessProfilePicture.count) > 0 {
let url = URL(string: (businessProfilePicture))
DispatchQueue.global().async {
let data = try? Data(contentsOf: url!)
DispatchQueue.main.async {
let image = UIImage(data: data!)?.potter_circle
cell.businessImage.contentMode = UIView.ContentMode.scaleAspectFill
cell.businessImage.image = image
}
}
} else {
let image = UIImage(named: "default")?.potter_circle
cell.businessImage.contentMode = UIView.ContentMode.scaleAspectFill
cell.businessImage.image = image
}
//cell.profileImage.image =
//cell.businessDistance.text = String(user?["distanceLabelText"] as! String)
case .authorizedAlways, .authorizedWhenInUse:
print("Access")
print("****Called")
cell.businessName.text = String(user?["businessName"] as! String)
cell.businessStreet.text = String(user?["businessStreet"] as! String)
cell.businessCity.text = String(user?["businessCity"] as! String)
cell.businessDistance.text = String(user?["distanceLabelText"] as! String)
//cell.selectedCell.image = UIImage(named: "cellSelected")
let businessProfilePicture = String(user?["profPicString"] as! String)
if (businessProfilePicture.count) > 0 {
let url = URL(string: (businessProfilePicture))
DispatchQueue.global().async {
let data = try? Data(contentsOf: url!)
DispatchQueue.main.async {
let image = UIImage(data: data!)?.potter_circle
cell.businessImage.contentMode = UIView.ContentMode.scaleAspectFill
cell.businessImage.image = image
}
}
} else {
let image = UIImage(named: "default")?.potter_circle
cell.businessImage.contentMode = UIView.ContentMode.scaleAspectFill
cell.businessImage.image = image
}
}
} else {
print("Location services are not enabled")
}
} else if cell.isSelected == false {
var user = self.usersArray[indexPath.row]
if CLLocationManager.locationServicesEnabled() {
switch(CLLocationManager.authorizationStatus()) {
case .notDetermined, .restricted, .denied:
print("No access")
cell.businessName.text = String(user?["businessName"] as! String)
cell.businessStreet.text = String(user?["businessStreet"] as! String)
cell.businessCity.text = String(user?["businessCity"] as! String)
//cell.selectedCell.image = UIImage(named: "cellNotSelected")
let businessProfilePicture = String(user?["profPicString"] as! String)
if (businessProfilePicture.count) > 0 {
let url = URL(string: (businessProfilePicture))
DispatchQueue.global().async {
let data = try? Data(contentsOf: url!)
DispatchQueue.main.async {
let image = UIImage(data: data!)?.potter_circle
cell.businessImage.contentMode = UIView.ContentMode.scaleAspectFill
cell.businessImage.image = image
}
}
} else {
let image = UIImage(named: "default")?.potter_circle
cell.businessImage.contentMode = UIView.ContentMode.scaleAspectFill
cell.businessImage.image = image
}
//cell.profileImage.image =
//cell.businessDistance.text = String(user?["distanceLabelText"] as! String)
case .authorizedAlways, .authorizedWhenInUse:
print("Access")
print("%called")
cell.businessName.text = String(user?["businessName"] as! String)
cell.businessStreet.text = String(user?["businessStreet"] as! String)
cell.businessCity.text = String(user?["businessCity"] as! String)
cell.businessDistance.text = String(user?["distanceLabelText"] as! String)
//cell.selectedCell.image = UIImage(named: "cellNotSelected")
let businessProfilePicture = String(user?["profPicString"] as! String)
if (businessProfilePicture.count) > 0 {
let url = URL(string: (businessProfilePicture))
DispatchQueue.global().async {
let data = try? Data(contentsOf: url!)
DispatchQueue.main.async {
let image = UIImage(data: data!)?.potter_circle
cell.businessImage.contentMode = UIView.ContentMode.scaleAspectFill
cell.businessImage.image = image
}
}
} else {
let image = UIImage(named: "default")?.potter_circle
cell.businessImage.contentMode = UIView.ContentMode.scaleAspectFill
cell.businessImage.image = image
}
}
} else {
print("Location services are not enabled")
}
}
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! CustomerAddSelectedBusinessesCell
let user = usersArray[indexPath.row]
let name = user!["uid"] as? String
var NSdata = NSDictionary()
var realArray = [NSDictionary]()
if let cell = tableView.cellForRow(at: indexPath as IndexPath) {
if cell.accessoryType == .checkmark{
cell.accessoryType = .none
print("Deleted \(name!)")
if let idx = data.index(of:name!) {
data.remove(at: idx)
print(data)
}
} else {
cell.accessoryType = .checkmark
data.append(name!)
print(data)
}
}
print(data)
}
Selected Cells after view loads
Cells that appear to selected but are not
It's most common cell reusable issue. Cells which are visible to screen will be reused when you scroll.
Eg. You've 5 cells visible. when you select 2,3 and scroll down 7,8 will be selected.
To avoid this you've 2 options.
You can use external Bool array to manage this(Bool array count must be same as your array count).
You can put bool variable in your user dictionary to manage that.
So whenever your scroll, newly visible cell will not selected automatically.
I am working on a project to shows news feeds to the user.
I am calling a function getNewsFeeds() to get news feeds.
I will generate new newsfeeds every one hour
ViewDidLoad(){
get current time in "HH" format and store it in currentTime
Store this currentTime in to a HoursVar variable using UserDefaults
}
ViewDidAppear(){
if( currentTime - HoursVar >= 1){
getNewsFeeds
}else{
}
retreiveStoredValuesFromUserDeafults()
}
I dont know where exactly to setup my tableViewDataSOurce and Delegate methods and reloadData to populate the tableView when getting data from the saved Userdefaults retreiveStoredValuesFromUserDeafults()
override func viewDidLoad() {
super.viewDidLoad()
hoursFormatter.dateFormat = "HH"
hoursVar = Int(hoursFormatter.string(from: hours))!
if hoursVar > 12 {
hoursVar = hoursVar - 12
}
self.defaults.set(self.hoursVar, forKey: "hoursVar")
customNavBar()
self.view.addGestureRecognizer(self.revealViewController().panGestureRecognizer())
feedsArray = ["Reliance","Economy"]
}
override func viewDidAppear(_ animated: Bool) {
//getRssFeeds()
if((hoursVar - myHoursVar) == 1 && (hoursVar - myHoursVar) > 1){
getRssFeeds()
}else{
feedsTable.register(UITableViewCell.self, forCellReuseIdentifier: "newsFeeds")
self.feedsTable.delegate = self
self.feedsTable.dataSource = self
retreiveMyArrayData()
feedsTableView.reloadData()
}
}
func getRssFeeds(){
for i in 0..<feedsArray.count{
let url = URL(string: "https://api.cognitive.microsoft.com/bing/v5.0/news/search?q=\(feedsArray[i])&count=3&mkt=en-in")
var request = URLRequest(url: url!)
request.setValue("My Subscription Key", forHTTPHeaderField: "Ocp-Apim-Subscription-Key")
Alamofire.request(request as URLRequest).responseJSON{response in
if let json = response.result.value as? [String:AnyObject]{
if let value = json["value"]{
//
print("json \(json)")
for j in 0..<value.count{
let items = value[j] as! [String:AnyObject]
let name = items["name"] as! String
let url = items["url"] as! String
let description = items["description"] as! String
let datePublished = items["datePublished"] as! String
let dateAndTime = datePublished.replacingOccurrences(of: "T", with: " ")
self.feedsName.append(name)
self.feedsUrl.append(url)
self.feedsDescription.append(description)
self.feedsDatePublished.append(dateAndTime)
if let image = items["image"] as? [String:AnyObject]{
if let thumbnail = image["thumbnail"] as? [String:AnyObject]{
let contentUrl = thumbnail["contentUrl"] as! String
self.feedsContentUrl.append(contentUrl)
}
}else{
self.feedsContentUrl.append(self.errorImage)
}
if let provider = items["provider"]{
for i in 0..<provider.count{
let items = provider[i] as! [String:AnyObject]
let providerName = items["name"] as! String
self.feedsProvider.append(providerName)
}
}
self.feedsTable.delegate = self
self.feedsTable.dataSource = self
self.feedsTable.reloadData()
self.defaults.set(self.feedsUrl, forKey: "feedsUrl")
self.defaults.set(self.feedsDescription, forKey: "feedsDescription")
self.defaults.set(self.feedsName, forKey: "feedsName")
self.defaults.set(self.feedsProvider, forKey: "feedsProvider")
self.defaults.set(self.feedsContentUrl, forKey: "feedsContentUrl")
self.defaults.set(self.feedsDatePublished, forKey: "feedsDatePublished")
print("All Counts \(self.feedsName.count)")
}
}
}
}
}
}
func slideOpen(){
self.revealViewController().revealToggle(animated: true)
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return feedsName.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "newsFeeds") as! newsFeeds
randomNumberArray = randomNumber()
//self.feedsRandomArray.append(self.feedsRandom)
print("feedsRandom \(feedsRandom)")
selectedRow = randomNumberArray[indexPath.row]
let url = URL(string: feedsContentUrl[randomNumberArray[indexPath.row]])
do{
let data = try Data(contentsOf: url!)
cell.feedsImage.image = UIImage(data: data )
}catch{
print(error)
}
let tap = UITapGestureRecognizer(target: self, action: #selector(HomeViewController.tapFunction))
let titleAttributes = [NSFontAttributeName: UIFont.preferredFont(forTextStyle: UIFontTextStyle.headline), NSForegroundColorAttributeName: UIColor.purple]
let titleString = NSAttributedString(string: feedsName[randomNumberArray[indexPath.row]] , attributes: titleAttributes)
cell.feedsHeadlines.isUserInteractionEnabled = true
cell.feedsHeadlines.addGestureRecognizer(tap)
cell.feedsHeadlines.attributedText = titleString
cell.feedsDescription.text = feedsDescription[randomNumberArray[indexPath.row]]
cell.feedsPublisherName.text = feedsProvider[randomNumberArray[indexPath.row]]
cell.publishedOn.text = feedsDatePublished[randomNumberArray[indexPath.row]]
//print("All Counts \(myFeedsName.count) \(myFeedsProvider.count) \(myFeedsContentUrl.count) \(myFeedsUrl.count) \(myFeedsDescription.count) \(myFeedsDescription.count)")
return cell
}
func tapFunction(sender:UITapGestureRecognizer) {
let safariVC = SFSafariViewController(url: NSURL(string: feedsUrl[selectedRow]) as! URL)
self.present(safariVC, animated: true, completion: nil)
safariVC.delegate = self
}
func safariViewControllerDidFinish(_ controller: SFSafariViewController) {
controller.dismiss(animated: true, completion: nil)
}
func randomNumber() -> [Int] {
let feedsIndex = feedsName.count - 1
var randomNumber = Int(arc4random_uniform(UInt32(feedsIndex)))
print("Randome number \(randomNumber) \(randomNumberArray)")
for k in 0..<randomNumberArray.count{
while randomNumber == randomNumberArray[k] {
randomNumber = Int(arc4random_uniform(UInt32(feedsIndex)))
}
}
randomNumberArray.append(randomNumber)
self.defaults.set(self.randomNumberArray, forKey: "randomNumberArray")
return randomNumberArray
}
func retreiveMyArrayData(){
myFeedsUrl = defaults.stringArray(forKey: "feedsUrl") ?? [String]()
myFeedsDescription = defaults.stringArray(forKey: "feedsDescription") ?? [String]()
myFeedsName = defaults.stringArray(forKey: "feedsName") ?? [String]()
myFeedsProvider = defaults.stringArray(forKey: "feedsProvider") ?? [String]()
myFeedsContentUrl = defaults.stringArray(forKey: "feedsContentUrl") ?? [String]()
myFeedsDatePublished = defaults.stringArray(forKey: "feedsDatePublished") ?? [String]()
myHoursVar = defaults.integer(forKey: "hoursVar")
myFeedsRandom = defaults.array(forKey: "randomNumberArray") as! [Int]
print("Values \(myHoursVar) \(myFeedsProvider) \(myFeedsUrl.count)")
}
You can set UITableViewDataSourceand UITableViewDelegate into .xib
//Setting datasource & delegate for tableview inside viewDidLoad
override func viewDidLoad() {
super.viewDidLoad()
self.feedsTableView.delegate = self
self.feedsTableView.datasource = self
}
Now, you need to reload the tableview when you setValue & retrieve the value to the userDefaults. self.feedsTableView.reloadData()
If this didn't helped you, please let me know. I'll work more to provide you with a complete workflow for the above project.
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.
I want to add a search bar in my tableview which is populated with data from Core Data. Below is parts of code from my TableViewController. How do I begin implementing the searchbar function after placing one on the tableview?
let managedObjectContext =
(UIApplication.sharedApplication().delegate
as! AppDelegate).managedObjectContext
var fetchedLastName = [String]()
var fetchedFirstName = [String]()
var fetchedImage = [UIImage]()
override func viewDidLoad() {
super.viewDidLoad()
NSNotificationCenter.defaultCenter().addObserver(self, selector: "reloadData:",name:"load", object: nil)
let entityDescription =
NSEntityDescription.entityForName("Faculty",
inManagedObjectContext: managedObjectContext)
let request = NSFetchRequest()
request.entity = entityDescription
do{
let objects = try managedObjectContext.executeFetchRequest(request)
let results = objects
if results.count > 0 {
for var i = 0; i < results.count; i += 1{
let match = results[i] as! NSManagedObject
fetchedLastName.append((match.valueForKey("lastname") as? String)!)
fetchedFirstName.append((match.valueForKey("firstname") as? String)!)
let image = match.valueForKey("image") as! NSData
fetchedImage.append(UIImage(data: image)!)
}
} else {
}
}
catch{}
}
func reloadData(notification: NSNotification){
fetchedLastName.removeAll()
fetchedFirstName.removeAll()
fetchedImage.removeAll()
let entityDescription =
NSEntityDescription.entityForName("Faculty",
inManagedObjectContext: managedObjectContext)
let request = NSFetchRequest()
request.entity = entityDescription
do{
let objects = try managedObjectContext.executeFetchRequest(request)
let results = objects
if results.count > 0 {
for var i = 0; i < results.count; i += 1{
let match = results[i] as! NSManagedObject
fetchedLastName.append((match.valueForKey("lastname") as? String)!)
fetchedFirstName.append((match.valueForKey("firstname") as? String)!)
let image = match.valueForKey("image") as! NSData
fetchedImage.append(UIImage(data: image)!)
}
} else {
}
}
catch{}
self.tableView.reloadData()
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("TEACH", forIndexPath: indexPath) as! TEACHTableViewCell
let row = indexPath.row
print(fetchedFirstName)
cell.facultyName.text = fetchedLastName[row] + ", " + fetchedFirstName[row]
cell.facultyImage.image = fetchedImage[row]
return cell
}
}
Try this code all tested:
//
// TEACHTableViewController.swift
// TEACH
//
// Created by ICST340.N1 on 9/29/15.
// Copyright © 2015 IyoTugs. All rights reserved.
//
import UIKit
import CoreData
class TEACHTableViewController: UITableViewController, UISearchBarDelegate, UISearchControllerDelegate, UISearchResultsUpdating {
var searchController = UISearchController()
var filteredTableData = [[String: AnyObject?]]()
var tableData = [[String: AnyObject?]]()
let managedObjectContext =
(UIApplication.sharedApplication().delegate
as! AppDelegate).managedObjectContext
var fetchedLastName = [String]()
var fetchedFirstName = [String]()
var fetchedImage = [UIImage]()
override func viewDidLoad() {
super.viewDidLoad()
//setup search controller
searchController = UISearchController(searchResultsController: nil)
searchController.searchResultsUpdater = self
searchController.dimsBackgroundDuringPresentation = false
searchController.delegate = self
tableView.tableHeaderView = searchController.searchBar
definesPresentationContext = true
searchController.searchBar.sizeToFit()
NSNotificationCenter.defaultCenter().addObserver(self, selector: "reloadData:",name:"load", object: nil)
let entityDescription =
NSEntityDescription.entityForName("Faculty",
inManagedObjectContext: managedObjectContext)
let request = NSFetchRequest()
request.entity = entityDescription
do{
let objects = try managedObjectContext.executeFetchRequest(request)
let results = objects
if results.count > 0 {
for var i = 0; i < results.count; i += 1{
let match = results[i] as! NSManagedObject
fetchedLastName.append((match.valueForKey("lastname") as? String)!)
fetchedFirstName.append((match.valueForKey("firstname") as? String)!)
//added this is convert the image
let image = match.valueForKey("image") as! NSData
let realImage = UIImage(data: image)!
fetchedImage.append(UIImage(data: image)!)
tableData.append(["firstName" : match.valueForKey("firstname"), "lastName" : match.valueForKey("firstname"), "image" : realImage])
}
} else {
}
}
catch{}
// Uncomment the following line to preserve selection between presentations
// self.clearsSelectionOnViewWillAppear = false
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem()
}
func reloadData(notification: NSNotification){
fetchedLastName.removeAll()
fetchedFirstName.removeAll()
//Added this to remove all images
fetchedImage.removeAll()
tableData.removeAll()
let entityDescription =
NSEntityDescription.entityForName("Faculty",
inManagedObjectContext: managedObjectContext)
let request = NSFetchRequest()
request.entity = entityDescription
do{
let objects = try managedObjectContext.executeFetchRequest(request)
let results = objects
if results.count > 0 {
for var i = 0; i < results.count; i += 1{
let match = results[i] as! NSManagedObject
fetchedLastName.append((match.valueForKey("lastname") as? String)!)
fetchedFirstName.append((match.valueForKey("firstname") as? String)!)
//added this is convert the image
let image = match.valueForKey("image") as! NSData
let realImage = UIImage(data: image)!
fetchedImage.append(UIImage(data: image)!)
tableData.append(["firstName" : match.valueForKey("firstname"), "lastName" : match.valueForKey("firstname"), "image" : realImage])
}
} else {
}
}
catch{}
self.tableView.reloadData()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
if searchController.active {
return filteredTableData.count
} else {
return fetchedLastName.count
}
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("TEACH", forIndexPath: indexPath) as! TEACHTableViewCell
if searchController.active {
let row = indexPath.row
print(fetchedFirstName)
let firstName = filteredTableData[row]["firstName"] as! String
let lastName = filteredTableData[row]["lastName"] as! String
let image = filteredTableData[row]["image"] as! UIImage
cell.facultyName.text = lastName + ", " + firstName
cell.facultyImage.image = image
} else {
let row = indexPath.row
print(fetchedFirstName)
cell.facultyName.text = fetchedLastName[row] + ", " + fetchedFirstName[row]
cell.facultyImage.image = fetchedImage[row]
}
return cell
}
func filterContentForSearchText(searchText: String) {
for singleTableData in tableData {
let firstname = singleTableData["firstName"] as! String
let lastname = singleTableData["lastName"] as! String
let image = singleTableData["image"] as! UIImage
print(firstname)
print(lastname)
if searchText != "" {
if (firstname.rangeOfString(searchText) != nil) {
filteredTableData.append(["firstName" : firstname, "lastName" : lastname, "image" : image])
} else if (lastname.rangeOfString(searchText) != nil) {
filteredTableData.append(["firstName" : firstname, "lastName" : lastname, "image" : image])
}
} else {
filteredTableData.append(["firstName" : firstname, "lastName" : lastname, "image" : image])
}
}
}
func updateSearchResultsForSearchController(searchController: UISearchController) {
filteredTableData.removeAll()
filterContentForSearchText(searchController.searchBar.text!)
tableView.reloadData()
}
}