So I've been trying this for a while now and it is completely frustrating me but here is a brief summary of what I am trying to do. I have a LocationTableViewController with a plus button on the top right to add new locations to the table view. When that happens, I enter the LocationEditViewController where I can enter the name of the location I want to add. After adding my text and hitting the save location button I want the code to bring me back to the LocationTableViewController and there in my table I see my newly added location. Posted below is the code of the two view controllers. Hopefully you guys can help me thanks a ton!!
#import <UIKit/UIKit.h>
#import "Location.h"
#import "User.h"
#interface LocationEditViewController : UIViewController <UITextFieldDelegate>
#property (strong, nonatomic) Location *location;
#property (strong, nonatomic) User *user;
#property (strong, nonatomic) UITextField *locationNameField;
- (void)saveLocation:(id) sender;
#end
#import "LocationEditViewController.h"
#interface LocationEditViewController ()
#end
#implementation LocationEditViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
self.title = #"Edit";
self.location = [[Location alloc] init];
self.user = [[User alloc] init];
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
UILabel *locationLabel = [[UILabel alloc] init];
locationLabel.frame = CGRectMake(20,15,50,30);
locationLabel.text = #"Name:";
[self.view addSubview:locationLabel];
self.locationNameField = [[UITextField alloc] init];
self.locationNameField.frame = CGRectMake(15,50,290,30);
self.locationNameField.borderStyle = UITextBorderStyleBezel;
self.locationNameField.keyboardType = UIKeyboardTypeDefault;
self.locationNameField.delegate = self;
[self.view addSubview:self.locationNameField];
UIButton *saveLocationButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
saveLocationButton.frame = CGRectMake(15,400,290,50);
[saveLocationButton setTitle:#"Save Location" forState:UIControlStateNormal];
[saveLocationButton addTarget:self action:#selector(saveLocation:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:saveLocationButton];
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
[textField resignFirstResponder];
return YES;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)saveLocation:(id)sender {
self.location.name = self.locationNameField.text;
NSMutableArray *tempArray = [[NSMutableArray alloc] initWithArray:self.user.createdLocations];
[tempArray addObject:self.location];
self.user.createdLocations = [[NSArray alloc] initWithArray:tempArray];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Location Added"
message:#"This location is now accessable in the locations tab"
delegate:nil
cancelButtonTitle:#"Ok"
otherButtonTitles:nil];
[alert show];
[self.tabBarController.tabBar.items[1] setBadgeValue:[NSString stringWithFormat:#"%i",self.user.createdLocations.count]];
[self dismissViewControllerAnimated:YES completion:^{
[[NSNotificationCenter defaultCenter] postNotificationName:#"somethingAddedNotification" object:nil];
}];
}
/*
#pragma mark - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/
#end
Here is the LocationTableViewController code:
#import <UIKit/UIKit.h>
#import "User.h"
#interface LocationTableViewController : UITableViewController
#property (strong, nonatomic) NSArray *locations;
#property (strong, nonatomic) User *user;
#property (strong, nonatomic) id _observer;
- (void) addLocationPressed;
#end
#import "LocationTableViewController.h"
#import "LocationEditViewController.h"
#import "LocationViewController.h"
#interface LocationTableViewController ()
#end
#implementation LocationTableViewController
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
self.title = #"Locations";
self.user = [[User alloc] init];
UIBarButtonItem *addLocationButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:#selector(addLocationPressed)];
self.navigationItem.rightBarButtonItem = addLocationButton;
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
//Location *loc = [[Location alloc] init];
//self.user.createdLocations = #[loc];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
- (void) addLocationPressed
{
LocationEditViewController *locationEditVC = [[LocationEditViewController alloc] init];
[self presentViewController:locationEditVC animated:YES completion:nil];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.user.createdLocations.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell"];
if(cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"Cell"];
}
cell.textLabel.text = [self.user.createdLocations[indexPath.row] name];
NSLog(#"%#", [self.user.createdLocations[indexPath.row] name]);
return cell;
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
LocationViewController *locationVC = [[LocationViewController alloc] init];
locationVC.location = self.user.createdLocations[indexPath.row];
[self.navigationController pushViewController:locationVC animated:YES];
}
- (void)viewWillAppear:(BOOL)animated {
__observer = [[NSNotificationCenter defaultCenter] addObserverForName:#"somethingAddedNotification"
object:nil
queue:nil
usingBlock:^(NSNotification *notification)
{
[self.tableView reloadData];
}];
}
- (void)viewWillDisappear:(BOOL)animated {
[[NSNotificationCenter defaultCenter] removeObserver:__observer];
}
For additional information here is the user class where I am getting the array
#import <Foundation/Foundation.h>
#import "Location.h"
#interface User : NSObject
#property (strong, nonatomic) Location *profilePhoto;
#property (strong, nonatomic) NSString *location;
#property (strong, nonatomic) NSArray *createdLocations;
-(id) initWithTitle: (Location *) aLoc
detail: (NSString *) aDet
filename: (NSArray *) aLocList;
//-(id)initWithJSON;
//+(NSString *)getPathToArchive;
//+(User *)getUser;
//+(void)saveUser:(User *)aUser;
#end
#import "User.h"
#import "Location.h"
#implementation User
- (id)init;
{
self = [self initWithTitle: [[Location alloc] init]
detail: #"Temp"
filename: [[NSArray alloc] init]];
return self;
}
-(id) initWithTitle: (Location *) aLoc
detail: (NSString *) aDet
filename: (NSArray *) aLocList
{
self = [super init];
if (self) {
self.profilePhoto = aLoc;
self.location = aDet;
self.createdLocations = aLocList;
}
return self;
}
#end
and the Locations class if necessary
#import <Foundation/Foundation.h>
#interface Location : NSObject
#property (strong, nonatomic) NSString *name;
#property (strong, nonatomic) NSString *detail;
#property (strong, nonatomic) NSString *filename;
#property (strong, nonatomic) NSString *thumbnail;
-(id) initWithTitle: (NSString *) aTitle
detail: (NSString *) aDetail
filename: (NSString *) aFilename
thumbnail: (NSString *) aThumbnail;
#end
#import "Location.h"
#implementation Location
-(id)init
{
self = [self initWithTitle:#"Title"
detail:#"Detail"
filename:#"placeholder.jpg"
thumbnail:#"placeholder.jpg"];
return self;
}
-(id)initWithTitle:(NSString *)aTitle
detail:(NSString *)aDetail
filename:(NSString *)aFilename
thumbnail:(NSString *)aThumbnail
{
self = [super init];
if (self) {
self.name = aTitle;
self.detail = aDetail;
self.filename = aFilename;
self.thumbnail = aThumbnail;
}
return self;
}
#end
Hopefully you guys can help me! Thanks again!!!
Have you set a breakpoint on...
[self.tableView reloadData];
...in your observer block? Does it get hit? Separately, Drew Crawford is wary of that API you are using (http://sealedabstract.com/code/nsnotificationcenter-with-blocks-considered-harmful/).
Like the comment said, this is definitely a problem, and may in fact be the root cause. You must use the __weak reference inside the block or else NSNotificationCenter owns a strong reference to self and self owns a strong reference to NSNotificationCenter, and you have a retain cycle.
- (void)viewWillAppear:(BOOL)animated {
__weak LocationTableViewController *weakSelf = self;
__observer = [[NSNotificationCenter defaultCenter] addObserverForName:#"somethingAddedNotification"
object:nil
queue:nil
usingBlock:^(NSNotification *notification)
{
[weakSelf.tableView reloadData];
}];
}
Related
When a user taps a cell, I want itemURL to be set to that cells "Item URL" property. Once it does this, it should then send over the itemURL in prepareForSegue over to WebViewController, as I've attempted to do. When I have WebViewController NSLog the itemURL property however, it comes up as null. How can I make sure the value is sent over properly?
MatchCenterViewController.h:
#import <UIKit/UIKit.h>
#import <Parse/Parse.h>
#import "AsyncImageView.h"
#import "SearchViewController.h"
#import "WebViewController.h"
#interface MatchCenterViewController : UIViewController <UITableViewDataSource>
#property (nonatomic) IBOutlet NSString *itemSearch;
#property (nonatomic, strong) NSArray *imageURLs;
#property (strong, nonatomic) NSString *matchingCategoryCondition;
#property (strong, nonatomic) NSString *matchingCategoryLocation;
#property (strong, nonatomic) NSNumber *matchingCategoryMaxPrice;
#property (strong, nonatomic) NSNumber *matchingCategoryMinPrice;
#property (strong, nonatomic) NSArray *matchCenterArray;
#property (strong, nonatomic) NSString *searchTerm;
#property (strong, nonatomic) NSURL *itemURL;
#end
MatchCenterViewController.m:
#import "MatchCenterViewController.h"
#import <UIKit/UIKit.h>
#interface MatchCenterViewController () <UITableViewDataSource, UITableViewDelegate>
#property (nonatomic, strong) UITableView *matchCenter;
#end
#implementation MatchCenterViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.matchCenter = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewCellStyleSubtitle];
self.matchCenter.frame = CGRectMake(0,50,320,self.view.frame.size.height-100);
_matchCenter.dataSource = self;
_matchCenter.delegate = self;
[self.view addSubview:self.matchCenter];
_matchCenterArray = [[NSArray alloc] init];
}
- (void)viewDidAppear:(BOOL)animated
{
self.matchCenterArray = [[NSArray alloc] init];
[PFCloud callFunctionInBackground:#"MatchCenter"
withParameters:#{
#"test": #"Hi",
}
block:^(NSArray *result, NSError *error) {
if (!error) {
_matchCenterArray = result;
[_matchCenter reloadData];
NSLog(#"Result: '%#'", result);
}
}];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return _matchCenterArray.count;
}
//the part where i setup sections and the deleting of said sections
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
return 21.0f;
}
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
UIView *headerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 21)];
headerView.backgroundColor = [UIColor lightGrayColor];
_searchTerm = [[[[_matchCenterArray objectAtIndex:section] objectForKey:#"Top 3"] objectAtIndex:3]objectForKey:#"Search Term"];
UILabel *headerLabel = [[UILabel alloc] initWithFrame:CGRectMake(8, 0, 250, 21)];
headerLabel.text = [NSString stringWithFormat:#"%#", _searchTerm];
headerLabel.font = [UIFont boldSystemFontOfSize:[UIFont systemFontSize]];
headerLabel.textColor = [UIColor whiteColor];
headerLabel.backgroundColor = [UIColor lightGrayColor];
[headerView addSubview:headerLabel];
UIButton *deleteButton = [UIButton buttonWithType:UIButtonTypeCustom];
deleteButton.tag = section;
deleteButton.frame = CGRectMake(300, 2, 17, 17);
[deleteButton setImage:[UIImage imageNamed:#"xbutton.png"] forState:UIControlStateNormal];
[deleteButton addTarget:self action:#selector(deleteButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
[headerView addSubview:deleteButton];
return headerView;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 3;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// Initialize cell
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (!cell) {
// if no cell could be dequeued create a new one
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
// No cell seperators = clean design
tableView.separatorColor = [UIColor clearColor];
// title of the item
cell.textLabel.text = _matchCenterArray[indexPath.section][#"Top 3"][indexPath.row][#"Title"];
cell.textLabel.font = [UIFont boldSystemFontOfSize:14];
// price of the item
cell.detailTextLabel.text = [NSString stringWithFormat:#"$%#", _matchCenterArray[indexPath.section][#"Top 3"][indexPath.row][#"Price"]];
cell.detailTextLabel.textColor = [UIColor colorWithRed:0/255.0f green:127/255.0f blue:31/255.0f alpha:1.0f];
// image of the item
NSData *imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:_matchCenterArray[indexPath.section][#"Top 3"][indexPath.row][#"Image URL"]]];
[[cell imageView] setImage:[UIImage imageWithData:imageData]];
return cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 65;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSURL *itemURL = _matchCenterArray[indexPath.section][#"Top 3"][indexPath.row][#"Item URL"];
// NSLog(#"The url is: '%#'", itemURL);
[self performSegueWithIdentifier:#"WebViewSegue" sender:self];
}
- (void)deleteButtonPressed:(id)sender
{
// links button
UIButton *deleteButton = (UIButton *)sender;
// Define the sections title
NSString *sectionName = _searchTerm = [[[[_matchCenterArray objectAtIndex:deleteButton.tag] objectForKey:#"Top 3"] objectAtIndex:3]objectForKey:#"Search Term"];
// Run delete function with respective section header as parameter
[PFCloud callFunctionInBackground:#"deleteFromMatchCenter"
withParameters:
#{#"searchTerm": sectionName,}
block:^(NSDictionary *result, NSError *error) {
if (!error) {
[PFCloud callFunctionInBackground:#"MatchCenter"
withParameters:#{
#"test": #"Hi",
}
block:^(NSArray *result, NSError *error) {
if (!error) {
_matchCenterArray = result;
[_matchCenter reloadData];
NSLog(#"Result: '%#'", result);
}
}];
}
}];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
WebViewController *controller = (WebViewController *) segue.destinationViewController;
controller.itemURL = self.itemURL;
}
#end
WebViewController.h:
#import <UIKit/UIKit.h>
#import "MatchCenterViewController.h"
#interface WebViewController : UIViewController <UIWebViewDelegate>
#property (strong, nonatomic) NSURL *itemURL;
#property (weak, nonatomic) IBOutlet UIWebView *myWebView;
#end
WebViewController.m:
#import "WebViewController.h"
#interface WebViewController ()
#end
#implementation WebViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(#"The url is: '%#'", _itemURL);
// _myWebView=[[UIWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 460)];
// _myWebView.delegate=self;
// [self.view addSubview:_myWebView];
self.myWebView.delegate = self;
//////////
NSURLRequest *request = [NSURLRequest requestWithURL:_itemURL];
//4
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
//5
[NSURLConnection sendAsynchronousRequest:request queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *error)
{
if ([data length] > 0 && error == nil) [self.myWebView loadRequest:request];
else if (error != nil) NSLog(#"Error: %#", error);
}];
[self.myWebView setScalesPageToFit:YES];
//////
//[self.myWebView loadRequest:request];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
/*
#pragma mark - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/
#end
In your didSelectRowForIndexPath: instead of
NSURL *itemURL = _matchCenterArray[indexPath.section][#"Top 3"][indexPath.row][#"Item URL"];
use
self.itemURL = _matchCenterArray[indexPath.section][#"Top 3"][indexPath.row][#"Item URL"];
I've programmatically created a UITableView within my MatchCenterViewController, however it doesn't seem to populate with the JSON data being returned by my cloud code function. It simply shows a blank View Controller. MatchCenterViewController is a ViewController embedded within a Navigation View Controller.
MatchCenterViewController.h:
#import <UIKit/UIKit.h>
#import <Parse/Parse.h>
#import "AsyncImageView.h"
#import "SearchViewController.h"
#interface MatchCenterViewController : UIViewController <UITableViewDataSource>
#property (nonatomic) IBOutlet NSString *itemSearch;
#property (nonatomic, strong) NSArray *imageURLs;
#property (strong, nonatomic) NSString *matchingCategoryCondition;
#property (strong, nonatomic) NSString *matchingCategoryLocation;
#property (strong, nonatomic) NSNumber *matchingCategoryMaxPrice;
#property (strong, nonatomic) NSNumber *matchingCategoryMinPrice;
#property (strong, nonatomic) NSArray *matchCenterArray;
#end
MatchCenterViewController.m:
#import "MatchCenterViewController.h"
#import <UIKit/UIKit.h>
#interface MatchCenterViewController () <UITableViewDataSource, UITableViewDelegate>
#property (nonatomic, strong) UITableView *matchCenter;
#end
#implementation MatchCenterViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
self.matchCenter = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStylePlain];
_matchCenter.dataSource = self;
_matchCenter.delegate = self;
[self.view addSubview:self.matchCenter];
}
return self;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 3;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [_matchCenter dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
NSDictionary *matchCenterDictionary= [self.matchCenterArray objectAtIndex:indexPath.row];
cell.textLabel.text = [matchCenterDictionary objectForKey:#"Title"];// title of the first object
// if([matchCenterDictionary objectForKey:#"Price"] != NULL)
// {
// cell.detailTextLabel.text = [NSString stringWithFormat:#"$%#",[matchCenterDictionary objectForKey:#"Price"]];
// }
return cell;
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.matchCenterArray = [[NSArray alloc] init];
}
- (void)viewDidAppear:(BOOL)animated
{
self.matchCenterArray = [[NSArray alloc] init];
[PFCloud callFunctionInBackground:#"MatchCenterTest"
withParameters:#{
#"test": #"Hi",
}
block:^(NSDictionary *result, NSError *error) {
if (!error) {
self.matchCenterArray = [result objectForKey:#"Top 3"];
dispatch_async(dispatch_get_main_queue(), ^{
[_matchCenter reloadData];
});
NSLog(#"Test Result: '%#'", result);
}
}];
}
#end
How do you create this viewController? If you don't use [[MatchCenterViewController alloc] initWithNibName:... bundle:...] the table creation won't be called. This might happen because you have the viewController in a storyBoard, in this case initWithCoder: would be the method to overwrite.
I would recommend to move this code to viewDidLoad, which will be called regardless how the viewController was created . E.g.:
- (void)viewDidLoad {
[super viewDidLoad];
self.matchCenter = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStylePlain];
_matchCenter.dataSource = self;
_matchCenter.delegate = self;
[self.view addSubview:self.matchCenter];
self.matchCenterArray = [[NSArray alloc] init];
}
I am creating an iOS app. Since I am a beginner, I started with checking out some tutorials.
I started with creating an app with a Table View. The cells are dynamically filled through a database connection. This works fine.
However now I'm trying to define a push segue that opens a detail view for the cells. These also have to become filled dynamically with data. To achieve this, I started going through this tutorial and got it working up to "Passing Data Using Segue". In that step, you have to assign an identifier to your segue and fill in the prepareForSegue:sender: method.
I believe the implementation of my method causes the above error, because it isn't doing what it's supposed to. Looking up the error did not provide me with (understandable) answers since I fail to see how this problem has arisen.
Could someone please take a look at my code? Thanks in advance.
Main.storyboard:
In case you might be wondering, I did add an identifier to my segue, named showEventDetails.
EventsTableViewController.h
#import <UIKit/UIKit.h>
#import <sqlite3.h>
#interface EventsTableViewController : UITableViewController {
NSMutableArray *EventsArray;
sqlite3 *db;
}
#property (nonatomic, retain) NSMutableArray *EventsArray;
#property (nonatomic, strong) IBOutlet UITableView *eventTable;
-(NSMutableArray *) EventList;
#end
EventsTableViewController.m
#import "EventsTableViewController.h"
#import "TableCellViewController.h"
#import "Event.h"
#import <sqlite3.h>
#implementation EventsTableViewController
#synthesize EventsArray;
#synthesize eventTable;
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)didReceiveMemoryWarning
{
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[self EventList];
[super viewDidLoad];
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
}
- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
//Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
//Return the number of rows in the section.
return [self.EventsArray count];
}
- (NSMutableArray *) EventList
{
EventsArray = [[NSMutableArray alloc] initWithCapacity:10];
#try {
NSFileManager *fileMgr = [NSFileManager defaultManager];
NSString *dbPath = [[[NSBundle mainBundle] resourcePath]stringByAppendingPathComponent:#"eventsDb.sqlite"];
BOOL success = [fileMgr fileExistsAtPath:dbPath];
if(!success) {
NSLog(#"Cannot locate database file '%#'.", dbPath);
}
if (!(sqlite3_open([dbPath UTF8String], &db) == SQLITE_OK)) {
NSLog(#"An error has occured: %s", sqlite3_errmsg(db));
}
const char *sql = "SELECT * FROM events";
sqlite3_stmt *sqlStatement;
if(sqlite3_prepare(db, sql, -1, &sqlStatement, NULL) != SQLITE_OK) {
NSLog(#"Problem with prepare statement: %s", sqlite3_errmsg(db));
}
else {
while (sqlite3_step(sqlStatement) == SQLITE_ROW) {
Event *event = [[Event alloc] init];
event.name = [NSString stringWithUTF8String:(char *) sqlite3_column_text(sqlStatement, 1)];
event.date = [NSString stringWithUTF8String:(char *) sqlite3_column_text(sqlStatement, 2)];
event.starttime = [NSString stringWithUTF8String:(char *) sqlite3_column_text(sqlStatement, 3)];
event.endtime = [NSString stringWithUTF8String:(char *) sqlite3_column_text(sqlStatement, 4)];
event.location = [NSString stringWithUTF8String:(char *) sqlite3_column_text(sqlStatement, 5)];
event.description = [NSString stringWithUTF8String:(char *) sqlite3_column_text(sqlStatement, 6)];
event.favourite = sqlite3_column_int(sqlStatement, 7);
[EventsArray addObject:event];
event = nil;
}
}
sqlite3_finalize(sqlStatement);
}
#catch (NSException *exception) {
NSLog(#"Problem with prepare statement: %s", sqlite3_errmsg(db));
}
#finally {
sqlite3_close(db);
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"EventCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
int rowCount = indexPath.row;
Event *event = [self.EventsArray objectAtIndex:rowCount];
cell.textLabel.text = event.name;
cell.detailTextLabel.text= event.description;
return cell;
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"showEventDetails"]) {
NSIndexPath *indexPath = [self.eventTable indexPathForSelectedRow];
TableCellViewController *destViewController = segue.destinationViewController;
destViewController.eventName = [EventsArray objectAtIndex:indexPath.row];
}
}
- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath
{
}
#end
TableCellViewController.h
#import <UIKit/UIKit.h>
#interface TableCellViewController : UIViewController
#property(nonatomic, copy) NSString *eventName;
#property(nonatomic, strong) IBOutlet UILabel * eventNameLabel;
#property(nonatomic, copy) NSString *eventDate;
#property(nonatomic, strong) IBOutlet UILabel * eventDateLabel;
#property(nonatomic, copy) NSString *eventStarttime;
#property(nonatomic, strong) IBOutlet UILabel * eventStarttimeLabel;
#property(nonatomic, copy) NSString *eventEndtime;
#property(nonatomic, strong) IBOutlet UILabel * eventEndtimeLabel;
#property(nonatomic, copy) NSString *eventLocation;
#property(nonatomic, strong) IBOutlet UILabel * eventLocationLabel;
#property(nonatomic, copy) NSString *eventDescription;
#property(nonatomic, strong) IBOutlet UILabel * eventDescriptionLabel;
#property(nonatomic, assign) NSInteger eventFavourite;
#property(nonatomic, strong) IBOutlet UILabel * eventFavouriteLabel;
#end
TableCellViewController.m
#import "TableCellViewController.h"
#interface TableCellViewController ()
#end
#implementation TableCellViewController
#synthesize eventName;
#synthesize eventNameLabel;
#synthesize eventDate;
#synthesize eventDateLabel;
#synthesize eventStarttime;
#synthesize eventStarttimeLabel;
#synthesize eventEndtime;
#synthesize eventEndtimeLabel;
#synthesize eventLocation;
#synthesize eventLocationLabel;
#synthesize eventDescription;
#synthesize eventDescriptionLabel;
#synthesize eventFavourite;
#synthesize eventFavouriteLabel;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Set the eventNameLabel with the name of the event
eventNameLabel.text = eventName;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
/*
#pragma mark - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/
#end
Thanks again!
This is the offending line:
destViewController.eventName = [EventsArray objectAtIndex:indexPath.row];
You're trying to assign an object of type Event stored in the array, to an object of type NSString.
Since your string is defined with the copy modifier, the assignment tries to copy to object on the right side of the assignment (Event) but apparently this object doesn't conform to the NSCopying protocol, hence the error unrecognized selector... copyWithZone....
I have a SurroundViewController (CollectionView) which shows images loaded from a webserver. If you click on the image you will be navigated to a DetailViewController (TableView) which shows additional information to the image. Both Emebded in a NavigationController (see storyboard image).
My problem start when I do a refresh in the SurroundViewController, when coming back from the DetailViewController. Then it crashes with EXC_BAD_ACCESS on the performSelector line
WebApi.m
-(void)getSurroundStream {
NSString *URLString = [NSString stringWithFormat:#"%#/%#/view/%f/%f", kApiHost, kApiPath, self.sshare.coordinate.longitude, self.sshare.coordinate.latitude];
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
[self setAuthHeader:manager];
[manager GET:URLString parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
[self.sshare putViData:responseObject];
[self.delegate performSelector:#selector(didLoadFoo)]; // --> EXC_BAD_ACCESS
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
[self.error vError:error message:operation.responseString url:URLString];
}];
}
I checked in the Debug Console:
2014-03-11 14:22:51.989 Foo[6923:60b] -[SurroundViewController refresh:] [Line 352] refreshing
2014-03-11 14:22:51.998 Foo[6923:60b] -[WebApi getSurroundImages] [Line 393] do surround composition
(lldb) po self.delegate
[no Objective-C description available]
Seems that the object which is not available. What I do not understand is. I am in the SurroundViewController and do activly a refresh by pull-to-refresh. So I am on the Surround View and the object should be available...
How do I fix this issue, that the App does not crash with EXC_BAD_ACCESS at the performSelector line?
Here's the code which is involved with the issue (necessary parts):
SurroundViewController.h
#import <UIKit/UIKit.h>
#import "WebApi.h"
#import "DetailViewController.h"
#import "SingletonClass.h"
#interface SurroundViewController : UICollectionViewController <WebApiDelegate>
#property (nonatomic, strong) WebApi *swebapi;
#property (nonatomic, strong) SingletonClass *sshare;
#end
SurroundViewController.m
#import "SurroundViewController.h"
#interface SurroundViewController ()
#property (nonatomic, strong) UIRefreshControl *refresh;
#end
#implementation SurroundViewController
-(void)vinit {
self.sshare = [SingletonClass sharedInstance];
self.swebapi = [WebApi sharedInstance];
self.swebapi.delegate = self;
}
- (void)viewDidLoad
{
[self vinit];
[self.navigationController setNavigationBarHidden:YES animated:NO];
[super viewDidLoad];
[self addRefresh];
[self.swebapi getSurroundImages]; // will call delegate didComposition
}
- (void)viewDidAppear:(BOOL)animated
{
[self.navigationController setNavigationBarHidden:YES animated:NO];
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
// cell configuration
}
-(void)addRefresh {
UIRefreshControl *refreshControl = [[UIRefreshControl alloc] init];
[refreshControl addTarget:self action:#selector(refresh:) forControlEvents:UIControlEventValueChanged];
self.refresh = refreshControl;
[self.collectionView addSubview:self.refresh];
}
-(void)refresh:(UIRefreshControl*)refresh {
refresh.attributedTitle = [[NSAttributedString alloc] initWithString:#"Refreshing..."];
[self.swebapi getSurroundImages];
}
-(void)didLoadFoo {
[self.swebapi doComposition];
}
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
[self performSegueWithIdentifier:#"toDetailView" sender:indexPath];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"toDetailView"]) {
DetailViewController *dvc = [segue destinationViewController];
NSIndexPath *indexPath = sender;
dvc.idx = [self getItemOfSection:indexPath];
dvc.detailData = [[self.sshare coItem:dvc.idx] mutableCopy];
}
}
- (int)getItemOfSection:(NSIndexPath *)indexPath {
return (int)indexPath.item + ((int)indexPath.section * 4);
}
#end
WebApi.h
#import "AFHTTPRequestOperationManager.h"
#import "Errors.h"
#class WebApi;
#protocol WebApiDelegate <NSObject>
#optional
-(void)didLoadFoo;
#end
#interface WebApi : AFHTTPRequestOperationManager <SingletonDelegate>
#property (assign, nonatomic)id<WebApiDelegate> delegate;
#property (nonatomic, strong) Errors *error;
+(WebApi*)sharedInstance;
-(void)getSurroundStream;
-(void)getSurroundImages;
#end
WebApi.m
#import "WebApi.h"
#define kApiHost #"http://sample.com"
#define kApiPath #"sample"
#implementation WebApi
-(WebApi*)initWithBaseURL:url {
self = [super init];
if (self != nil) {
self.sshare = [SingletonClass sharedInstance];
self.error = [[Errors alloc] init];
}
return self;
}
+(WebApi*)sharedInstance
{
static WebApi *sharedInstance = nil;
static dispatch_once_t oncePredicate;
dispatch_once(&oncePredicate, ^{
sharedInstance = [[self alloc] initWithBaseURL:[NSURL URLWithString:kApiHost]];
});
return sharedInstance;
}
-(void)getSurroundStream {
NSString *URLString = [NSString stringWithFormat:#"%#/%#/view/%f/%f", kApiHost, kApiPath, self.sshare.coordinate.longitude, self.sshare.coordinate.latitude];
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
[self setAuthHeader:manager];
[manager GET:URLString parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
[self.sshare putViData:responseObject];
[self.delegate performSelector:#selector(didLoadFoo)]; // --> EXC_BAD_ACCESS
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
[self.error vError:error message:operation.responseString url:URLString];
}];
}
-(void)getSurroundImages {
[self getSurroundStream];
}
#end
SingletonClass.h
#import <Foundation/Foundation.h>
#class Singleton;
#protocol SingletonDelegate <NSObject>
-(void)didRefreshToken;
#end
#interface SingletonClass : NSObject
#property (assign, nonatomic) id<SingletonDelegate> delegate;
#property (nonatomic, strong) NSMutableArray *viData;
#property (nonatomic, strong) NSMutableArray *coData;
#end
SingletonClasss.m
#import "SingletonClass.h"
#implementation SingletonClass
static SingletonClass *sharedInstance = nil;
// Get the shared instance and create it if necessary.
+ (SingletonClass *)sharedInstance {
if (sharedInstance == nil) {
sharedInstance = [[super allocWithZone:NULL] init];
}
return sharedInstance;
}
- (id)init
{
self = [super init];
if (self) {
self.coData = [[NSMutableArray alloc] init];
self.viData = [[NSMutableArray alloc] init];
}
return self;
}
// We don't want to allocate a new instance, so return the current one.
+ (id)allocWithZone:(NSZone*)zone {
return [self sharedInstance];
}
// Equally, we don't want to generate multiple copies of the singleton.
- (id)copyWithZone:(NSZone *)zone {
return self;
}
-(NSMutableDictionary *)coItem:(int)position {
NSAssert(self.coData.count > position, #"Position does not exists: coData.count: %lu > position: %d", (unsigned long)self.coData.count, position);
return self.coData[position];
}
#end
DetailViewController.h
#import <UIKit/UIKit.h>
#import "SingletonClass.h"
#import "WebApi.h"
#interface DetailViewController : UITableViewController <WebApiDelegate>
#property (nonatomic) int idx;
#property (nonatomic, strong) SingletonClass *sshare;
#property (nonatomic, strong) WebApi *swebapi;
#property (nonatomic, strong) NSMutableDictionary *detailData;
#end
DetailViewController.m
#import "DetailViewController.h"
#interface DetailViewController ()
#property (nonatomic, strong) NSArray *cellRows;
#end
#implementation DetailViewController
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)vinit {
self.sshare = [SingletonClass sharedInstance];
self.swebapi = [WebApi sharedInstance];
self.swebapi.delegate = self;
NSAssert(self.detailData, #"detailData is not available");
}
- (void)viewDidLoad
{
[self vinit];
[self.navigationController setNavigationBarHidden:NO animated:NO];
[super viewDidLoad];
self.cellRows = #[#"cellLocation:", #"cellIntention:"];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.cellRows.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"detailCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
// Configure the cell...
SEL functionCall = NSSelectorFromString(self.cellRows[indexPath.row]);
[self performSelector:functionCall withObject:cell];
return cell;
}
- (void)cellLocation:(UITableViewCell*)cell {
// configuration of table cell
}
- (void)cellIntention:(UITableViewCell*)cell {
// configuration of table cell
}
#end
You are setting DetailViewController as delegate. Of course you will get EXC_BAD_ACCESS after it's deallocated.
You should use notifications instead delegates for shared instances.
- (void)addObserver:(id)notificationObserver selector:(SEL)notificationSelector name:(NSString *)notificationName object:(id)notificationSender and - (void)removeObserver:(id)notificationObserver are yours friends.
In your protocol, you set didLoadDoo as optional,
#protocol WebApiDelegate <NSObject>
#optional
-(void)didLoadFoo;
#end
so you need to secure the call to that method in your delegate
if ([self.delegate respondsToSelector:#selector(didLoadFoo)]) {
[self.delegate performSelector:#selector(didLoadFoo)];
}
As you are working with a singleton
+(WebApi*)sharedInstance
if your singleton.delegate is change somewhere else in your code (i.e. in your detailVC), it is change everyWhere !
edit :
After some more check, now we know that WebApi.delegate is change in detailVC, and the bug appear when we are back from detailVC because at this step detailVC is becoming nil and of course WebApi.delegate also.
So, the solution is to reset WebApi.delegate when we are back in SurroundViewController, and we can do that in :
SurroundViewController.m
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
self.swebapi.delegate = self;
}
I am newbie in iOS programming. I have read so may threads regarding this problem but also couldn't figure out what is actually causing the error. I need to pass first tableview cell's text of tableview of bookmarkViewController back to URL address bar of myViewController which is the root ViewController when i click the first tableview's cell.
Everything is working fine beside this data passing to root ViewController and i am using delegation for it.
myViewController.h
#import "bookmarkViewController.h"
#import <UIKit/UIKit.h>
#import "historyViewController.h"
#import "AppDelegate.h"
#import "Reachability.h"
#interface myViewController : UIViewController <UITextFieldDelegate,UIAlertViewDelegate,secondViewControllerDelegate>
#property (weak, nonatomic) IBOutlet UIBarButtonItem *addButton;
#property (weak, nonatomic) IBOutlet UITextField *addressBar;
#property (weak, nonatomic) IBOutlet UIWebView *webView;
#property (weak, nonatomic) IBOutlet UITextField *searchBar;
- (IBAction)goBack:(id)sender;
- (IBAction)goForward:(id)sender;
- (IBAction)refreshWebView:(id)sender;
#property (weak, nonatomic) IBOutlet UIBarButtonItem *goBackButton;
#property (weak, nonatomic) IBOutlet UIBarButtonItem *goForwardButton;
#property (weak, nonatomic) IBOutlet UIBarButtonItem *refreshButton;
-(void)textFieldDidEndEditing:(UITextField *)textField;
- (void) loadWebPageFromString:(NSString *)string;
#end
myViewController.m
#import "myViewController.h"
#interface myViewController ()
#end
#implementation myViewController
-(void)loadView
{
[super loadView];
[_goBackButton setEnabled:NO];
}
- (void)webViewDidFinishLoad:(UIWebView *)webview
{
_addButton.enabled=YES;
_refreshButton.enabled=YES;
if ([_webView canGoBack]) {
[_goBackButton setEnabled:YES];
} else [_goBackButton setEnabled:NO];
if ([_webView canGoForward]) {
[_goForwardButton setEnabled:YES];
} else _goForwardButton.enabled=NO;
}
- (void)checkForWIFIConnection {
Reachability* wifiReach = [Reachability reachabilityForLocalWiFi];
NetworkStatus netStatus = [wifiReach currentReachabilityStatus];
if (netStatus!=ReachableViaWiFi)
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"No Internet Connection"
message:#"Your device is not connected to internet."
delegate:self
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
}
}
- (void)viewDidLoad
{
_refreshButton.enabled=NO;
_addButton.enabled=NO;
[_goBackButton setEnabled:NO];
_goForwardButton.enabled=NO;
[self checkForWIFIConnection];
[super viewDidLoad];
}
-(void)textFieldDidEndEditing :(UITextField *)textField
{
if (textField.text){
if (textField==_searchBar){
AppDelegate *historydelegate= (AppDelegate *)[[UIApplication sharedApplication]delegate];
NSMutableArray *a=historydelegate.historyArray;
NSString *b=[NSString stringWithFormat:#"http://www.google.com/search?q=%#",textField.text] ;
[a addObject:b];
}}}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)googleEntered:(UITextField *)sender {
Reachability* wifiReach = [Reachability reachabilityForLocalWiFi];
NetworkStatus netStatus = [wifiReach currentReachabilityStatus];
if (netStatus==ReachableViaWiFi){
[self loadWebPageFromString:_searchBar.text];
[self textFieldDidEndEditing:_searchBar];
_addressBar.text=[NSString stringWithFormat: #"http://www.google.com/search?q=%#",_searchBar.text] ;
}else {[self checkForWIFIConnection];self.addressBar.text=NULL;}
}
- (IBAction)goBack:(id)sender {
[_webView goBack];
_searchBar.text=NULL;
_addressBar.text=NULL;
}
- (IBAction)goForward:(id)sender {
[_webView goForward];
_searchBar.text=NULL;
}
- (IBAction)refreshWebView:(id)sender {
[_webView reload];
[self checkForWIFIConnection];
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
AppDelegate *maindelegate= (AppDelegate *)[[UIApplication sharedApplication]delegate];
NSMutableArray *a=maindelegate.bookmarksArray;
if([segue.identifier isEqualToString:#"segueOne"]){
if ([_addressBar.text length]!=0){
NSString *b=[NSString stringWithFormat:#"%#",_addressBar.text];
[a addObject:b];
}}}
- (void) loadWebPageFromString:(NSString *)string {
NSURL *url = [NSURL URLWithString:string];
NSString *googleSearch = [string stringByReplacingOccurrencesOfString:#" " withString:#"+"];
url = [NSURL URLWithString:[NSString stringWithFormat:#"http://www.google.com/search?q=%#", googleSearch]];
NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url];
[_webView loadRequest:request];
}
-(void)loadAddress:(NSString *)mystring{
NSURL *myurl = [NSURL URLWithString:mystring];
if(!myurl.scheme){
myurl = [NSURL URLWithString:[NSString stringWithFormat:#"http://%#", mystring]];
NSURLRequest *request = [[NSURLRequest alloc] initWithURL:myurl];
[_webView loadRequest:request];}
else{
myurl = [NSURL URLWithString:[NSString stringWithFormat:#"%#", mystring]];
NSURLRequest *request = [[NSURLRequest alloc] initWithURL:myurl];
[_webView loadRequest:request];
}
}
-(BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{
if (navigationType==UIWebViewNavigationTypeLinkClicked) {
NSURL *URL=[request URL];
[self checkForWIFIConnection];
if ([URL scheme] ) {
Reachability* wifiReach = [Reachability reachabilityForLocalWiFi];
NetworkStatus netStatus = [wifiReach currentReachabilityStatus];
if (netStatus==ReachableViaWiFi ){
_addressBar.text=URL.absoluteString;
_searchBar.text=NULL;
[_webView loadRequest:request];
AppDelegate *historydelegate= (AppDelegate *)[[UIApplication sharedApplication]delegate];
NSMutableArray *a=historydelegate.historyArray;
[a addObject:URL.absoluteString];
}
}
return NO;
}
return YES;
}
- (BOOL) urlIsValid: (NSString *) url
{
NSString *regex =
#"((?:http|https)://)?(?:www\\.)?[\\w\\d\\-_]+\\.\\w{2,3}(\\.\\w{2})?(/(?<=/)(?:[\\w\\d\\-./_]+)?)?";
/// OR use this
///NSString *regex = "(http|ftp|https)://[\w-_]+(.[\w-_]+)+([\w-.,#?^=%&:/~+#]* [\w-\#?^=%&/~+#])?";
NSPredicate *regextest = [NSPredicate predicateWithFormat:#"SELF MATCHES %#", regex];
if ([regextest evaluateWithObject: url] == NO) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Invalid URL"
message:#"Enter valid URL."
delegate:self
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
}
return [regextest evaluateWithObject:url];
}
-(IBAction)addressEntered:(UITextField *)sender {
Reachability* wifiReach = [Reachability reachabilityForLocalWiFi];
NetworkStatus netStatus = [wifiReach currentReachabilityStatus];
if (netStatus==ReachableViaWiFi && [self urlIsValid:_addressBar.text]){
[self loadAddress:_addressBar.text];
AppDelegate *historydelegate= (AppDelegate *)[[UIApplication sharedApplication]delegate];
NSMutableArray *a=historydelegate.historyArray;
[a addObject:_addressBar.text];
}else [self checkForWIFIConnection];
[sender resignFirstResponder];
_searchBar.text =NULL;
}
-(void)showView{
bookmarkViewController *b=[[bookmarkViewController alloc]initWithNibName:#"bookmarkViewController" bundle:nil];
b.delegate=self;
[self presentViewController:b animated:YES completion:nil];
}
- (void)passData:(NSString *)data
{
self.addressBar.text=data;
}
- (IBAction)go:(id)sender {
[self showView];
}
#end
bookmarkViewController.h
#protocol secondViewControllerDelegate <NSObject>
#required
- (void)passData:(NSString *)data;
#end
#import <UIKit/UIKit.h>
#import "AppDelegate.h"
#import "myViewController.h"
#interface bookmarkViewController : UIViewController
#property (nonatomic, weak) id<secondViewControllerDelegate> delegate;
#property (weak, nonatomic) IBOutlet UITableView *tableView;
- (IBAction)goBac:(id)sender;
#end
bookmarkViewController.m
#import "bookmarkViewController.h"
#import "AppDelegate.h"
#interface bookmarkViewController ()
#end
#implementation bookmarkViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
- (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];
}
// Configure the cell...
AppDelegate *maindelegate= (AppDelegate *)[[UIApplication sharedApplication]delegate];
NSMutableArray *a=[maindelegate bookmarksArray];
cell.textLabel.text = [a objectAtIndex:[indexPath row]];
return cell;
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell * cell = [tableView cellForRowAtIndexPath:indexPath];
if ([indexPath row]==0) {
if ([self.delegate respondsToSelector:#selector(passData:)]) {
[self.delegate passData:cell.textLabel.text];
}
[self dismissViewControllerAnimated:YES completion:nil];
}
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
AppDelegate *maindelegate= (AppDelegate *)[[UIApplication sharedApplication]delegate];
NSMutableArray *a=[maindelegate bookmarksArray];
return [a count];
}
- (void)viewDidLoad
{
[super viewDidLoad];
[[self tableView] reloadData];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)goBac:(id)sender {
[self dismissViewControllerAnimated:YES completion:nil];
}
#end
You shouldn't use dequeueReusableCellWithIdentifier: method when a row is selected. It should be used only when you want to get a reusable cell actually. You can use:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell * cell = [tableView cellForRowAtIndexPath:indexPath];
if ([indexPath row]==0)
{
if ([self.delegate respondsToSelector:#selector(passData:)])
{
[self.delegate passData:cell.textLabel.text];
}
}
}
You shouldn't call dismissViewControllerAnimated:completion: method from your child view controller, it is the parent view controller's job.
And in your delegate method:
- (void) passData:(NSString *)data
{
self.addressBar.text = data;
[self dismissViewControllerAnimated:YES completion:nil];
}
EDIT: Method names updated.
Another way to do same is by using navigation controller stack if your application is navigation based.
Try this:-
1.Define a global NSString in MyViewController.h like
#property(strong, nonatomic) NSString *strText;
2.Do following code on didSelectRowAtIndexPath of BookMarkViewController
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell * cell = [tableView cellForRowAtIndexPath:indexPath];
if(indexPath.row == 0)
{
NSArray *arrControllers = [self.navigationController.viewControllers];
MyViewController *objMyCnrl = [arrControllers objectAtIndex:[arrControllers count]-2];
objMyCnrl.strText = cell.textLabel.text; // Pass the string value here
[self dismissViewControllerAnimated:YES completion:nil];
}
}