Need a view that acts like a log view - objective-c

I need to implement a view that acts as a log view, so that when you push a message into it, the message would push other messages upwards.
Is there anything like that for iOS?

You can easily implement that using standard UITableView:
Each cell will be responsible for displaying 1 log message
Add new cell to the end of the table when new message arrive
Scroll table to the bottom after cell is added (using scrollToRowAtIndexPath:atScrollPosition:animated: method with UITableViewScrollPositionBottom position parameter)
That means you'll need to store your log messages in array, but if you're going to display them you need to store messages anyway

#Vladimir's answer is probably the way to go, but just for the sake of seeing some additional options, here's an example using a UITextView:
- (IBAction)addNewLog:(UIButton *)sender {
NSString *myInputText = #"some new text from string";
NSString *temp = myTextView.text;
[myTextView setText:[temp stringByAppendingString:[NSString stringWithFormat:#"\n%#: %#",[NSDate date],myInputText]]];
[myTextView setContentOffset:CGPointMake(0, myTextView.contentSize.height - myTextView.frame.size.height) animated:NO];
}
Then if you wanted to separate the text in the text view into objects in an array:
NSArray *myAwesomeArray = [myTextView.text componentsSeparatedByString:#"\n"];
Mind you, the above would break if the "myInputText" string ever contained a line break.

Related

Change text of a label

I have a array that reads a .txt file and when you click a button the label changes in one of the words of the .txt file, but the label doen't change.
This is the code:
if(sender == self.button) {
NSArray *words = [[NSArray alloc] initWithObjects:#"words.txt", nil];
[randomLabel setText:[words objectAtIndex:random() % [words count]]];
}
What should I do so the label changes when I press the button?
What file do I use?
A few things here:
Reading in file into an array
Well, for starters you're not reading in the contents of the .txt file.
NSArray *words = [[NSArray alloc] initWithObjects:#"words.txt", nil];
This creates a 1 element array, with that one element being #"words.txt". I don't know the format of your .txt file, so I can't say for sure how you have to load it in. See How do I format a text file to be read in using arrayWithContentsOfFile on how to potentially do this.
Setting button text
Also, you need to make sure randomLabel actually refers to the label contained within the button, otherwise the button text won't change. Typically for a button, you'd change the title using the method:
- (void)setTitle:(NSString *)title forState:(UIControlState)state
So in your instance, it'd be:
NSString* newTitle = [words objectAtIndex:random() % [words count]];
[self.button setTitle:newTitle forState:UIControlStateNormal];
Is the code actually being called?
Double check that sender == self.button evaluates to true (for readability and clarity, I'd use [sender isEqual:self.button]). Use the debugger to step through the code, to see if that particular piece of code is being called. See http://mobile.tutsplus.com/tutorials/iphone/xcode-debugging_iphone-sdk/ on how to achieve this.
You should try using
(id)initWithContentsOfFile:(NSString *)aPath

Xcode Like log with NSTextView

I'm trying to set up a NSTextView like the console in Xcode (or pretty much any other IDE available). That being the user cannot edit the NSTextView, however they can put in a character when appropriate, I'm trying to set up that same functionality. No clue how to go about it. Any ideas?
You could simply make an action that appends a formatted string containing a line break, a time stamp, and your desired text to the text view. Here's an example:
- (void)addToLog:(NSString *)input
{
[[self.myTextView textStorage] appendAttributedString:[[NSAttributedString alloc] initWithString:[NSString stringWithFormat:#"\n%#: %#",[NSDate date],input]]];
}
So then instead of using NSLog(#"some text"); you could call [self addToLog:#"some text"]; and it would be added to a new line in your text view.

Get EXC_BAD_ACCESS when tableview get data from URL?

My tableview is get XML data from URL,First I declare a NSMutableArray *dataArray;
and this is how I get the data in my TableviewSample.m
- (void)getDataFromURL{
NSString *theURLAsString = [NSString stringWithFormat:GetAllData];//<-EXE_BAD_ACCESS HERE
//#define stringWithFormat:GetAllData #"http://192.168.10.28/req_alldata.php"
NSURL *theURL = [NSURL URLWithString:theURLAsString];
self.dataArray = [NSMutableArray arrayWithContentsOfURL:theURL];
}
Then I just get the elements form this array to my tableview ...
But here I have to say one more thing , actually it won't crash before I add another view...
I add a bar button to go to a webView , this webView is use to load a IP Cam stream video
When I back to the tableview , It will appear EXC_BAD_ACCESS
This is odd things I cannot to solve it...because both side code are all looks normal
If I remove this webview ,no matter how I run the program ,it won't crash...
And sometimes I leave the webView I will receive memory warning :level 2
But just only one time.
or do I use a wrong way to open an ip cam stream ???
Thanks for all reply : )
OK,here is the code different I use in my webview class
This is first version I use
- (void)viewDidAppear:(BOOL)animated{
NSString *directGoToWebCam = [NSString stringWithFormat:GetAllData];
self.IPCamWebView=[[[UIWebView alloc] initWithFrame:CGRectMake(0,0,640,960)] autorelease];
[self.IPCamWebView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:directGoToWebCam]]];
[self.view addSubview:self.IPCamWebView];
}
Where does GetAllData come from? It looks like that isn't pointing to anything. More code, the exact error, and a more careful description will go a long way here.
It probably has something to do with the use of #define which does not say anything about the type of the object you are using.
If you want to define a constant string in your code the best would be to use something like this:
static NSString *GetAllData = #"192.168.10.28/req_alldata.php";
Where you need to use the string you can simply write:
NSString *GoToWebCam = [NSString stringWithString:GetAllData];

Navigating between View controllers?

In my Iphone application I am trying to navigate from one table view controller to next table view controller. Problem I am facing is that I have to fetch data using http request and then parse this data when the user select a cell. I am able to fetch and parse the data but the view controller is not waiting for the data to parsed and the next view controller is shown (which is empty). How to over come this problem.
indexSelected = [NSString stringWithFormat: #"%d",[indexPath row] ];
[[MySingletonClass sharedMySingleton] doAnAuthenticatedAPIFetch_Subscriber_Detail : indexSelected];
SubscribersDetailViews2 *viewController = [[SubscribersDetailViews2 alloc] initWithNibName:#"SubscribersDetailViews2" bundle:nil];
[[self navigationController] pushViewController:viewController animated:YES];
[viewController release];
This is what you do:
indexSelected = [NSString stringWithFormat: #"%d",[indexPath row] ];
SubscribersDetailViews2 *viewController = [[SubscribersDetailViews2 alloc] initWithNibName:#"SubscribersDetailViews2" bundle:nil];
[[MySingletonClass sharedMySingleton] doAnAuthenticatedAPIFetch_Subscriber_Detail:indexSelected delegate:self];
[[self navigationController] pushViewController:viewController animated:YES];
[viewController release];
You define a protocol that your view controller conforms to and when the fetching and parsing of data is done you call a method on the delegate to let the view controller know that the data is ready to be displayed.
If you need more information on how to do this, leave a comment.
EDIT: So here's how to declare and use a protocol. I'm going to try to keep it as simple as possible. I'm not sure if I like your naming convention, but I'll still use it for this example.
So let's get down to the code. This is how you declare a protocol:
#protocol MySingletonClassDelegate <NSObject>
#optional
- (void)didDoAnAuthenticatedAPIFetch_Subscriber_Detail_WithData:(NSArray *)data;
- (void)failedToDoAnAuthenticatedAPIFetch_Subscriber_Detail_WithError:(NSError *)error;
#end
Again, I'm not too fond of the naming convention. You shouldn't have underscores in objective-c method names.
The protocol should be defined in MySingletonClass.h before the declaration of MySingletonClass.
I declared two methods in the protocol, one for delivering the data and one for delivering an error if it fails, so that you can notify the user that it failed.
To use the protocol you need the following:
#interface SubscribersDetailViews2 : UITableViewController <MySingletonClassDelegate>
You also need to implement the methods declared in the protocol, but I'll leave that implementation to you.
Since the fetching of data already seems to be happening in the background I don't think I'll need to explain how to do that. One important thing to remember is that you want to execute the delegate methods on the main thread. Here's the code to do that:
- (void)doAnAuthenticatedAPIFetch_Subscriber_Detail:(NSUInteger)index delegate:id<MySingletonClassDelegate>delegate {
// Fetching data in background
if (successful) {
[self performSelectorOnMainThread:#selector(didDoAnAuthenticatedAPIFetch_Subscriber_Detail_WithData:) withObject:data waitUntilDone:NO];
} else {
[self performSelectorOnMainThread:#selector(failedToDoAnAuthenticatedAPIFetch_Subscriber_Detail_WithError:) withObject:error waitUntilDone:NO];
}
}
Just to be clear the // Fetching data in background is supposed to be replaced by your code. I assume that your code produces the variables (NSArray *data, NSError *error, BOOL successful) that I use.
That's about it, if you need clarification on anything let me know.
There are a number of options:
Cache the data, i.e., take a full copy of it on the iOS device (may not be practical of course)
Display an interstitial screen saying "loading" and then move to the "real" screen when the data has downloaded
Have, effectively, two different data sources for your table. The first is your current one. The second would be a single cell saying "Loading..."
In short, there's no point and click way of doing this but there's no problem downloading the data on the fly as long as you tell your users what's happening.

Drag file from NSTableView to other osx application

I want to drag a file from a NSTableView row to copy it to another application (i.e. Finder). I implemented the first two steps ('Configuring Your Table View', 'Beginning a Drag Operation') of this guide and thought that would do the trick:
http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/TableView/Tasks/UsingDragAndDrop.html
However, when I attempt to drag a row, the row text follows my mouse but the file does not copy when released. Here's what I'm sending to my UITableView upon initialization:
#define librarySongDataType #"NSFileContentsPboardType"
- (void)awakeFromNib
{
[self setDraggingSourceOperationMask:NSUIntegerMax forLocal:YES]; // allow interapplication drags
[self registerForDraggedTypes:[NSArray arrayWithObject:librarySongDataType] ]; // NSFileContentsPboardType
}
Here's how I'm handling the drag in my NSTableView's data source (an NSArrayController):
- (BOOL)tableView:(NSTableView *)aTableView writeRowsWithIndexes:(NSIndexSet *)rowIndexes toPasteboard:(NSPasteboard *)pboard
{
NSLog(#"writeRowsWithIndexes");
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:rowIndexes];
[pboard setData:data forType:librarySongDataType];
return YES;
}
To be clear, I'm not trying to drag files into my table view, I'm just trying to drag file(s) out of it.
Firstly, which document did you refer to when you wrote this line ?
[self setDraggingSourceOperationMask:NSUIntegerMax forLocal:YES];
This doesn't make sense. Don't use NSUIntegerMax. Use operation masks as defined here. It's written there that NSUIntegerMax stands for everything, but you shouldn't use it; Apple may re-define the bit in the future. You should use NSDragOperationCopy or something specific. If you copied that line from a webpage or a book, you should stop trusting that book/webpage.
Secondly, forLocal: should be NO to pass the data to another application; local here means application local.
Third, instead of just setting the archived data in
[pboard setData:data forType:librarySongDataType];
Consider making an NSFileWrapper and set it using writeFileWrapper:, see here. That way you can specify the file name to be created in Finder. Otherwise, the system doesn't have any idea what the data represent.