UITableView inside UIScrollView partially invisible in Xcode 7.0.1? - ios

So I was working on an update to an Objective-C app coded with Xcode 6 but this time with Xcode 7.0.1 (and recently with Xcode 7.1) and I spotted a strange outcome with a specific part of my code.
First, I have to state that in the previous version of the app this part of the code was working just fine. So we are talking about a UIScrollView that contains a bunch of things among those we can find three UITableViews displaying three top lists.
Here's the problem : since working on Xcode 7.0.1 the UITableViews aren't displaying any infos anymore, but I wasn't able to find out why since the infos of each cells are actually here when you select one....
Has anyone encounter the same problem ?
Here is the code :
- (void)toppassionglob:(NSString *)topglobreceived {
//on retransforme le string des stats en data
NSData *toppassioner = [topglobreceived dataUsingEncoding:NSUTF8StringEncoding];
NSError *error3;
NSArray *jsonArray3 = [NSJSONSerialization JSONObjectWithData:toppassioner options:NSJSONReadingAllowFragments error:&error3];
if (jsonArray3) {
dispatch_async(dispatch_get_main_queue(), ^{
//on purge notre tableau
[toppassion removeAllObjects];
//puis on traite les infos
for (int i = 0; i < jsonArray3.count; i++)
{
NSDictionary *jsonElement = jsonArray3[i];
Games *newpassionner = [[Games alloc] init];
newpassionner.name = jsonElement[#"pseudo"];
newpassionner.score = jsonElement[#"nbvote"];
newpassionner.image = jsonElement[#"nbvotesoffline"];
[toppassion addObject:newpassionner];
}
//puis le remplissage des tops
[_toppassionnerglob reloadData];
});
}
That's for the call of infos (it works)
And then inside the cellForRowAtIndexPath: function :
RankCell *myCell = [tableView dequeueReusableCellWithIdentifier:#"RankCell"];
if (myCell == nil) {
myCell = [[RankCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"cell"];
}
Games *thisone = [toppassion objectAtIndex:indexPath.row];
myCell.textLabel.text = [NSString stringWithFormat:#"%ld", (long)indexPath.row+1];
myCell.textLabel.textColor = [UIColor purpleColor];
myCell.name.text = [NSString stringWithFormat:#"%#", thisone.name];
myCell.rank.text = [NSString stringWithFormat:#"%# votes, %# offline", [self separateur:thisone.score], [self separateur:thisone.image]];
}
Thanks for your answers in advance.
EDIT:
Here are what toplobreceived and jsonArray3 contains
topglobreceived = (__NSCFString *)#"[{\"pseudo\":\"Padadise\",\"nbvote\":\"7969\",\"nbvotesoffline\":\"364\"},{\"pseudo\":\"Roope\",\"nbvote\":\"5647\",\"nbvotesoffline\":\"0\"},{\"pseudo\":\"Spank78\",\"nbvote\":\"2696\",\"nbvotesoffline\":\"6\"},{\"pseudo\":\"All Ice\",\"nbvote\":\"680\",\"nbvotesoffline\":\"73\"},{\"pseudo\":\"NewPad\",\"nbvote\":\"73\",\"nbvotesoffline\":\"1\"},{\"pseudo\":\"Nell\",\"nbvote\":\"47\",\"nbvotesoffline\":\"0\"},{\"pseudo\":\"AppleFriend\",\"nbvote\":\"4\",\"nbvotesoffline\":\"0\"}]"
jsonArray3 = (__NSCFArray *) #"7 objects"
[0] __NSCFDictionary * 3 key/value pairs
[0] struct __lldb_autogen_nspair
key NSTaggedPointerString * #"pseudo"
value NSTaggedPointerString * #"Padadise"
[1] struct __lldb_autogen_nspair
key NSTaggedPointerString * #"nbvote"
value NSTaggedPointerString * #"7969"
[2] struct __lldb_autogen_nspair
key __NSCFString * #"nbvotesoffline"
value NSTaggedPointerString * #"364"
for jsonArray3 I give only the first object (not to be redondant)

So I figured it out !
In newer versions of Xcode, the initial properties of the cells (not the elements you design in your custom cell) have changed. One in particular is the background of the textfield of the cell that is now white as default or is placed in front of the custom elements of the dynamic cell.
To solve my problem I had to had this bit of code and everything worked as it should.
myCell.textLabel.backgroundColor = [UIColor clearColor];
That wasn't easy to find out...

Related

how to Display data get from JSON in View controller

I have idea how to display data in UITableViewController in cell by index.row but i don't have idea how to show data in viewController
for e.g.
when i use UITableViewController that time,
NSString *str = [NSString stringWithFormat:#"%#", [[self.data
objectAtIndex:indexPath.row ] valueForKey:#"profile_image"]]; // data
is my array
this code will get image from array and set it in particular cell with the help of index.row.
but when i am using UIViewController then how i should set data for particular view??
Please provide me your guidance for this issue that how can i set image form array to my ViewController as i set it in UITableViewController by objectAtIndex:indexPath.row .
Thanks
i asked the above question but i got answer myself after many research and defiantly with the help of my stackoverflow's intelligent friends.
so i like to post my answer.
my answer is if i take int value i and then i use it in my function then it look like below code..
[requestDynamic startWithCompletionHandler:^(FBSDKGraphRequestConnection *connection, id result, NSError *error) {
// Insert your code here
NSLog(#"%#",result);
self.arrData = nil;
self.arrData = [[NSMutableArray alloc]init];
self.arrData = [result[#"data"] mutableCopy];
int i =0;
// NSString *strImage1 = [NSString stringWithFormat:#"%#",[[self.arrData objectAtIndex:i]valueForKey:#"picture"]];
NSString *strComment =[NSString stringWithFormat:#"%#", [[self.arrData objectAtIndex:i ]valueForKey:#"message"]];
NSString *strLike = [NSString stringWithFormat:#"%#", [[[[self.arrData objectAtIndex:i]valueForKey:#"likes"]valueForKey:#"summary"]valueForKey:#"total_count"]];
NSString *strCommentCount = [NSString stringWithFormat:#"%#", [[[[self.arrData objectAtIndex:i]valueForKey:#"comments"]valueForKey:#"summary"]valueForKey:#"total_count"]];
CustomSocialView *imageView1 = [[CustomSocialView alloc] initWithFrame:CGRectMake(0, 0, width, height)];
[imageView1 setContentText:strComment like:strLike comment:strCommentCount];
may be this question and answer is silly for you all experienced people but it is very important for me and some others like me.
so i post answer as i got it.
Thank you

How to filter search within a set of letters in search bar so that each letter typed will reduce the results in objective -c

i have implemented a search bar that searching trough an array of countries(presented in a picker view), the problem is that the user need to type the full country name that it will find it and i want him to be able to type even one letter and it will show the first country that starts with that letter and if types another than it sorts even further etc etc.
Anyone have any ideas??
for(int x = 0; x < countryTable.count; x++){
NSString *countryName = [[countryTable objectAtIndex:x]objectForKey:#"name"];
if([searchedStr isEqualToString:countryName.lowercaseString]){
[self.picker selectRow:i inComponent:0 animated:YES];
flag.image = [UIImage imageNamed:[[countryTable objectAtIndex:i]objectForKey:#"flag"]];
}
}
There's a method on NSArray called filteredArrayUsingPredicate: and a method on NSString called hasPrefix:. Together they do what you need...
NSString *userInput = //... user input as lowercase string. don't call this countryName, its confusing
NSPredicate *p = [NSPredicate predicateWithBlock:^BOOL(id element, NSDictionary *bind) {
NSString countryName = [[element objectForKey:#"name"] lowercaseString];
return [countryName hasPrefix:userInput];
}];
NSArray *filteredCountries = [countryTable filteredArrayUsingPredicate:p];
If you're on iOS 8 or OS X Yosemite, you can do:
NSString *country = countryName.lowercaseString; //"england"
NSString *needle = #"engl";
if (![country containsString:needle]) {
NSLog(#"Country string does not contain part (or whole) of searched country");
} else {
NSLog(#"Found the country!");
}
Else, if on versions below iOS 8:
NSString *country = countryName.lowercaseString; //"england"
NSString *needle = #"engl";
if ([country rangeOfString:needle].location == NSNotFound) {
NSLog(#"Country string does not contain part (or whole) of searched country");
} else {
NSLog(#"Found the country!");
}
Lastly, just iterate through all possible countries and apply this to them all. There might exist more robust solutions out there (like danh's solution with some smaller modifications), but this is by far the easiest to start with.

Load array and display based on state of uiswitch

Im trying to develop an app that displays a random truth or dare type question, however the user has the ability to turn off truths or dares in option. I have successfully managed to get the app to display a random quote from a plist file from either the truth or dare array also i have managed to program two switch buttons in the user options view controller.
My problem is how would i go about displaying only a truth or dare or both if the user has turned on of the uiswitchs off?
- (IBAction)button:(id)sender
{
if (!self.plistArray)
{
NSString *path = [[NSBundle mainBundle] pathForResource:
#"data" ofType:#"plist"];
NSUserDefaults *defaults =[NSUserDefaults standardUserDefaults];
if ([[defaults objectForKey:#"truthonoff"] isEqualToString:#"YES"])
{
NSDictionary *plistDict = [[NSDictionary alloc] initWithContentsOfFile:path];
NSArray *plistArray1 = plistDict[#"truth"];
}
if ([[defaults objectForKey:#"dareonoff"] isEqualToString:#"YES"])
{
NSDictionary *plistDict2 = [[NSDictionary alloc] initWithContentsOfFile:path];
NSArray *plistArray2 = plistDict2[#"dare"];
}
self.plistArray = [[plistArray1 arrayByAddingObjectsFromArray:plistArray2] mutableCopy];
}
NSLog(#"%#", plistArray);
//check to see if array is empty and display message
if ([plistArray count] == 0)
{
self.text.text = #"array empty";
}
else
{
//display random quote from array
int randV = arc4random() % self.plistArray.count;
self.text.text = self.plistArray[randV];
[self.plistArray removeObjectAtIndex:randV];
}
}
That is my attempt however it will not run and i have the feeling it wont ddo the job i need.
Basicly i need it to display only truth if the user has selected that to true or only dare if that is selected or both if both are set to true.
EDIT
sorry the problem with the above code is the plist isnt being loaded and it is scipping straight to if array ==0 {
How do i ensure it loads the array and then checks which arrays to load from the plist file?
Any help is greatly appreciated
This is the code before i tried to add if statements. Im so confussed how best to do this
- (IBAction)shownext:(id)sender {
//load array and check then cycle through this untill array is empty. Array will add two arrays from plist file.
if (!self.plistArray) {
NSString *path = [[NSBundle mainBundle] pathForResource:
#"data" ofType:#"plist"];
NSDictionary *plistDict = [[NSDictionary alloc] initWithContentsOfFile:path];
NSArray * plistArray1 = plistDict[#"truth"];
NSDictionary *plistDict2 = [[NSDictionary alloc] initWithContentsOfFile:path];
NSArray *plistArray2 = plistDict2[#"dare"];
self.plistArray = [[plistArray1 arrayByAddingObjectsFromArray:plistArray2] mutableCopy];
}
NSLog(#"%#", plistArray);
//check to see if array is empty and display message
if ([plistArray count] == 0) {
self.text.text = #"array empty";
}
else {
//display random quote from array
int randV = arc4random() % self.plistArray.count;
self.text.text = self.plistArray[randV];
[self.plistArray removeObjectAtIndex:randV];
}
}
First, if you have a switch for truth and one for dare I hope you have something in place to deal with when the user turns both switches off and doesn't understand why they get nothing (trust me it will happen).
For the rest I'm not sure exactly how you app works but I will take a guess. I'm thinking you have a utility style app with the main UI in one view and then an info button that flips to a second view where the switches are. I'm also guessing that there is a button in the main view that retrieves a truth or dare string. My final assumption, based on your code above, is that when the user changes the state of a switch that writes a user default that you've use a #define to keep out spelling mistakes.
When your view loads you should load both arrays in case the user changes their mind in the middle of using your app and turns on both options or changes from one to the other. Depending on how many entries you have in each of those arrays you might consider creating a combined array as well to simplify things.
When the button is pressed you should then look at the defaults and see if you need to look at both arrays or just one (the below is pseudo code)
if(truth && dare) {
// if you have a combined array pick a random element from it.
// otherwise first randomly pick one of the arrays to pick from.
}
else if (truth) {
// get a random element from the truth array
}
else {
// get a random element from the dare array
}
Also, your current checks of the switch values will always return no unless you are doing extra work in the switch view controller. You should be using [defaults setBool:<UISwitch.isOn> forKey:<#definedKeyHere>] and [defaults boolForKey:<#definedKeyHere>].
It would really help to know what part isn't working. For one thing, it might help to store your flags as NSNumber objects instead of strings (could your string comparison be failing?). Then you could do something like:
if ([[defaults objectForKey:#"truthonoff"] boolValue])
Use a literal to add the actual NSNumber - #YES or #NO.
Consider changing your logic to something like:
VERIFY CODE - doing this freehand:
if (!self.plistArray)
{
self.plistArray = [NSMutableArray array];
NSString *path = [[NSBundle mainBundle] pathForResource:
#"data" ofType:#"plist"];
// why are you loading this twice?
NSDictionary *plistDict = [[NSDictionary alloc] initWithContentsOfFile:path];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if ([[defaults valueForKey:#"truthonoff"] boolValue])
{
[self.plistArray addObject:plistDict[#"truth"]];
}
if ([[defaults valueForKey:#"dareonoff"] boolValue])
{
[self.plistArray addObject:plistDict[#"dare"]];
}
}
I am assuming that your code to load the Plists is working. Verify all your keys match what's in the Plist. Set a breakpoint and verify.
Calling a method on a nil object is a no-op in Objective C. So, it'll happily ignore calls to nil objects without telling you. Verify you have what you think you have.
Also, here:
//display random quote from array
int randV = arc4random() % self.plistArray.count;
self.text.text = self.plistArray[randV];
[self.plistArray removeObjectAtIndex:randV];
Consider using arc4random_uniform(self.plistArray.count) as it avoids modulo bias in the generator.
Now, this just gives you say 0 or 1 if you have two elements. Are you sure the two dictionary keys, "truth" and "dare" actually point to arrays?
Ok, everything working to this point. Now, you have an array of ARRAYS! So you need to randomly pick a question array, and THEN randomly pick a question.
Something like:
//get random array
int randArrayIndex = arc4random_uniform(self.plistArray.count);
NSArray* questionArray = self.plistArray[randArrayIndex];
//get random question
int randQuestionIndex = arc4random_uniform([questionArray count]);
NSString* randomQuestion = questionArray[randQuestionIndex];
self.text.text = randomQuestion;
// remove question
[questionArray removeObjectAtIndex:randQuestionIndex];
Something like that anyway. Of course, assuming you are storing NSStrings in those Plist arrays.

Passing parameters makes the code run "slower"?

Background Information
Currently I'm setting the text for each UITableViewCell in my UITableView using the following code:
Scenario A:
cell.textLabel.attributedText = [news formattedSubject];
However, consider if I were to add a parameter for the formattedSubject definition, just a single integer parameter so the code is now:
Scenario B:
cell.textLabel.attributedText = [news formattedSubject:1];
The text in each table view cell is roughly 3-5 lines in length, and is read from an external source and parsed via JSON. Here's a diagram of the desired result, which is what happens in Scenario A:
Scenario A Flow Diagram:
Image A simply displays the default, empty UITableView that I get when the app is still loading the JSON data. After the app retrieves and parses this data, it then populates the data into the UITableView, which results in Image B. This is the desired (and expected) result.
However, if I add a parameter to formattedSubject, I instead get the flow diagram below:
Scenario B Flow Diagram:
Once again, Image A displays the default UITableView. However, it is what happens in Image B that is the problem. In Image B, the data has been parsed, but has not yet been formatted properly by formattedSubject, thus resulting in a single, horizontally-narrow, and lengthy row of unformatted text. After a fraction of a second, the app looks like Image C, the end result which displays the formatted data after it has been parsed.
My question:
The only change I made is the addition of a parameter to formattedSubject. That is, I changed -(NSAttributedString*)formattedSubject { to -(NSAttributedString*)formattedSubject:(int)state {. It doesn't matter that there is nothing within formattedSubject that actually uses the state integer, I'm still getting the results from Scenario B.
This change seems to make the code run more slowly. It creates a delay between when the data is parsed and when it is formatted and displayed in the UITableView. I'm curious as to why this is, and how I can fix/circumvent this issue.
Aside from being an aesthetics issue, what happens in Scenario B also interferes with my automatic loading of new data when the user reaches the end of the UITableView. Because of horizontally-narrowed rows of text, the last row of data will momentarily be displayed in the UITableView when it is first loaded, thus causing data to be retrieved twice upon app startup.
I am nowhere close to an expert in coding, and thus it makes absolutely no sense to me how simply adding a parameter to my NSAttributedString could create the aforementioned delay. I would be very appreciative if someone could:
Explain why this is happening, and
Offer a solution to resolve this issue.
Thank you very much for reading this, any and all comments/help is welcomed.
Edit 1: #Vijay-Apple-Dev.blogspot.com, #txulu
Here is my formattedSubject code:
-(NSAttributedString*)formattedSubject:(int)state {
if(formattedSubject!=nil) return formattedSubject;
NSDictionary *boldStyle = [[NSDictionary alloc] init];
if(state==1) {
boldStyle = #{NSFontAttributeName:[UIFont fontWithName:#"Helvetica-Bold" size:16.0],NSForegroundColorAttributeName:[UIColor colorWithRed:0.067 green:0.129 blue:0.216 alpha:1.0]};
}
else {
boldStyle = #{NSFontAttributeName:[UIFont fontWithName:#"Helvetica-Bold" size:16.0],NSForegroundColorAttributeName:[UIColor whiteColor]};
}
NSDictionary* normalStyle = #{NSFontAttributeName: [UIFont fontWithName:#"Helvetica" size:14.0]};
NSMutableAttributedString* articleAbstract = [[NSMutableAttributedString alloc] initWithString:subject];
[articleAbstract setAttributes:boldStyle range:NSMakeRange(0, subject.length)];
[articleAbstract appendAttributedString:[[NSAttributedString alloc] initWithString:#"\n"]];
int startIndex = [articleAbstract length];
NSTimeInterval _interval=[datestamp doubleValue];
NSDate *date = [NSDate dateWithTimeIntervalSince1970:_interval];
NSDateFormatter *_formatter=[[NSDateFormatter alloc]init];
[_formatter setDateFormat:#"MM/dd/yy"];
NSString* description = [NSString stringWithFormat:#"By %# on %#",author,[_formatter stringFromDate:date]];
[articleAbstract appendAttributedString:[[NSAttributedString alloc] initWithString: description]];
[articleAbstract setAttributes:normalStyle range:NSMakeRange(startIndex, articleAbstract.length - startIndex)];
formattedSubject = articleAbstract;
return formattedSubject;
}
Please note that as I said before, even if I don't actually use the state parameter, I still get the same results.
Here is my cellForRowAtIndexPath code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
News *news = newsArray[indexPath.row];
NSIndexPath *selectedIndexPath = [tableView indexPathForSelectedRow];
if([selectedIndexPath isEqual:indexPath]) {
cell.textLabel.attributedText = [news formattedSubject:1];
}
else {
cell.textLabel.attributedText = [news formattedSubject:0];
}
cell.textLabel.numberOfLines = 0;
cell.textLabel.lineBreakMode = NSLineBreakByWordWrapping;
UIView *selectedBackgroundViewForCell = [UIView new];
[selectedBackgroundViewForCell setBackgroundColor:[UIColor colorWithRed:0.169 green:0.322 blue:0.525 alpha:1.0]];
cell.selectedBackgroundView = selectedBackgroundViewForCell;
cell.textLabel.highlightedTextColor = [UIColor whiteColor];
if (indexPath.row == [newsArray count] - 1) {
[self parseJSON];
}
return cell;
}
Please let me know if I can post anything else that may help.
Edit 2:
I'm not exactly sure if there is a performance issue. Upon further testing, I am inclined to believe that in Scenario A, the app loads and formats the cell data before displaying it, while in Scenario B, the app loads the data, displays it in the UITableViewCell, and then formats it, which creates the problem I detailed above.
Some people have brought up the code in my parseJSON method, so I'm posting it here for reference. As you can see I do indeed implement multithreading in order to prevent the data loading from lagging the application.
-(void)parseJSON
{
loading.alpha = 1;
loading.image = [UIImage imageNamed:#"loading.png"];
activityIndicator.alpha = 1;
timer = [NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:#selector(checkLoading) userInfo:nil repeats:YES];
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul);
dispatch_async(queue, ^{
parseNumber = parseNumber + 1;
int offset = parseNumber*20-1;
NSString *URLString = [NSString stringWithFormat:#"http://feedurl.com/feed.php?offset=%d",offset];
NSURL *url=[NSURL URLWithString:URLString];
NSData *data=[NSData dataWithContentsOfURL:url];
NSError* error;
if(data!=nil) {
json = [NSJSONSerialization JSONObjectWithData:data options: NSJSONReadingMutableContainers error: &error];
for(NSDictionary *newsInfo in json) {
News *newsList = [[News alloc] init];
newsList.thread = newsInfo[#"thread"];
newsList.author = newsInfo[#"author"];
newsList.subject = newsInfo[#"subject"];
newsList.body= newsInfo[#"body"];
newsList.datestamp = newsInfo[#"datestamp"];
[jsonTemp addObject:newsList];
}
newsArray = jsonTemp;
}
dispatch_sync(dispatch_get_main_queue(), ^{
if(data!=nil) {
[newsTable reloadData];
}
else {
activityIndicator.alpha = 0;
loading.image = [UIImage imageNamed:#"error.png"];
[self startTimer];
}
});
});
}
Edit:
Okay, there's a difference when calling [news formattedSubject] instead of [news formattedSubject:1]. The first one is like doing news.formattedSubject, this is, access the formattedSubject property that returns the ivar immediately, pretty fast. The second one calls the more complex formattedSubject: method that executes the code you posted, slower.
Original:
Your code seems fine except for some minor details like:
NSDictionary *boldStyle = [[NSDictionary alloc] init];
not being necessary because you assign just afterwards:
boldStyle = #{NSFontAttributeName ...}
Also, what I guess could be causing your problem is:
if (indexPath.row == [newsArray count] - 1) {
[self parseJSON];
}
Calling this inside your cellForRowAtIndexPath: could be a severe performance problem. If this method does a lot of work and does not do it in a background it could cause the delays you mention. As a rule of thumb, you should never do network/data processing in the main thread (cellForRowAtIndexPath will always be called in that thread by the system).
You says like below
"The text in each table view cell is roughly 3-5 lines in length, and is read from an external source and parsed via JSON. Here's a diagram of the desired result, which is what happens in Scenario A:"
I assume that you are reading data from
1.Local Core data Database
or
2.Web server's database.
For case 1, you should use NSFetchedResultsController, follow up this tutorial
https://developer.apple.com/library/ios/documentation/CoreData/Reference/NSFetchedResultsController_Class/Reference/Reference.html
http://www.raywenderlich.com/999/core-data-tutorial-for-ios-how-to-use-nsfetchedresultscontroller
For case 2 you should do in background thread,and update it by Main thread in tableview, when it is available, follow up this tutorial
How to load JSON asynchronously (iOS)

NSDictionary App Crash

Trying to read a plist and change my font color depending on the option that was selected in the following settings bundle.
The following is how I am trying to accomplish it:
NSString *path = #"/var/mobile/Library/Preferences/NCNotes.plist";
NSDictionary *dict = [[NSDictionary alloc] initWithContentsOfFile:path];
fontSize = [[dict objectForKey:#"slideSwitched"] floatValue];
if ([[dict objectForKey:#"noteColor"] valueForKey:#"Purple"]) {
noteView.textColor = [UIColor purpleColor];
} else {
noteView.textColor = [UIColor blackColor];
}
Any ideas why this is why my app is crashing? How do I read the values and change the color depending on what was selected?
It appears that the top level of your plist is an array, not a dictionary, because at the top it says "Item 1" where all of your content is within that. So you have a dictionary within an array. So you can change your code like this:
NSString *path = #"/var/mobile/Library/Preferences/NCNotes.plist";
NSArray *array = [[NSArray alloc] initWithContentsOfFile:path];
NSDictionary *dict = array[0];
You could also change the structure of your plist so that you have a dictionary as the root instead of an array.
Also, keys are supposed to be on the left-hand side and their values on the right-hand side, so I don't see a key "noteColor". You have a key "key" with a value "noteColor", so you'll need to make that correction. I'm also not seeing a "slideSwitched" key, though it might just be outside the bounds of your screenshot.
Also the following won't work:
[[dict objectForKey:#"noteColor"] valueForKey:#"Purple"]
Whatever you get from [dict objectForKey:#"noteColor"] isn't going to be a dictionary, so calling valueForKey: on that isn't going to give you what you want.
simply you should do this with document directory
NSString *contentPath=[[NSBundle mainBundle] pathForResource:#"PLIST_FILE_NAME" ofType:#"plist"];
NSDictionary *dictionary=[NSDictionary dictionaryWithContentsOfFile:contentPath];
write your logic after this, wait a minute , its seems like you dont have a key "noteColor" also. check your plist
Here is some example code documented up the wazoo. Hopefully it will help you understand how these plists and dictionaries work. Everything will be based on your plist file (which could definitely be improved upon, but that's up to you as I don't know your specific situation).
Your question is "How do I find color based on user selection?" I will assume you get the user selection as an int. Something like "User selected 7".
//Load your plist dictionary
NSString *path = #"/var/mobile/Library/Preferences/NCNotes.plist";
NSDictionary *dict = [[NSDictionary alloc] initWithContentsOfFile:path];
//Get the array of validValues and the array of validTitles
NSArray *valuesArray = [dict objectForKey:#"validValues"];
NSArray *titlesArray = [dict objectForKey:#"validTitles"];
//Now get the user selected index from the validValues array
int arraySelection = -1;
for(int i = 0; i < [valuesArray count]; i++)
{
NSNumber *number = [valuesArray objectAtIndex:i];
if([number intValue] == userSelectedInput)
{
arraySelection = i;
break;
}
}
if(arraySelection == -1)
{
//Not found in array
return;
}
//Now with that index get the title of the object that the user selected
NSString *userSelectedTitle = [titlesArray objectAtIndex:arraySelection];
//Now do your checking on what the user selected based on that:
if([userSelectedTitle isEqualToString:#"Purple"])
...
You could boil this down quite a bit. Currently your validValues array is completely useless. If it were out of order or missing numbers then it would be needed, but straight counting can be achieved by the validTitles array.

Resources