I have an IPad MasterDetail project in Xcode 7. I have set up a MasterDetail template. The TableView rows have both title and subtitle. I have the ViewController loaded with a Plist data and it is working. I can NSLog both title and subtitle values from a selected row to check that the data from a selected row is correct.
I need to pass the two values from a selected row to the DetailController. Using a segue I can pass one or the other row items but have not been able to pass both.
Any suggestions would be helpful.
Create an object for it, and pass the object:
For example:
class Album {
var title: String?
var SubTitle: String?
}
Related
I'm building an app which which has built in with 2 different tabs. First tab is is "Home" which basically has a tableview with cells that configured from an api.(The api gets me country names for now)
Those cells also have a "Star" button which prints the data of the specific cell for now.
Second tab is "Saved" tab(SavedViewController), where I want to show the "starred" countries, using a tableview.
You can see the image below in order to get an idea for the app.
App simulation Image
The star button has a function in my CountriesTableViewCell. I'm using a saveButtonDelegate in order to let the SavedViewController know about an item is going to be saved. The code in CountriesTableViewCell for star button is as below.
#objc func buttonTapped() {
//If Button is selected fill the image. Else unfill it.
if !isSaveButtonSelected {
saveButton.setImage(UIImage(systemName: "star.fill"), for: .normal)
isSaveButtonSelected = true
saveButtonDelegate?.saveButtonClicked(with: countryData) //Checking if save button is clicked
}
}
countryData is the data that I get from the api, and this is the data I want to pass to SavedViewController.
struct CountryData: Codable {
let name : String
}
So on the SavedViewController, I'm handling the data using the SaveButtonProtocol conformance as below:
extension SavedViewController: SaveButtonProtocol {
func saveButtonClicked(with data: CountryData) {
countryDataArray.append(data)
print("saveButtonClicked")
print("countryData in savevc is \(countryDataArray)")
DispatchQueue.main.async {
self.countriesTableView.reloadData()
}
}
}
Whenever I click the star button on the first tab, this function is getting called on SavedViewController. So whenever I click to button, those print statements above work fine.
The problem is, whenever the star button is clicked, it should append the data of the current clicked cell to countryDataArray in SavedViewController. But the array is not populating as it should.
Let's say I pressed the first cell's star button, my print("countryData in savevc is (countryDataArray)") statement prints : ["Vatican City"], then I press the second cell's star button it only prints ["Ethiopia"] while it should print ["Vatican City", "Ethiopia"]
Why this issue is happening? My best guess is I'm delegating SavedViewController from the cell class so it behaves differently for every other cell. If that is the problem what should I do to solve it?
Many Thanks.
You should store your data in a shared (static array) object so you only have one source and add the saved indicator in your country struct so you do not rely on what is displayed in one view controller.
I have tableview where I need to show few sections. You should imagine this table like a playlist of your songs. In the top first section I need to display a cell with button which will add more songs to the playlist and other sections of tableview are header titles of Music category (like pop, rock and etc). Each of these sections contains cells which are songs names.
I have an array of songs called like this: var songsGroups = [SongGroup]. Which is actually my datasource.
SongGroup contains few properties:
var categoryName: String
var songs: [Songs]
But the problem appears on the next level. I every time need to check indexPath.section and do like this:
if indexPath.section == 0 {
// this is a section for ADD NEW SONG BUTTON cell no need in header title as there is no data repression only static text on the cell.
} else {
var musicCategoryName = songsGroups[indexPath.seciton - 1]. categoryName
headerTitle.title = musicCategoryName
}
As you see my code became magical by adding this cool -1 magical number. Which I replay don't love at all.
As an idea for sure I can try to combine my ADD NEW SONG BUTTON section (by adding some additional object) with songsGroups array and create NSArray for this purposes. Like in Objective-C as you remember. So then my datasource array will looks like this:
some NSArray = ["empty data for first cell", songsGroups[0], songsGroups[1]... etc]
So then there is no need to check any sections we can trust our array to build everything and even if I will add more empty data cells there is no need for me to handle my code via if block and adding tons of magical numbers.
But the issue I see here that we don't use explicit types of array and it's upset.
So maybe you know more beautiful solutions how to resolve my issue.
You can introduce a helper enum:
enum Section {
case empty
case songCategory(categoryName: String, songs: [String])
}
Your data source would then look something like this:
let datasource: [Section] = [.empty, .songCategory(categoryName: "Category1", songs: ["Song 1", "Song2"])]
So now you can use pattern matching to fill the table view:
let section = datasource[indexPath.section]
if case let .songCategory(categoryName, songs) = section {
headerTitle.title = categoryName
} else {
// this is a section for ADD NEW SONG BUTTON cell no need in header title as there is no data repression only static text on the cell.
}
I am not sure if I understand you right. But is seems to me that you want to display
1) something that lets the user add a new song by tapping a button, and
2) a table of songs, sectioned into groups.
If this is the case, why don’t you put the add new song button in the table header view, and all your song groups and songs in a 2-dim array used as your dataSource?
So the number of buttons on screen change with number of items in array from API.
I have a simple example, i have an array of integers and for each item in the array i am going to create a UIButton and add it to array of UIButton.
let array = [1,2,3,4]
var buttons: [UIButton] = []
for item in array {
let button = UIButton()
button.titleLabel?.text = "Button \(item)"
buttons.append(button)
}
print("Number of buttons: \(buttons.count)")
Based on your information you should not create a button for each item in the array you collect from an external API. Since you are using a collection view I would design a collection view cell with the appropriate properties. One of the properties should be a unique identifier. This standard collection view cell is the model for all your collection view cells, that represent your buttons.
Then use the collection view delegate method: collectionView(_:didSelectItemAt:) to react on a tap/press from the user. In this method the functionality that you use will be based on the unique identifier of your collection view cell.
There is no need to create a button in a collection view. The collection view already has all the functionality in its collection view item.
I´m using a table view to display different types of items. The view controller for the table is always the same, ItemsViewController.
I have a menu with buttons for each type of item. Depending on what button the user clicks, a specific array of items must be used to populate the table view.
My solution:
Every item has an typeId property. When a type button is clicked, the following method is called:
[self.itemController createItemListForId:buttonPressed.typeId];
where buttonPressed is, well, the pressed menu button.
This is the implementation for createItemListForId:
-(void)createItemListForId:(int)theId{
for (Item *item in self.masterItemList){
if(item.typeId == theId){
[self.itemList addObject:item];
}
}
}
The masterItemList is popluted with all the items at initialization.
My ItemsViewController uses the itemList to populate the cells.
The problem is that itemList is empty when the table view appears, so something not working with this method.
Any ideas on how to get this to work?
I've got a QNX Picker control that isn't displaying the selected values when there's only one item in the picker. For example:
import qnx.ui.picker.Picker;
var pick:Picker = new Picker();
var arr:Array = [{label: "hi!"}];
pick.dataProvider = new DataProvider([new DataProvider(arr)]);
pick.selectedIndices = [0];
addChild(pick);
The result is a blank picker. Maybe I'm doing something wrong. When there are 2 items in the arr Array, the picker actually shows the selected Indices.
How do I get the picker to display the selected item when there is only 1 item to choose from?
I'm using Burrito, with Playbook SDK 0.9.3.
Thanks in advanced!
I assume that you are going to populate the picker at some point in order to actually use it, so you could just use your existing array and add a blank entry:
var arr:Array = [{label: "hi!"}, {label: ""}];
and then pop the array to remove the blank item before you add new data.