EDIT
I have a UIPickerview and I want do fill it up with data from my NSMutualArray. I have tested if something is in my array with NSLog and i get the data back. But it will not fill up my pickerviewer
I have this methods for my pickerviewer.
- (NSString *)pickView:(UIPickerView *)pickview titleForRow:(NSInteger)row forComponent:(NSInteger)component{
return [dataArray objectAtIndex:row];
}
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView{
return 1;// assuming a single spinning wheel of strings (not split into left/right for example)
}
-(NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component{
return [json count]; // the number of strings that your parser finds and adds to the array
}
To get my data out of my JSON I use these two methods. And i call the start function in my viewdidload.
-(void) getData:(NSData *) data{
NSError *error;
json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
}
-(void) start {
NSURL *url = [NSURL URLWithString:kGETUrl];
NSData *data = [NSData dataWithContentsOfURL:url];
[self getData:data];
}
I have also a button which hides and shows my UIPickerviewer.
-(IBAction)setPicker:(id)sender{
if (pickview.hidden == TRUE) {
[pickview setHidden:NO];
[pickview setDelegate:self];
[pickview setDataSource:self];
[pickview reloadAllComponents];
}else {
[pickview setHidden:YES];
[pickview setDelegate:self];
[pickview setDataSource:self];
[pickview reloadAllComponents];
}
}
I use this method for filling up my array.
-(void) fillArray{
dataArray = [[NSMutableArray alloc] init];
for (int i=0; i<[json count]; i++) {
NSDictionary *info = [json objectAtIndex:i];
[dataArray addObject:[info objectForKey:#"Use_naam"]];
}
NSLog(#"%#\n",dataArray);
}
And i call it in my viewdidload.
- (void)viewDidLoad
{
[super viewDidLoad];
[self start];
[self fillArray];
// Do any additional setup after loading the view, typically from a nib.
}
Anybody knows what I am doing wrong ?
When you see a number of question marks matching the expected number of rows it's usually the methods that returns the title or view for the rows that are missing.
This can either be because the UIPickerViews delegate is not set (you did that) or because the signature is not correct.
Your signature is off. It needs to be exactly:
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component;
^^^^
Most commonly people forget that you have to set the UIPickerView delegate and datasource.
Related
I am getting events from a Shared Google Calendar into my App using JSON. On some dates there are 2 or more events. As you can see here - the dates (found under {gd$when}, {startDate} are in a long format (2013-04-28T19:00:00.000+02:00).
I would need each section to be a date in the format dd-MM-yy. Then the cell.textLabel.Text would be the Title/$t, and the cell.detailTextLabel.Text would be the time (hh:mm) from gd$when/startTime. I would only want to show those that are equal to or after todays date.
I have played around with it, to match a tutorial on raywenderlich.com. My code right now looks like this, but I haven't yet implemented it into a tableviewcontroller
#define kBgQueue dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
#define googleURL [NSURL URLWithString: #"http://www.google.com/calendar/feeds/kao1d80fd2u5kh7268caop11o4%40group.calendar.google.com/public/full?alt=json"]
#import "ViewController.h"
#interface ViewController () {
IBOutlet UILabel* humanReadble;
IBOutlet UILabel* jsonSummary;
}
#end
#implementation ViewController
-(void)viewDidLoad
{
[super viewDidLoad];
dispatch_async(kBgQueue, ^{
NSData* data = [NSData dataWithContentsOfURL:googleURL];
[self performSelectorOnMainThread:#selector(fetchedData:) withObject:data waitUntilDone:YES];
});
}
- (void)fetchedData:(NSData *)responseData {
//parse out the JSON data
NSError* error;
NSDictionary* json = [NSJSONSerialization JSONObjectWithData:responseData options:kNilOptions error:&error];
NSArray* feed = [json valueForKeyPath:#"feed.entry"];
NSLog(#"feed: %#", feed);
for (int i=0; i<[feed count]; i++) {
NSDictionary* event = [feed objectAtIndex:i];
NSString* eventTitle = [event valueForKeyPath:#"title.$t"];
NSLog(#"Title: %#", eventTitle);
}
}
#end
If anybody can give a pointer - especially as to how I would create the sections from the date, it would be highly appreciated
Where as my suggestion says to you create the number of section as you get number of dates you get, and in each section you have to put number of events that would be the number of rows at each section. which you will declare at
-(NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
and after this put the view for each header like this-
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
headerView=[[UIView alloc] init];
headerView.tag=section+1000;
headerView.backgroundColor=[UIColor clearColor];
UILabel *labelInHeader=[[UILabel alloc] init];
labelInHeader.backgroundColor=[UIColor clearColor];
labelInHeader.adjustsFontSizeToFitWidth=YES;
labelInHeader.minimumScaleFactor=13.00;
labelInHeader.textColor=[UIColor blackColor];
labelInHeader.textAlignment=NSTextAlignmentCenter;
labelInHeader.font=[UIFont fontWithName:FONTCENTURYGOTHICBOLD size:20.0];
labelInHeader.frame=CGRectMake(30, 0, 229,47);
labelInHeader.lineBreakMode=NSLineBreakByWordWrapping;
labelInHeader.numberOfLines=2;
[headerView addSubview:labelInHeader];
return headerView;
}
Hope this helps.
I'm trying to delete a row when user swipes. I got this error driving me crazy. I've spent last three hours trying to figure out why. But, I have got no clue so far.
Here is my code to accomplish that.
in .h
#import <UIKit/UIKit.h>
#import "CustomCell.h"
#interface FollowersTableViewController : UITableViewController
#property (nonatomic,strong)NSMutableArray *arrayWithUser ;
#end
and in .m i have this code .
#import "FollowersTableViewController.h"
#implementation FollowersTableViewController
#synthesize arrayWithUser ;
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
-(void)viewDidLoad
{
[super viewDidLoad];
NSDictionary *dicUrlList= [NSDictionary dictionaryWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"Urls" ofType:#"plist"]];
NSString *baseURl = [dicUrlList objectForKey:#"urlWithUser"];
baseURl = [baseURl stringByAppendingFormat:#"getfollowers"];
NSURL *urlToGetFollowers = [NSURL URLWithString:baseURl];
NSURLRequest *request = [NSURLRequest requestWithURL:urlToGetFollowers];
NSError *error = nil ;
NSURLResponse *response = nil ;
NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
arrayWithUser = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:nil];
}
- (void)viewDidUnload
{
[super viewDidUnload];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [arrayWithUser count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *MyIdentifier = #"Cell";
CustomCell *customCell = (CustomCell *)[tableView dequeueReusableCellWithIdentifier:MyIdentifier];
if (customCell == nil)
{
customCell = [[CustomCell alloc] initWithFrame:CGRectMake(0, 0, 320, 50)] ;
}
NSDictionary *dicWithUser = [arrayWithUser objectAtIndex:indexPath.row];
NSString *photoUrl = [dicWithUser objectForKey:#"profilePhotoUrl"];
if(![photoUrl isEqualToString:#""])
[customCell.thumbnail setImageWithURL:[dicWithUser objectForKey:#"profilePhotoUrl"] placeholderImage:[UIImage imageNamed:#"placeholder.png"] ];
else
{
[customCell.thumbnail setImage:[UIImage imageNamed:#"placeholder.png"]];
}
customCell.titleLabel.text = [dicWithUser objectForKey:#"username"];
UIButton *buttonFollow = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[buttonFollow setTitle:#"Follow" forState:UIControlStateNormal];
CGRect frame = buttonFollow.frame ;
frame = CGRectMake(200, 10, 60, 30);
buttonFollow.frame = frame ;
buttonFollow.tag = indexPath.row ;
[buttonFollow addTarget:self action:#selector(followButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
customCell.accessoryView = buttonFollow ;
return customCell;
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 60 ;
}
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the specified item to be editable.
return YES;
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete) {
// Delete the row from the data source
[arrayWithUser removeObjectAtIndex:indexPath.row];
}
}
So far,I'm able to see delete button, but when i pressed it gives me this error
[__NSCFArray removeObjectAtIndex:]: mutating method sent to immutable object.
Since I've already used NSMutableArray, I've no idea, why I'm getting this error?
I've already try to clean project. It didn't make any difference.
Your Json call returning an NSArray. You can go to create a mutableCopy - so you're will be able to use the "removeAtIndex.." method.
NSArray *rData = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:nil];
arrayWithUser = [rData mutableCopy];
The assignment to arrayWithUser from the JSON call is returning an NSArray not an NSMutableArray in viewDidLoad. Fix that.
Actually, your array(arrayWithUser) is strongly pointing to the array return by the JSONObjectWithData, as you don't have the ownership of the returned array, you can't remove its object.
You better do one thing ,take ownership of that array.
arrayWithUser = [[NSMutableArray alloc]arrayByAddingObjectsFromArray:[NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:nil]];
Just replace below line
arrayWithUser = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:nil];
with
arrayWithUser = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
From Apple's documentation:
NSJSONReadingMutableContainers: Specifies that arrays and dictionaries are created as mutable objects.
NSJSONReadingMutableLeaves: Specifies that leaf strings in the JSON object graph are created as instances of NSMutableString.
You used in viwDidLoad
arrayWithUser = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:nil];
Lets try like this
NSMutableArray *userMutarr = [NSMutableArray alloc]initWithCapacity:3];
self.arrayWithUser = userMutarr;
[userMutarr release];
Then
self.arrayWithUser = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:nil];
I've got a UIPickerView object that lists stores based on either a listed "home" location or one's current location (using CLLocationManager). If the latter is implemented, I make a NSMutableURLRequest to my server to get the closest stores, then update a UIPickerView with the received list.
On occasion, (and oddly enough never when I'm at the "home" location), I will use the current location, I'll see the picker update the list, then the app immediately crashes.
My picker code is simple enough:
-(NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView{
return 1;
}
-(NSInteger) pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {
if (isHome) {
return [storesData count];
} else {
return [storesDataLoc count];
}
}
-(NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component {
if (isHome) {
return [[storesData objectAtIndex:row] objectForKey:#"STName"];
} else {
return [[storesDataLoc objectAtIndex:row] objectForKey:#"STName"];
}
}
One thought was that it was providing a second, more accurate reading and that I was releasing something that I may have already released. My CLLocationManager code is:
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error {
if (error.code == kCLErrorLocationUnknown) {
NSLog(#"Currently unable to retrieve location");
} else if (error.code == kCLErrorNetwork) {
NSLog(#"Network used to retrieve location is unavailable");
} else if (error.code == kCLErrorDenied) {
NSLog(#"Permission to retrieve location is denied");
[locMan stopUpdatingLocation];
[locMan release];
locMan = nil;
// revert segmented controller to Home position
storeSource.selectedSegmentIndex = 0;
}
if(loadstoresconnection!=nil){
[loadstoresconnection release];
}
networkView.hidden = TRUE;
isHome = TRUE;
}
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation {
if (newLocation.horizontalAccuracy >= 0) {
networkView.hidden = TRUE;
if (newLocation.horizontalAccuracy < 200) {
[locMan stopUpdatingLocation];
[locMan release];
locMan = nil;
}
//call for store list from this location
NSString *myString = [NSString stringWithFormat:#"http://mywebsite.com/?lat=%f&lng=%f",newLocation.coordinate.latitude,newLocation.coordinate.longitude];
NSURL *myURL = [[NSURL alloc] initWithString:[myString stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding]];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:myURL cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:60];
loadstoresconnection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
}
}
And the pertinent NSMutableURLRequest methods are:
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
[responseData release];
[connection release];
networkView.hidden = TRUE;
isHome = YES;
// [textView setString:#"Unable to fetch data"];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
int i;
NSArray *querydata;
networkView.hidden = TRUE;
[loadstoresconnection release];
if (storesDataLoc!=nil) {
[storesDataLoc release];
storesDataLoc = nil;
}
storesDataLoc = [[NSMutableArray alloc] init];
NSString *txt = [[[NSString alloc] initWithData:responseData encoding: NSASCIIStringEncoding] autorelease];
[responseData release];
// put data into variables.
querydata = [txt componentsSeparatedByString:#"<-sl->"];//break up data into data sections: 0 - number of deptsections and names, 1 - list of objects
NSArray *allstoreinfo;
for (i=0; i<[querydata count]; i++) {
allstoreinfo = [[querydata objectAtIndex:i] componentsSeparatedByString:#"<-as->"];
[storesDataLoc addObject:[[[NSMutableDictionary alloc] initWithObjectsAndKeys:[allstoreinfo objectAtIndex:0],#"STid",[allstoreinfo objectAtIndex:1],#"STName",[allstoreinfo objectAtIndex:2],#"STAddr",nil] autorelease]];
}
if ([querydata count]>0) {
[pickerView reload];
[pickerView selectRow:0 inComponent:0 animated:NO];
isHome = NO;
}
}
Im curious as to why I can see the picker being updated just before the crashes. Because this happens when I'm on the road, I'm suspecting it's an accuracy thing, and location manager is sending a second result, causing the crash. Any thoughts?
It appears I was trying to do too much of a shortcut. When the user hit the location button, it would turn on the LocationManager, which with every result would set up an NSURLConnection to my server. I was bring to handle all this in a single class, but with the multiple results the location manager would return, NSURLConnections seemed to be uncontrolled. I have since put each location manager result in its own class and everything is working honky dory. So, no issue with the picker - mainly a memory issue with location manager and nsurlconnections.
I have an action for searching in NSMutableArray with name searcharray, which is equal to array with which NSTableView are connected.And I wrote a method for adding items to TableView just by sending NSMutableArray to my method.
The problem is that after searching if I delete what I have typed in SearchField and SearchField is empty, the compiler doesn't feel that it's empty and my TableView getting empty too, but due my code it's have to be with data from searcharray.
Here is my code:
#import "myTableViewAppDelegate.h"
#implementation myTableViewAppDelegate
#synthesize window;
#synthesize searcharray;
-(void)addItems:(NSMutableArray *)ar{
array = ar;
[array retain];
[tableView reloadData];
}
- (int)numberOfRowsInTableView:(NSTableView *)tableView{
return (int)[array count];
}
- (id)tableView:(NSTableView *)tableView
objectValueForTableColumn:(NSTableColumn *)tableColumn
row:(int)row
{
return [array objectAtIndex:row];
}
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
// Insert code here to initialize your application
NSMutableArray *animals = [[NSMutableArray arrayWithObjects:#"Cat", #"Dog", #"Fish", #"Squirrel", #"Bear", #"Turtle", nil] retain];
NSLog(#"%#",animals);
searcharray = animals;
[self addItems:animals];
}
- (IBAction)search:(id)sender {
//NSLog(#"%#",searcharray);
NSString *filter = [[NSString alloc] initWithString:[search stringValue]];
NSMutableArray *result = [[NSMutableArray alloc] init];
if (filter != nil) {
for (NSString *item in searcharray) {
if ([item rangeOfString:[search stringValue]].location !=NSNotFound ) {
NSLog(#"Item %# contains %#",item,[search stringValue]);
[result addObject:item];
}
}
}
else{
result = searcharray;
}
NSLog(#"%#",result);
[self addItems:result];
[result release];
[filter release];
}
#end
Fixed it.
if (filter != nil || filter.length != 0)
I don't know why, but just checking variable equal to NULL wasn't enough....
I'm trying to access the array (data source) in my NSTableView to allow replacing the string that is in the row with a new string.The app consist of an NSTextfield for data entry and a button to add the entry so that it's displayed in the NSTableView. What I want is to be able to double click the NSTableView and replace what ever string is there with a new string, but I'm not sure how to do this.Here is my code so far
#implementation AppController
-(id)init
{
[super init];
[tableView setDataSource:self];
[tableView setDelegate:self];
array = [[NSMutableArray alloc ] init];
//NSLog(#"this is my delegate %#",[tableView delegate]);
return self;
}
-(IBAction)addItem:(id)sender
{
inputString = [textField stringValue];
[array addObject:inputString];
[tableView reloadData];
return;
}
- (int)numberOfRowsInTableView:(NSTableView *)aTableView
{
return [array count];
}
- (id) tableView:(NSTableView *)aTableView
objectValueForTableColumn:(NSTableColumn *)aTableColumn
row:(int)rowIndex
{
//NSLog(#"this is the object %#",[array objectAtIndex:rowIndex]);
return [array objectAtIndex:rowIndex];
}
-(IBAction) replaceItem:(id)sender
{
NSString *newString = [[NSString alloc]init];
NSLog(#"The selected row %d",[tableView selectedRow]);
newString = [textField stringValue];
[array addObject:newString];
[array replaceObjectAtIndex:[tableView selectedRow ] withObject: newString];
NSLog(#"this is the new sting %#",newString);
[tableView reloadData];
}
#end
I think you're looking for these datasource and delegate methods:
-tableView:setObjectValue:forTableColumn:row:
-tableView:shouldEditTableColumn:row: