Indexed TableViews not displaying after upgrade to MT 4.0 - ios

After upgrading to MT 4.0, my TableViews that previously were displaying indexes on the right hand border are no longer working. The tableview still displays in sections and works properly, but the index is not displaying.
I have these three methods defined in my UITableViewSource, and all three appear to be working:
public override string[] SectionIndexTitles(UITableView tableView)
public override int SectionFor(UITableView tableView, string Title, int atIndex)
public override string TitleForHeader(UITableView tableView, int section)
Is anyone else having this problem? Is this a bug with MT 4.0?

This is a known bug.
It appears that UITableView is not retaining the returned array, you can use
the following to work around this issue while we investigate it further:
NSArray array;
[Export ("sectionIndexTitlesForTableView:")]
public NSArray SectionTitles (UITableView tableview)
{
if (array == null) {
string[] titles = new string[RowsInSection(tableview, 0)];
for (int index = 0; index < titles.Length; index++)
titles[index] = index.ToString();
array = NSArray.FromStrings (titles);
}
return array;
}

This was showing to me just numbers (index for each item of the section 0 (like A letter of the index), so I found that must change this to:
NSArray array;
[Export ("sectionIndexTitlesForTableView:")]
public NSArray SectionTitles (UITableView tableview)
{
if (array == null)
{
array = NSArray.FromStrings (SectionIndexTitles(tableview));
}
return array;
}

To all people who don't get the workaround to work correctly:
For me it was because I left the MonoTouch override method SectionIndexTitles in there - as soon as I removed it (or in my case renamed it so it can be called from the workaround), it worked as described :)

Getting the same problem, but the above fix did not work, I am sure it is probably something simple that I am doing wrong. The below methods are part of a UITableViewSource. All working as it was before MT 4.0, however the textual Index is not appearing. Debug output listed below the code shows that SectionTitles is not being called. Any thoughts on how this differs from the solution above, and how to get it working? Happy to start a new thread on this, but thought that it might be useful to have more information on this question instead.
NSArray array;
[Export ("sectionIndexTitlesForTableView:")]
public NSArray SectionTitles(UITableView tableview)
{
Debug.WriteLine("SectionTitles");
if (array == null)
{
array = NSArray.FromStrings(SectionIndexTitles(tableview));
}
return array;
}
public override string[] SectionIndexTitles(UITableView tableView)
{
Debug.WriteLine("SectionIndexTitles");
var sectionIndexTitles = Root.Sections.Select(section => section.IndexTitle ?? string.Empty);
var applySectionIndexTitles = sectionIndexTitles.Any (sectionIndexTitle => !string.IsNullOrEmpty (sectionIndexTitle));
foreach (string s in sectionIndexTitles)
{
Debug.WriteLine(s);
}
Debug.WriteLine("applySectionIndexTitles = " + applySectionIndexTitles);
return applySectionIndexTitles ? sectionIndexTitles.ToArray () : null;
}
Debug output:
SectionIndexTitles
A
B
C
D
E
F
G
H
J
K
L
M
N
O
P
R
S
T
W
applySectionIndexTitles = True

Wow, the answers here are a extremely misleading. Where do I start?
First, why are the examples using a backing NSArray? Why not a string [] for the backing data? Just because the method returns a NSArray doesn't mean you have to back it with an NSArray. Yikes. Why would you use an NSArray unless you have to. You don't have to here.
Second, realistically, I always store my index titles in a backing string []. That is normal use I'd say. Why wouldn't you do that anyway? The answers here make it sounds like it's a special case or something where you have to store it. As far as I know you are always responsible for doing that anyway. And another example relying on the cells to get data... Why on earth? If you can't simply use an array then get a clue that your array is out of scope or something.
Also, some people mentioned to not override as you normally would. Ummm... I don't know about that. That completely contradicts all the monotouch code I've seen. I've seen a lot of examples do both and it makes sense. Look at some of the template UIViewController constructors. The internal calls that explicitly reference selectors will need the selector. Normally you wouldn't need one but in this case apparently something internal is broken referencing the selector. That is NOT a reason to ditch overriding it as you normally would. You still need to override it in case you have some external call that came from your own managed code. You should absolutely still override it. Unless you always explicitly referencing selectors in YOUR code... then keep it overriden.
Anyway, a lot of this is my general monotouch understanding and I could be wrong. I mean, I don't know... I'm seriously not trying to criticize. I just had to comment because it looks like to me there is A LOT of bad information in this thread and I'm hoping this post will help someone who might be getting misinformed.

Related

How can search a string array contains metod without loop

I have an array of view model. Now I want to check that view model array to contain a word within an array.
public IQueryable<CategorisedPostViewModel> GetRelatedPostbyCategories(string categories)
{
var ctries = categories.Split(',');
var result = GetAllCategoriedPost().**Where(p=>p.CategoryName.Contains(ctries)).**OrderByDescending(c => c.Published);
return result;
}
How can I search that bold portions without loop?
We may assume for simplicity,
p.categoryName="jerry,tom,ema"
and
ctries={"Gates","jerry","Jobs","ema"}
I want to check if any ctries is found on p.categoryName. Please help me. Thanks in advance.
To check if any category name is present in ctries try, Intersect
p.categoryName.Intersect(tries).Any()

expressin is not an integer constant expression

