My program works
send byte using CocoaAsyncSocket (TCP)
get response (byte data)
change byte array to valid data (int / nsstring / etc)
change label text with it(step 3)
I put a NSLog and watched. Log shows almost fast and my function (change label text) runs well. However, I can see change label`s text on simulator about 4~5 second later then function called.
My first way is this
get a byte array - split into nsdata - change to nsstring - input array - get string - add sub string (like '000%' or '000 sec') - change label text
And Second is
get a byte array - split - change to nsstring - call a function (add sub string - change label text)
Well... How can I boost its change speed?
Changing the label text should happen "almost instantly", and when it takes this long it is usually caused by not updating the label text on the main thread. It is a UIKit object, therefore it must only be modified on the main thread.
Use:
dispatch_async(dispatch_get_main_queue(), ^{
self.label.text = myString;
});
I had a similar problem when fetching events from the Calendar with almost an identical delay. If what Inafziger suggested doesn't work for you, I suggest using performSelectorOnMainThread: and call a method to update your labels in your "Step 3."
[self performSelectorOnMainThread:#selector(yourMethodToUpdateLabels) withObject:nil waitUntilDone:NO];
It worked great for my situation. Hope it helps. :)
Related
I have not been able to find this information anywhere. How long can a string be send with the TTL version of the redpark cable?
The following delegate method is called twice when I print something thorough serial from my Arduino, an example of a string is this: 144;480,42;532,40;20e
- (void) readBytesAvailable:(UInt32)length{
When I use the new function methods of retrieving available data [getStringFromBytesAvailable] I will only get 144;480,42;532,40; and then the whole function is called again and the string now contains the rest of the string: 20e
The following method is working for appending the two strings, but only if the rate of data transmission is 'slow' (1 time a second, I would prefer minimum 10 times a second).
-
(void) readBytesAvailable:(UInt32)length{
if(string && [string rangeOfString:#"e"].location == NSNotFound){
string = [string stringByAppendingString:[rscMgr getStringFromBytesAvailable]];
NSLog(string);
finishedReading = YES;
}
else{
string = [rscMgr getStringFromBytesAvailable];
}
if (finishedReading == YES)
{
//do stuff
}
finishedReading = NO;
string = nil;
}
}
But can you tell my why the methods is called twice if I write a "long" string, and how to avoid this issue?
Since your program fragment runs faster then the time it takes to send a string, you need to capture the bytes and append them to a string.
If the serial data is terminated with a carriage return you can test for it to know when you have received the entire string.
Then you can allow your Arduino to send 10 times a second.
That is just how serial ports work. You can't and don't need to avoid those issues. There is no attempt at any level of the SW/HW to keep your serial data stream intact, so making any assumptions about that in your code is just wrong. Serial data is just a stream of bytes, with no concept of packetization. So you have to deal with the fact that you might have to read partial data and read the rest later.
The serialPortConfig within the redparkSerial header file provided by RedPark does, in fact, give you more configuration control than you may realize. The readBytesAvailable:length method is abstracted, and is only called when one of two conditions is met: rxForwardingTimeout value is exceeded with data in the primary buffer (default set to 100 ms) or rxForwardCount is reached (default set to 16 characters).
So, in your case it looks like you've still got data in your buffer after your initial read, which means that the readBytesAvailable:length method will be called again (from the main run loop) to retrieve the remaining data. I would propose playing around with the rxForwardingTimeout and rxForwardCount until it performs as you'd expect.
As already mentioned, though, I'd recommend adding a flag (doesn't have to be carriage return) to at least the end of your packet, for identification.
Also, some good advice here: How do you design a serial command protocol for an embedded system?
Good luck!
If you wanna see the code Im having problem with, here is the link:
Code
My question is connected with my past question.
I'm really having problem with my NSMutableArray, I'm currently using iCarousel for my slotMachine object(slot1 and slot2). My app works this way:
From PhotoViewController I made a view that has thumbnail images, then assign its frame with button. So if 1 image was pressed, it will save that integer via NSUserDefaults.
Then I will retrieve it in my carouselViewController
Im thinking of adjusting the array but I can't.
I also have tried my question here:
Comparing with NSMutableArray
If only I can do it the same as Array 2 it would be much easy, but still not working.
(ADDITIONAL INFO:)
I have done it this way, have a Viewcontroller that contains the UIImageView with a button in it, so when the user taps it, my CustomPicker pops up. My CustomPicker contains the image on what the user have picked on the camera roll. So each button has a specific value sent to my iCarouselView using NSUserDefaults. carousel1 for First slot and carousel2 for Second slot.
Here is what I wanna do: I want to forcefully make it stop to the index the user picks. (Which Im doing in my carouselDidEndScrollingAnimtaion)
In my carouselDidEndScrollingAnimation method i tested all of my condition(individually) it works perfectly in terms of comparing.
Then when I combine the conditions, the first Two comparison or STOP is RIGHT, but the next two are always wrong. Or sometimes Got mixed up.
I need to scroll the two specific indexes/integer which was User Picked( I already done that) was able to scroll 2 pairs of them but then the next two were always wrong because I think there indexes were adjusting.
PICTURES:
Image Below is my PhotoViewController which contained the Comparing Stage SETTING of my game.UIImageVIew with UIButton.Image that will be put in the number according to it will be Forcefully and should be forcefully shown.
When my iCarousel start then it stops for example in the image below(Which is not the same as the above):
Will be forcefully scroll to the inputted image in the PhotoViewController
Into:
Summary:
Its like this. I have a settingsView from there, I will import my images(Multiple) for Slot1 & Slot2.
Then in another View the PhotoViewController that is where the image above is shown. THe first column corresponds to 1st slot followed by the 2nd slot. if a view is pressed (for example No. 1 of Slot 1 it will load a thumbnail of images loading the images picked from Picker for the Slot 1.
You will have to do it 4 times(pair) ----> The displayed here I get their indexes via NSUserDefaults via button.tag then send to iCarouselView.
Then when you are done (pressed Done button) it will go to iCarouselView then, as shown above thats the view of it.
When pressed it will spin for couple of seconds, then when finished but not stop at the user picked in the PhotoView it will forcefully scroll to that index.
QUESTION:
Is there a way to make my array or my iCarousel.view not adjust their indexes when Im deleting. To still retain my indexes the right way. Or are there other solution like adjusting my array, the same as adjusting my PhotoViewController picked indexes too. Because I think that when my array retain their indexes even deleting I would be able to solve this problem. But still can't.
Hope you understand my question.
Is there a way to make my array or my iCarousel.view not adjust their indexes when Im deleting. To still retain my indexes the right way. Or are there other solution like adjusting my array, the same as adjusting my PhotoViewController picked indexes too. Because I think that when my array retain their indexes even deleting I would be able to solve this problem. But still can't.
The only way you have to modify the way iCarousel manages its indexes is by modifying the code. Indeed, if you look at the removeViewAtIndex method in iCarousel.m, you will see that indexes are managed through an NSDictionary, and at the moment of deleting, the dictionary is rearranged (items are reordered). You could take that method:
- (void)removeViewAtIndex:(NSInteger)index
{
NSMutableDictionary *newItemViews = [NSMutableDictionary dictionaryWithCapacity:[itemViews count] - 1];
for (NSNumber *number in [self indexesForVisibleItems])
{
NSInteger i = [number integerValue];
if (i < index)
{
[newItemViews setObject:[itemViews objectForKey:number] forKey:number];
}
else if (i > index)
{
[newItemViews setObject:[itemViews objectForKey:number] forKey:[NSNumber numberWithInteger:i - 1]];
}
}
self.itemViews = newItemViews;
}
You could apply the same logic to your array, so that the carousel and your array keep in sync. Of course, if you store the indexes somewhere (slot1/slot2/slot2/slot4?), you should also update their values after removing an element.
On the other hand, I think that what you are asking here is how to do something that you believe would solve the problem you have, but you are not really explaining what the problem is. Indeed, if I understand you correctly, what you do is:
spinning the carousel;
when the carousel stops, if it is not by chance on the desired item, you "force" it to scroll to that item.
There is no reason why this should not work after deleting some elements (unless iCarousel has some bugs, then the solution would be catching the bug). The only part is knowing which index is the one you would like to move to.
As a suggestion, I would start off by simplifying your delegate carouselDidEndScrollingAnimation method. Indeed, your carouselDidEndScrollingAnimation has a parameter called carousel, well, I think this is the only carousel you should ever be referring to in that method. If you don't see it, this is the reasoning: each of your carousel will stop scrolling and the carouselDidEndScrollingAnimation will be called; so that method will be called twice. Each time that method is executed you will modify the state of both carousel1 and carousel2 (by calling scrollToItemAtIndex); therefore, on each carousel you will call scrollToItemAtIndex twice.
This does no sound very correct to me. So you should find a way to scroll only carousel1 when carouselDidEndScrollingAnimation is called for carousel1 and to scroll only carousel2 when carouselDidEndScrollingAnimation is called for carousel2.
More generally, another point I would like to raise is that the idea of:
letting a carousel stop;
scrolling it again so that it reaches the desired position;
does not seem the best implementation possible since the user would see the carousel stopping and then starting over again.
The way I would approach this is by modifying directly iCarousel implementation so that it supports this specific behavior you need.
Concretely, give a look at the step method in iCarousel.m. This is called at each frame to produce the carousel animation. Now, in this method there is decelerating branch:
else if (decelerating)
{
CGFloat time = fminf(scrollDuration, currentTime - startTime);
CGFloat acceleration = -startVelocity/scrollDuration;
CGFloat distance = startVelocity * time + 0.5f * acceleration * powf(time, 2.0f);
scrollOffset = startOffset + distance;
[self didScroll];
if (time == (CGFloat)scrollDuration)
{
decelerating = NO;
if ([delegate respondsToSelector:#selector(carouselDidEndDecelerating:)])
{
[delegate carouselDidEndDecelerating:self];
}
if (scrollToItemBoundary || (scrollOffset - [self clampedOffset:scrollOffset]) != 0.0f)
{
if (fabsf(scrollOffset/itemWidth - self.currentItemIndex) < 0.01f)
{
//call scroll to trigger events for legacy support reasons
//even though technically we don't need to scroll at all
[self scrollToItemAtIndex:self.currentItemIndex duration:0.01];
}
else
{
[self scrollToItemAtIndex:self.currentItemIndex animated:YES];
}
}
else
{
CGFloat difference = (CGFloat)self.currentItemIndex - scrollOffset/itemWidth;
if (difference > 0.5)
{
difference = difference - 1.0f;
}
else if (difference < -0.5)
{
difference = 1.0 + difference;
}
toggleTime = currentTime - MAX_TOGGLE_DURATION * fabsf(difference);
toggle = fmaxf(-1.0f, fminf(1.0f, -difference));
}
}
}
and you see that when the carousel stops decelerating, it is scrolled again. This is exactly the same as you are doing, so you might find a way to modify this code and have the carousel scrolls exactly to the index you need. In this way you would get a far smoother spinning of the carousel.
Hope this helps and apologies for the lengthy reply.
Its a little difficult to know what the issue is here. Are you using a single NSMutableArray for the images and using the NSUserDefaults value to get the object at the index in the array?
Im not 100% sure on what is happening. What does the user do(and in what view) and what is triggered after that(which view is presented).
Are you trying to stop the "spinning" images on the image that is the same as the one picked from the previous view?
According to your images above, the images are off by a single index. Is this the case every time? Maybe there is an issue with your fetching from the array.
If you give me some more info I can help.
I looked through the code you pasted again and I think this might be your issue
if (twoSlot1 > [(UIImageView*)[self.carousel2 currentItemView] tag]){
[self.carousel1 scrollToItemAtIndex:(-twoSlot1)-2 duration: 3.5f];
} else {
[self.carousel1 scrollToItemAtIndex:-twoSlot1 duration: 3.5f];
}
On all other code blocks like that you have this where you call each carousel. In the above code you call carousel 1 twice.
if (slot2 > [(UIImageView*)[self.carousel1 currentItemView] tag]){
[self.carousel1 scrollToItemAtIndex:(-slot2)-2 duration: 3.0f];
} else {
[self.carousel1 scrollToItemAtIndex:-slot2 duration: 3.0f];
}
if (twoSlot2 > [(UIImageView*)[self.carousel2 currentItemView] tag]){
[self.carousel2 scrollToItemAtIndex:(-twoSlot2)-2 duration: 3.5f];
} else {
[self.carousel2 scrollToItemAtIndex:-twoSlot2 duration: 3.5f];
}
You call self.carousel1 when you should be calling number 2.
Is this correct?
Referring to your question. You want an array that does not change its members' indexes when a member is deleted from the array.
I guess you could use an NSMutableDictionary. It is an associative array so to say, where the indexes are of your choice and they remain unchanged when you delete a member from in between.
You may still use 0..n as your Index. You can still use some methods that you are familiar with from NSArray, such as count. You can use an enumerator to go through all members of the dictionary. On the other hand you can still use your for-loops as you are used to use them with arrays. Just be prepared that a) objectForKey:i may return nil if the key/index does not exist (e.g. was deleted) and that count retuns the number of the objects but not the highest index+1 as it does with arrays.
Not sure if I understand completely, but when one of the elements in your mutable array is deleted, rather than just deleting it, maybe insert it with another "dummy" place holder object? That way your indexes won't change at all when a delete occurs
I'm having a hard time understanding your overall problem, but from what I can gather the crux of your question is this:
Is there a way to make my array or my iCarousel.view not adjust their indexes when Im deleting.
I don't know whether it will solve your bigger issue, but using an NSMutableDictionary to simulate an array should allow you to do this. You can simply use the indices as the keys to the dictionary, and then when you remove the item associated with an index, no other indices will be adjusted as a result. For example:
NSMutableDictionary *arrayDict = [[NSMutableDictionary alloc] init];
[arrayDict setValue:foo forKey:[NSNumber numberWithInt:[arrayDict count]]];
[arrayDict setValue:bar forKey:[NSNumber numberWithInt:[arrayDict count]]];
[arrayDict setValue:fooBar forKey:[NSNumber numberWithInt:[arrayDict count]]];
And then you can access the object an at index with [arrayDict objectForKey:[NSNumber numberWithInt:index]].
Note that using an NSNumber for the key parameter of setValue:forKey: will generate a warning, but you can safely ignore this (or use the string representation if it bothers you).
I'm trying to implement openFlow in my project but I cant seem to get the images to show up on my uiview. What isnt clear to me is once I have the dictionary of image links, how do i tell AFOpenView that I want to use that dictionary object as my data source?
I've looked at the demo code and I see that when the flickr request finishes, he saves a copy of the dictionary results, counts them, and then tells OpenFlowView that there are x number of images, but what is never clear is how he tells OpenFlowView to use the dictionary with the results?
- (void)flickrAPIRequest:(OFFlickrAPIRequest *)inRequest didCompleteWithResponse:(NSDictionary *)inResponseDictionary
{
// Hold onto the response dictionary.
interestingPhotosDictionary = [inResponseDictionary retain];
int numberOfImages = [[inResponseDictionary valueForKeyPath:#"photos.photo"] count];
[(AFOpenFlowView *)self.view setNumberOfImages:numberOfImages];
}
See here: http://blog.objectgraph.com/index.php/2010/04/09/how-to-add-coverflow-effect-on-your-iphone-app-openflow/
This tutorial seems to suggest that you have to call the view's setImage method multiple times, once per image.
This tells me that the implementation is confusing and weird, but for this you have to blame the component's author.
The images are loaded on demand in the 'updateCoverImage:' method of AFOpenFlowView.m
'updateCoverImage:' calls 'openFlowView:requestImageForIndex:' in AFOpenFlowViewController.m, which uses interestingPhotosDictionary.
So, it is called on demand whenever an image needs to be loaded. It wraps an operation queue so the images are loaded outside the main thread.
First off, I'm a complete beginner.
That said, I thought an ambitious longer-term project/learning experience would be to create an app that displayed daily quotes, like those cheesy day-by-day calendars our grandmothers have in their bathrooms. I want it to have two per day, each one represented by a tab in a UISegmentedControl. That's the long term. Right now I'd be happy with getting a single day's worth of quotes functioning.
Onto the questions:
How can I get text saved in a .txt or .rtf file to be displayed in a UITextView? Preferably without using 'stringWithContentsOfFile,' since Xcode is telling me that's deprecated.
How can I get content from a different file (or maybe a different portion of the same file...?) to be displayed when the user taps the second segment?
If I can get it running so that those two conditions are met and I understand what's going on, I'll consider the day a success. Thanks!
1.
NSError *error = nil;
NSStringEncoding stringEncoding;
NSString *fileText = [NSString stringWithContentsOfFile:#"/path" usedEncoding:&stringEncoding error:&error];
myTextView.text = fileText;
The error and encoding are optional, and you can pass in nil for both. But if you care about the error, or what encoding the file was in they will have useful info in them after the string is created.
2.
Set the valueChanged outlet in Interface Builder to an IBAction on your controller, such as setSegmentValue:. Then, assuming you have an array of quote strings:
- (IBAction)setSegmentValue:(id)sender {
UISegmentedControl *control = (UISegmentedControl*)sender;
NSString *quote = [quotes objectAtIndex:control.selectedSegmentIndex];
myTextView.text = quote;
}
Even though stringWithContentsOfFile: is deprecated, stringWithContentsOfFile:usedEncoding:error: is not. That is the standard method to use for reading from files.
As for the second question, you simply test the state of the segmented control and perform as action based on it. Admittedly this is a high level answer but should get you going.
i have made one list of images + respective data in tableview.
it takes long time while loading
i want to make multithreading two methods
1> parsing of data
2> parsing of images
i want to execute parsing of data first after that i can select any of rows listed even though images not been loaded(/parsed) because the images is parsed after the parsing of data and it takes long time.
from where should i call these both the methods.
and how enable the selection on row after parsing of the data...
how to do multithread both the methods
waiting for your great responce
Thanking in advance
You likely don't want to use NSThreads - at least not directly.
What you do is subclass NSOperation.
There are a few ways to do what you have in mind. If you know the total number of rows in your table right from the start, then things are simpler:
Make a subclass of NSOperation called MyParseDataOperation. Then make one MyParseDataOperation for each row in your table. When the operation is done, you need to message your main thread with the resulting data.
Code below is full of errors, incomplete. etc.
ie in your MyParseDataOperation class:
MyParseDataOperation
-(id)initWithStuff:(NSURL*)stuff forTableRow:(int)row;
{
blah blah -
// here is where I make sure I have all the data I need for main() which is called in the background on some random thread at some future time.
}
-(void)main;
{
// use data like Urls, file names, etc passed in to the initWithStuff method
get stuff
parse stuff
// ok now you have the data
NSMutableDictionary* parsedData = [NSMutableDictionary dictionary];
[parsedData setObject:[NSNumber numberWithInt:row] forKey:#"row"];
[parsedData setObject:stuff i figured out forKey:#parsed];
[tableDataSource performSelectorOnMainThread:#selector(dataParsed) withObject:parsedData];
}