xcode debugging terminates when i run app - xcode

When I run my app in Xcode using the simulator it runs just file until I add in the first three lines involving the text file. It gives me a message saying terminate called after throwing an instance of 'NSException'. I don't know what that means or why it only happens when I try to read in the text file and display it in the textView.
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"textfiles/brain_01" ofType:#"txt"];//establish file path for text file
NSString *textFile = [[NSString alloc] stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error: nil];
textView.text = textFile;
[super viewDidLoad];
fullButton.hidden = YES;
viewLabel.hidden = YES;
}

NSException means your code has a bug in it. An exception is an error. In your case, it's probably because
NSString *textFile = [[NSString alloc] stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error: nil];
should be
NSString *textFile = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error: nil];
stringWithContentsOfFile is a class method used to make NSString -- only use alloc with init... methods.

Related

Is it possible to unit test a WindowController thats initialised with a nib?

I have a simple Mac OS application that comes with the default MainMenu.xib. In there I have a second window for preferences and a PreferencesWindowController. I'd like to get the following test working:
#implementation TestPreferencesWindow
- (void)testProtectsUserPasswordByUsingAPasswordField
{
PreferencesWindowController *controller = [[PreferencesWindowController alloc] initWithWindowNibName:#"MainMenu"];
XCTAssertInstanceOf([[controller passwordField] class], NSSecureTextField);
}
#end
The problem is that [controller passwordField] is not initialised (because the nib isn't loading?) so it always returns nil.
How do I tell the nib to create all the bindings?
When I call [controller window] is gives the error, and returns nil:
Could not connect the action orderFrontStandardAboutPanel: to target of class PreferencesWindowController
For debugging I have tried the following:
NSBundle *bundle = [NSBundle mainBundle];
XCTAssertNotNil(bundle);
NSString *nibPath = [bundle pathForResource:#"MainMenu" ofType:#"nib"];
XCTAssertNotNil(nibPath);
PreferencesWindowController *controller = [[PreferencesWindowController alloc] initWithWindowNibPath:nibPath owner:self];
NSLog(#"%# %#", [controller window], [controller passwordField]);
However it still prints (null) (null) ...
To get rid of the warning:
NSBundle *bundle = [NSBundle mainBundle];
XCTAssertNotNil(bundle);
NSString *nibPath = [bundle pathForResource:#"MainMenu" ofType:#"nib"];
XCTAssertNotNil(nibPath);
NSApplication *app = [NSApplication sharedApplication];
PreferencesWindowController *controller = [[PreferencesWindowController alloc] initWithWindowNibPath:nibPath owner:app];
NSLog(#"%# %#", [controller window], [controller passwordField]);
No more warning, but still prints (null) (null) .. I feel like I'm getting closer though...
I got solution. Write below method in your .m file, and declare public in .h file
MyWindowController.m file
- (instancetype)initWithWindowNibPath:(NSString *)nibPath {
self = [super initWithWindowNibPath:nibPath owner:self];
if(self)
{
//initialize stuff
}
return self;
}
MyWindowController.h file
- (instancetype)initWithWindowNibPath:(NSString *)nibPath;
Now write your code:
NSBundle *bundle = [NSBundle mainBundle];
XCTAssertNotNil(bundle);
NSString *nibPath = [bundle pathForResource:#"MyWindowController" ofType:#"nib"];
XCTAssertNotNil(nibPath);
MyWindowController *controller = [[MyWindowController alloc] initWithWindowNibPath:nibPath];
NSLog(#"%# %#", [controller window], [controller passwordField]);
This is works perfect for me.
Reason:
owner value not properly set in initWithWindowNibPath method and therefore not set class's properties NSOutlet to nib's control.

Xcode 'autorelease is unavailable in URL request

I have the following code in my .m file:
- (IBAction)LoginButton:(id)sender {
// create string contains url address for php file, the file name is phpFile.php, it receives parameter :name
NSString *strURL = [NSString stringWithFormat:#"http://www.myURL.com/verify.php?Email=%#",Email.text];
// to execute php code
NSData *dataURL = [NSData dataWithContentsOfURL:[NSURL URLWithString:strURL]];
// to receive the returend value
NSString *strResult = [[[NSString alloc] initWithData:dataURL encoding:NSUTF8StringEncoding]autorelease];
NSLog(#"%#", strResult);
UIAlertView *alert = [[UIAlertView alloc]
initWithTitle:#"Result:"
message:strResult
delegate:nil
cancelButtonTitle:#"Okay"
otherButtonTitles:nil];
[alert show];
}
And I am getting that autorelease is unavailable in automatic reference counting mode.
It seems to be an issue with the following line:
NSString *strResult = [[[NSString alloc] initWithData:dataURL encoding:NSUTF8StringEncoding]autorelease];
How can I solve this?
Just delete the autorelease call; if you are using ARC (Automatic Reference Counting) you don't need to worry about memory management.

Why does my code break for one call to this method, but not another?

I have a Mac application that is supposed to fetch Twitter followers and friends for a given username and then, in turn, ask Twitter for the user NAMES for each of those returned UserIDs. As you can see below, I have a method that will call the Twitter API to get friends/followers (which works fine). It is the userNameForUserID:delegate: method that is causing me problems. I used to do these requests synchronously and return the NSString for the username right then. That (now commented out) line always broke, so I tried doing it with an NSURLConnection asynchronously. Still doesn't work. I don't understand why
[[NSString alloc] initWithContentsOfURL:...] works for the fetchFollowers... method, but not when I do it the EXACT SAME way in the other...
I put a break point on the line that used to alloc init the NSString with contents of URL, and when I step into it, it doesn't break, return, throw an exception, crash...nothing. It's as if that line just got stepped over (but my application is still blocked.
Any ideas? Much appreciated!
NSString * const GET_FOLLOWERS = #"https://api.twitter.com/1/followers/ids.json?cursor=-1&screen_name=";
NSString * const GET_FRIENDS = #"https://api.twitter.com/1/friends/ids.json?cursor=-1&screen_name=";
NSString * const GET_USER_INFO = #"https://api.twitter.com/1/users/show.json?user_id=";
#implementation TwitterAPI
+ (void)userNameForUserID:(NSNumber *)userID delegate:(id<UserNameDelegate>)delegate
{
NSURL *url = [NSURL URLWithString:[GET_USER_INFO stringByAppendingString:[userID stringValue]]];
// NSString *JSON = [[NSString alloc] initWithContentsOfURL:url encoding:NSUTF8StringEncoding error:&error];
NSURLRequest *req = [NSURLRequest requestWithURL:url];
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[NSURLConnection sendAsynchronousRequest:req queue:queue completionHandler:^(NSURLResponse *urlResponse, NSData *data, NSError *error) {
[delegate addUserNameToArray:data];
}];
}
+ (NSArray *)fetchFollowersWithUserName:(NSString *)userName
{
NSURL *url = [NSURL URLWithString:[GET_FOLLOWERS stringByAppendingString:userName]];
NSArray *followerIDs;
NSString *JSON = [[NSString alloc] initWithContentsOfURL:url encoding:NSASCIIStringEncoding error:nil];
if ([JSON rangeOfString:#"error"].location == NSNotFound)
followerIDs = [[JSON JSONValue] valueForKey:#"ids"];
return followerIDs;
}

XCode - UIWebView Not Loading

I have two local .html files in the Resources folder. I'm trying to load them the following way, but only the final page loads. What am I doing wrong?
File = please_wait.html
This one does not work.
NSError *error;
NSString* path = [[NSBundle mainBundle] pathForResource:#"please_wait" ofType:#"html"];
NSString* htmlString = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:&error];
[webView loadHTMLString:htmlString baseURL:[NSURL fileURLWithPath:path]];
//Big "do-while" loop here. It works fine so I omitted it.
File = update_graph.html
This one does not work
path = [[NSBundle mainBundle] pathForResource:#"update_graph" ofType:#"html"];
htmlString = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:&error];
[webView loadHTMLString:htmlString baseURL:[NSURL fileURLWithPath:path]];
//Lots of code removed. All works correctly and doesn't touch webview
This last one works perfectly. Google displays.
string = #"http://google.com";
NSURL *url = [NSURL URLWithString: string];
NSURLRequest *requestObj = [NSURLRequest requestWithURL:url];
[webView loadRequest:requestObj];
It appears from your comment that your UIWebView loads just fine, but it does not get a chance to refresh itself on the screen until you exit your method. It is not enough to set a break point inside the method and wait for the view to load: you must exit the method before iOS realizes that it needs to call UIWebView's drawRect method.
To fix this, split your method in three parts, A B and C, and set UIWebView's delegate in A to invoke B on webViewDidFinishLoad:, and the delegate in B to call C.
Here is how to implement this: start with a delegate that can call a selector when the loading has completed:
#interface GoToNext : NSObject <UIWebViewDelegate> {
id __weak target;
SEL next;
}
-(id)initWithTarget:(id)target andNext:(SEL)next;
-(void)webViewDidFinishLoad:(UIWebView *)webView;
#end
#implementation GoNext
-(id)initWithTarget:(id)_target andNext:(SEL)_next {
self = [super init];
if (self) {
target = _target;
next = _next;
}
return self;
}
-(void)webViewDidFinishLoad:(UIWebView *)webView {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
[target performSelector:next];
#pragma clang diagnostic pop
}
#end
Now split your method into three parts - loading the first page, loading the second page, and loading the third page:
-(void)loadPleaseWait {
NSError *error;
NSString* path = [[NSBundle mainBundle] pathForResource:#"please_wait" ofType:#"html"];
NSString* htmlString = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:&error];
webView.delegate = [[GoToNext alloc] initWithTarget:self andNext:#selector(loadUpdateGraph)];
[webView loadHTMLString:htmlString baseURL:[NSURL fileURLWithPath:path]];
// big do-while loop
}
-(void)loadUpdateGraph {
NSError *error;
NSString* path = [[NSBundle mainBundle] pathForResource:#"update_graph" ofType:#"html"];
NSString* htmlString = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:&error];
webView.delegate = [[GoToNext alloc] initWithTarget:self andNext:#selector(loadGoogle)];
[webView loadHTMLString:htmlString baseURL:[NSURL fileURLWithPath:path]];
// Lots of code removed
}
-(void)loadGoogle {
string = #"http://google.com";
NSURL *url = [NSURL URLWithString: string];
NSURLRequest *requestObj = [NSURLRequest requestWithURL:url];
[webView loadRequest:requestObj];
}

Open/edit a .txt file located in application bundle with NSTextView object

I would like to add an NSTextView object to my app and add an action that opens a .txt file located in the app bundle in the textView. Also - I would like to have the option to edit and save the edited doc without renaming it. So standard save, not save as.
What's the best way to handle this?
Use NSString to load the file and put it in your text view:
NSTextView *textView; //your NSTextView object
NSError *err = nil;
NSString *path = [[NSBundle mainBundle] pathForResource:#"EditableFile" ofType:#"txt"];
NSString *contents = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:&err];
if(!contents) {
//handle error
}
[textView setString:contents];
Saving is just the opposite. Get the string and write it to the file:
NSTextView *textView; //your NSTextView object
NSError *err = nil;
NSString *path = [[NSBundle mainBundle] pathForResource:#"EditableFile" ofType:#"txt"];
NSString *contents = [textView string];
if(![contents writeToFile:path atomically:YES encoding:NSUTF8StringEncoding error:&err]) {
//handle error
}

Resources