I am using switch case into my method like in screenshot
I already done with Enumeration but how can I directly pass int constant into case??
I googled it but I found it with Enumeration
Please help me with it
If that's all the functionality you want to achieve then you should write something like this:
if (index.row == value) {
// logic when it's that row
} else {
// default case
}
What you tried to do is simply not possible, see the two questions linked by Martin R in the comments.

Generating unique uibutton tags

I think this is impossible but I'm hoping someone knows a work around to use a unique int or string as a uibutton tag
Ideally I want something like this:
let uuid = NSUUID().UUIDString
myBTN.tag = uuid.toInt()!
It's frustrating swift only allows int as tags
If you'd like to assign a unique integer to the tag of the view as you've described you can do something like this:
myButton.tag = Int(arc4random())
That will give you a very random tag which is unlikely to collide.
This is almost certainly a poor solution to the broader context though. If adding a UUID is actually correct, consider subclassing UIButton and adding a unique identifier property instead of using the tag.
Consider, as #dimpiax suggests, storing references to your buttons as properties, most likely an array of buttons, rather than using identifiers and going back to find the related button later.
You can do a trick with a helper class and then, do it like this;
let uuid:Int = NSUUIDI.UUIDInt; // NSUUIDI() Not required here
myBTN.tag = uuid;
//Reverse (String value from tag)
println(NSUUIDI.UUIDStringFromInt(myBTN.tag));
Helper Class here;
//NSUUIDI.swift
class NSUUIDI:NSObject {
private static var _uUIDs:[String] = [String]();
class var UUIDInt:Int {
get {
let uUIDInt:Int = NSUUIDI._uUIDs.count;
NSUUIDI._uUIDs.append(NSUUID().UUIDString);
return uUIDInt;
}
}
class func UUIDStringFromInt(uUID:Int) -> String {
return (uUID < NSUUIDI._uUIDs.count) ? NSUUIDI._uUIDs[uUID]:"\(uUID)";
}
}

Filter array in a category/extension

For convenience, in a little experiment I am doing, I would like to extend Array to provide some app specific functionalities. This specific extension is not necessary best practice, but I am just curious about solving the Swift issues I am having.
Given a custom class Section, my extension (with partially extended closure) is:
extension Array {
func onlyFullSection() -> Array<Section> {
return self.filter {
(a:Section) -> Bool in
return a.isFullSection()
}
}
}
The error I get is: "T" is not a subtype of "Section".
I tried to fix it with all the sauces (changing types, casting, etc...) but still get similar errors.
This other variant:
extension Array {
func onlyFullSection() -> Array<Section> {
return (self as Array<Section>).filter {
(a:Section) -> Bool in
return a.isFullSection()
} as Array<Section>
}
throws: Cannot convert the expression's type 'Array<Section>' to type 'Array<Section>'
Any clue on what I am doing wrong? Thanks!
It is because you are extending T[] and not Section[]. That means that Int[] will also have your additional method. That might not be the best idea (since it will crash badly).
Swift currently does not allow you to extend a specialised generic type like Section[].
But if you really, really want to do it, here is one way to force a cast, use reinterpretCast, which Apple describes as follows
/// A brutal bit-cast of something to anything of the same size
func reinterpretCast<T, U>(x: T) -> U
You can use it like this:
extension Array {
func onlyFullSection() -> Section[] {
let sections : Section[] = reinterpretCast(self)
return sections.filter{ $0.isFullSection() }
}
}
But please don't.
The problem is that since the Array class is actually a generic Array<T>, you are extending Array<T>. And apparently you can't cast between generic types (i.e. <T> to <Section>), so I believe you'll have to make a new array and just push the appropriate objects into it.
17> extension Array {
18. func onlyFullSection() -> Array<Section> {
19. var ary = Array<Section>()
20. for s in self {
21. if (s as Section).isFullSection() {
22. ary.append(s as Section)
23. }
24. }
25. return ary
26. }
27. }
You could also create a helper method to convert between generic types for you, but in this instance that would just create an unnecessary temporary object.
Remember that the language is still heavily in flux so it's possible this will change. I think it's unlikely that we'll get the ability to cast between generic types, but I hope we'll at least be able to extend particular generics.

Javafx-2 tableview bindings with none text cells

I would like to show a series of financial transactions in a TableView.
Each Transaction consists of a Date, a Description and an Amount.
I can make this work using bindings if I treat all the cells as Text using the example shown in a reply to another question. This allows in cell editing which is my goal.
But I can't get it to work on the date and amount columns, I think I need a separate cell factory for each cell type and a possibly a separate updateItem method but I'm stuck.
Any pointers to an example or suggestions would be helpful.
You may want to check out the DataFX project at:
http://www.javafxdata.org/
and specifically the cell factories like:
http://www.javafxdata.org/javadoc/org/javafxdata/control/cell/TextFieldCellFactory.html
DataFX contains custom cell factories for several data types, tables, lists and tree views. Assuming that for example your amount has a double type, you could write something similar like that in a subclass of TableColum
(replace ??? by the class name of the class that represents a row in your table):
setCellFactory(TextFieldCellFactory.<???, Number>forTableColumn(new Callback<String,Number>(){
#Override
public Number call(String newValueStr) {
double newValue = Double.parseDouble(newValueStr);
return newValue;
}));
setOnEditCommit(new EventHandler<CellEditEvent<???, Number>>() {
#Override
public void handle(CellEditEvent<???, Number> t) {
double newValue = t.getNewValue().doubleValue();
// do something with the double value the user entered here
}
});
}
}
I hope that at least gives you some direction. I have left out Exception handling for clarity.

Resources