How to add NSArray in a video with AVMutableMetadataItem? - objective-c

I am trying to save video with custom NSArray metadata relevant for my app and trying to retrieve it when the user selects that video from the library.
I'm using the AVAssetExportSession function to add metadata.
I used the sample code AVMovieExporter, and I tried to change locationMetadata.value
http://developer.apple.com/library/ios/#samplecode/AVMovieExporter/Introduction/Intro.html#//apple_ref/doc/uid/DTS40011364
AVMutableMetadataItem *locationMetadata = [[AVMutableMetadataItem alloc] init];
locationMetadata.key = AVMetadataCommonKeyLocation;
locationMetadata.keySpace = AVMetadataKeySpaceCommon;
locationMetadata.locale = self.locale;
//locationMetadata.value = [NSString stringWithFormat:#"%+08.4lf%+09.4lf", self.location.coordinate.latitude, self.location.coordinate.longitude];
locationMetadata.value = [[NSArray alloc] initWithObjects: #"abc", #123,nil];
If I use value as a NSString there is no problem, but if I use a NSArray, it doesn't save the metadata.
Where is the problem?

Apple's documentation states:
NSString *const AVMetadataCommonKeyLocation;
I understand that to say the value must be a string, and cannot be an array.

Related

How to show polylines added in the source in mapbox ios?

I'm trying to show the polylines taken from a GeoJson then added to the same source but with poor results.
NSString *jsonString = #"{\"type\": \"FeatureCollection\",\"features\": [{\"type\": \"Feature\",\"properties\": {},\"geometry\": {\"type\": \"LineString\",\"coordinates\": [[4.873809814453125,52.3755991766591],[4.882049560546875,52.339534544106435],[4.94659423828125,52.34708539110632],[4.94659423828125,52.376437538867776],[5.009765625,52.370568669179654]]}},{\"type\": \"Feature\",\"properties\": {},\"geometry\": {\"type\": \"LineString\",\"coordinates\": [[4.73785400390625,52.32694693334544],[4.882049560546875,52.32778621884898],[4.872436523437499,52.29420237796669],[4.9713134765625,52.340373590787394]]}}]}";
NSData *jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
MGLShapeCollectionFeature *shapeCollectionFeature = (MGLShapeCollectionFeature *)[MGLShape shapeWithData:jsonData encoding:NSUTF8StringEncoding error:NULL];
MGLMultiPolyline *polylines = [MGLMultiPolyline multiPolylineWithPolylines:shapeCollectionFeature.shapes];
MGLShapeSource *source = [[MGLShapeSource alloc] initWithIdentifier:#"transit" shape:polylines options:nil];
[self.mapView.style addSource:source];
MGLLineStyleLayer *lineLayer = [[MGLLineStyleLayer alloc] initWithIdentifier:#"layer" source:source];
[self.mapView.style addLayer:lineLayer];
I logged the source object and inside there are the two polylines. But why are they not shown? what am I doing wrong?
I use mapbox sdk 3.7.6 for ios.
Are you using the -[MGLMapViewDelegate mapView:didFinishLoadingStyle] method to ensure that your map has properly initialized before you are adding the style layer? If not, you are likely running into a race issue where you are adding data that is immediately overwritten as the style is loading.
If you modify your code to ensure that the source and style aren't being added prematurely, I would expect your issues to resolve.
- (void)mapView:(MGLMapView *)mapView didFinishLoadingStyle:(MGLStyle *)style {
MGLShapeSource *source = [[MGLShapeSource alloc] initWithIdentifier:#"transit" shape:polylines options:nil];
[self.mapView.style addSource:source];
MGLLineStyleLayer *lineLayer = [[MGLLineStyleLayer alloc] initWithIdentifier:#"layer" source:source];
[self.mapView.style addLayer:lineLayer];
}
⚠️ Disclaimer: I currently work at Mapbox ⚠️

plist wont pull into my NSMutableArray. am i missing something?

So here's my code. I'm trying to display content from a plist into a table and i keep running into errors. ive been at it all day so i'm probably missing something fairly easy. hope you guys can figure out why when i build, the table is empty.
here is my plist (without headers):
<array>
<dict>
<key>word</key>
<string>AWord1</string>
<key>definition</key>
<string>here is a definition</string>
<key>partOfSpeech</key>
<string>here is a part of speech</string>
</dict>
<dict>
<key>word</key>
<string>Bword1</string>
<key>definition</key>
<string>here is a definition</string>
<key>partOfSpeech</key>
<string>here is a part of speech</string>
</dict>
</array>
</plist>
edit: closing tags were missing due to misformatting - fixed
ok. here is my new code. i NSLog'd and decided to back up to before i went to plist. so, if you could help. how would you suggest i pull this data from plist instead (assuming the data is in the plist)
//Initialize the array.
listOfItems = [[NSMutableArray alloc] init];
NSArray *countriesToLiveInArray = [NSArray arrayWithObjects:#"Iceland", #"Greenland", #"Switzerland", #"Norway", #"New Zealand", #"Greece", #"Italy", #"Ireland", nil];
NSDictionary *countriesToLiveInDict = [NSDictionary dictionaryWithObject:countriesToLiveInArray forKey:#"Countries"];
NSArray *countriesLivedInArray = [NSArray arrayWithObjects:#"India", #"U.S.A", #"Test", #"Test", #"Test", #"Test", #"Test", #"Test", #"Test", #"Test", #"Test", #"Test", #"Test", #"Test", #"Test", #"Test", nil];
NSDictionary *countriesLivedInDict = [NSDictionary dictionaryWithObject:countriesLivedInArray forKey:#"Countries"];
[listOfItems addObject:countriesToLiveInDict];
[listOfItems addObject:countriesLivedInDict];
//Initialize the copy array.
copyListOfItems = [[NSMutableArray alloc] init];
//Set the title
self.navigationItem.title = #"Countries";
//Add the search bar
self.tableView.tableHeaderView = searchBar;
searchBar.autocorrectionType = UITextAutocorrectionTypeNo;
searching = NO;
letUserSelectRow = YES;
i feel as though i'm still not actually telling it to parse the data from the plist. i've only init'd it. thoughts?
Your code seems very incomplete, it doesn't bear much relation to the plist. Here are a few issues
as noted by H2CO3 and Fogmeister, the plist as you show it is missing a closing </array> tag (but lets assume that is a typo in the question)
you load the entire array into a single entry in a countriesToLiveIn dictionary (against the key "definition")
countriesToLiveIn becomes a single object in the array listOfItems
you initialise a copyOfListItems array but then don't do anything with it
Then you do not indicate where the table is getting it's date from.
If it is from copyOfListItems, well that array is empty .: empty table.
If it is from listOfItems you will be parsing the countriesToLiveIn dictionary somehow, but you don't show how.
If it is directly from the plist array countriesToLiveInArray then that missing </array> tag could be a clue. You would also need to be parsing the array's contained dictionaries somehow, and you don't show us that code, there could be something wrong there.
To get further with this I suggest copious use of NSLog to find out how far the data gets in to your objects. Perhaps you could expand your question with the results if you are still getting stuck.
update
Following your updated code, my first suspicion is that there was a problem with your URL.
in your previous edit this is the suspect line
NSMutableArray *wordListArray = [[NSMutableArray alloc] initWithContentsOfURL: [NSURL URLWithString:#"http://url.com/dictpPlist.plist"]];
You need to NSLog right after it:
NSLog (#"wordListArray %#", wordListArray);
To confirm that you are not picking up the plist here. At least then we isolate the problem to this point in your code.
Then we need to question the URL - is it correct? how did the plist get there? can you verify it independently? Is it a local file URL or a network URL?
If you are accessing a network resource, this is quite likely your problem. The initWithContentsOfURL methods should only really be used with local filesystem URLs. See for example
initwithcontentsofurl methods considered harmful.
You should be using NSURLConnection asynchronously instead. Apple is a little cagey about this also:
aURL: The location of a file containing a string representation of an array produced by the writeToURL:atomically: method.
Assuming this is your issue, why don't you get it working with a local filesystem plist first.
Write one in code from your listOfItems array:
- (void) createPlist
{
NSFileManager* fManager = [NSFileManager defaultManager];
NSError* error;
NSURL* docsURL = [fManager URLForDirectory:NSDocumentDirectory
inDomain:NSUserDomainMask
appropriateForURL:nil
create:NO
error:&error];
NSURL* plistURL = [docsURL URLByAppendingPathComponent:#"testlist.plist"];
[listOfItems writeToURL:plistURL atomically:YES];
}
Read it back in, verify it works, then sort out how to do the same over a network.
try below code
// Path to the plist (in the application bundle)
NSString *path = [[NSBundle mainBundle] pathForResource:
#"dictpPlist" ofType:#"plist"];
// Build the array from the plist
NSMutableArray *array2 = [[NSMutableArray alloc] initWithContentsOfFile:path];
// Show the string values
for (NSString *str in array2)
NSLog(#"--%#", str);

xpath Table Contents into an array

How would I use xPath under the hpple Objective-C wrapper to extract the elements out of this table. Ideally I would like to put the addresses and prices into an array or dictionary.
I have been attempting to use the hpple objective c wrapper to pull the data out of the table located here: http://www.gaspry.com/index.php?zipcode=02169&action=search but haven't succeeded in getting the correct xpath query to pull out the information. Ideally, I would like to store this information in a set of arrays one, for addresses, and one for each of the prices. I am stuck on how to retrieve all of the information from the table and am unsure that my xPath is correct
My Code Thus Far is:
- (void)viewDidLoad {
[super viewDidLoad];
//Url Information
NSString *urlAddress = #"http://www.gaspry.com/index.php?zipcode=02169&action=search";
NSURL *url = [NSURL URLWithString:urlAddress];
NSData *htmlData = [[NSData alloc] initWithContentsOfURL:url];
//Start Parsing
TFHpple *xpathParser = [[TFHpple alloc] initWithHTMLData:htmlData];
NSArray *elements = [xpathParser search:#"//tBody[tr]"]; // get the table information
TFHppleElement *element = [elements objectAtIndex:0];
NSString *bodyTag = [element content];
NSLog(#"%#", bodyTag);
[xpathParser release];
[htmlData release];
}
One advice, a search path is case sensitive so make sure you use right one.
search query for :
#"//tbody//tr[1]//td[1]"
will get you address and change column "td[#]" to access other things you may want to store.
I'm not sure but address won't be parse correctly, that is, above search query will result after
tag but won't give you content before tag.
Hope this help :D

How do i grab numbers from a Table on a website in my Cocoa App?

Ok this is a more specific version of my last question.
So on a website there exists some data that is coded in HTML into a table.
In my Cocoa app, I want to download the html code of the website and then read through the html and snag the data from it. I was hoping someone could point out some useful classes/methods for accomplishing the retrieval of the website and putting it into some format where I can read through the code in my program?
Thanks in advance!
Try using hpple, it's an HTML parser for ObjC.
here's an example using it:
#import "TFHpple.h"
NSData *data = [[NSData alloc] initWithContentsOfFile:#"example.html"];
// Create parser
xpathParser = [[TFHpple alloc] initWithHTMLData:data];
//Get all the cells of the 2nd row of the 3rd table
NSArray *elements = [xpathParser search:#"//table[3]/tr[2]/td"];
// Access the first cell
TFHppleElement *element = [elements objectAtIndex:0];
// Get the text within the cell tag
NSString *content = [element content];
[xpathParser release];
[data release];

Reading samples via AVAssetReader

How do you read samples via AVAssetReader? I've found examples of duplicating or mixing using AVAssetReader, but those loops are always controlled by the AVAssetWriter loop. Is it possible just to create an AVAssetReader and read through it, getting each sample?
Thanks.
It's unclear from your question whether you are talking about video samples or audio samples. To read video samples, you need to do the following:
Construct an AVAssetReader:
asset_reader = [[AVAssetReader alloc] initWithAsset:asset error:&error];
(error checking goes here)
Get the video track(s) from your asset:
NSArray* video_tracks = [asset tracksWithMediaType:AVMediaTypeVideo];
AVAssetTrack* video_track = [video_tracks objectAtIndex:0];
Set the desired video frame format:
NSMutableDictionary* dictionary = [[NSMutableDictionary alloc] init];
[dictionary setObject:[NSNumber numberWithInt:<format code from CVPixelBuffer.h>] forKey:(NSString*)kCVPixelBufferPixelFormatTypeKey];
Note that certain video formats just will not work, and if you're doing something real-time, certain video formats perform better than others (BGRA is faster than ARGB, for instance).
Construct the actual track output and add it to the asset reader:
AVAssetReaderTrackOutput* asset_reader_output = [[AVAssetReaderTrackOutput alloc] initWithTrack:video_track outputSettings:dictionary];
[asset_reader addOutput:asset_reader_output];
Kick off the asset reader:
[asset_reader startReading];
Read off the samples:
CMSampleBufferRef buffer;
while ( [asset_reader status]==AVAssetReaderStatusReading )
buffer = [asset_reader_output copyNextSampleBuffer];
damian's answer worked for me with video, and one minor modification: In step 3, I think the dictionary needs to be mutable:
NSMutableDictionary* dictionary = [[NSMutableDictionary alloc] init];