Potential iOS memory leak with CFUUIDBytes - objective-c

I have a static method defined as follows:
+(NSString*)getNewIdAsBase64
{
// Grab new uuid
CFUUIDRef originalUuid = CFUUIDCreate(nil);//create a new UUID
//NSLog(#"Step a: original uuidObj = %#",originalUuid);
CFUUIDBytes originalBytes = CFUUIDGetUUIDBytes (originalUuid);//ISSUE
NSData* data88 = [NSData dataWithBytes: &originalBytes length: sizeof(originalBytes)];
NSString* hugo = [data88 base64EncodedString];
return hugo;
}
When I run Product->Analyze on my project then the line commented with //ISSUE raises the following issue:
Potential leak of an object alocated on line 23 and stored into 'originalUuid'
What am I doing wrong, and how do I fix it?
Thanks

You will need to release the object you create even if you are using ARC:
+(NSString*)getNewIdAsBase64
{
// Grab new uuid
CFUUIDRef originalUuid = CFUUIDCreate(nil);//create a new UUID
//NSLog(#"Step a: original uuidObj = %#",originalUuid);
CFUUIDBytes originalBytes = CFUUIDGetUUIDBytes (originalUuid);//ISSUE
NSData* data88 = [NSData dataWithBytes: &originalBytes length: sizeof(originalBytes)];
NSString* hugo = [data88 base64EncodedString];
CFRelease(originalUuid);
return hugo;
}

Related

Convert AVPlayer NSData to NSString (Or player format)

I need to know how to convert saved NSData from an AVPlayer back into a playable format. But I cannot figure out how to convert this NSData into a dataString, which would then allow me to create and NSUrl. Let's say I have the following code:
NSURL *videoUrl=(NSURL*)[info objectForKey:UIImagePickerControllerMediaURL];
self.data=[NSData dataWithContentsOfURL:videoUrl];
Now later on when I get this data back, I call:
NSString *dataString = [NSString stringWithUTF8String:[self.data bytes]];
But the dataString is always nil. Why? Am I decoding it in the wrong format or something?
A URL is a reference to data. The data is a (possibly complicated) encoding of something like a movie.
I am not sure exactly what you are asking, but I think you want to get the data (as an NSData object) and then save it somewhere. If this is correct, then what you need to do is
[self.data writeToFile:myFilePath atomically:YES]
where myFilePath is a path to somewhere where you can store files.
You could implement AVAssetResourceLoaderDelegate to provide data for AVPlayer.
func resourceLoader(resourceLoader: AVAssetResourceLoader!, shouldWaitForLoadingOfRequestedResource loadingRequest: AVAssetResourceLoadingRequest!) -> Bool {
if let data = videoData {
dispatch_async(dispatch_get_main_queue()) { () -> Void in
if let infoRequest = loadingRequest.contentInformationRequest {
infoRequest.contentType = "public.mpeg-4" // UTI
infoRequest.contentLength = Int64(data.length)
infoRequest.byteRangeAccessSupported = true
}
if let request = loadingRequest.dataRequest {
let part = data.subdataWithRange(NSRange(location: Int(request.requestedOffset), length: Int(request.requestedLength)))
request.respondWithData(part)
}
loadingRequest.finishLoading()
}
return true
}
return false
}
To create an AVPlayer:
let asset = AVURLAsset(URL: NSURL(scheme: "yourcustomscheme", host: nil, path: "/pathtovideo"), options: nil)
asset.resourceLoader.setDelegate(self, queue: dispatch_get_main_queue())
let item = AVPlayerItem(asset: asset)
let player = AVPlayer(playerItem: item)

I don't understand how to use the JSON data in Xcode

I have successfully downloaded and parsed (I think) the JSON data
NSURL *quoteURL = [NSURL URLWithString:#"http://www.qwoatzz.com"];
NSData *jsonData = [NSData dataWithContentsOfURL:quoteURL];
NSError *error = nil;
NSDictionary *dataDictionary = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:&error];
However, I'm not too sure how to actually use the JSON data. If the JSON file has an array with two keys, how do I get a value from one of these keys at a specific index (the first one for example) and use that to change the text of a label (I know how to do that, it's just the JSON part I am stuck on)?
2014-10-20 19:46:10.616 Qwoatz-2[3147:454481] dataDictionary : {
count = 10;
"count_total" = 1871;
pages = 188;
posts = (
{
author = "Jason Seifer";
date = "2014-10-20 13:54:11";
id = 24317;
thumbnail = "http://blog.teamtreehouse.com/wp-content/uploads/2014/10/1634685862_92b26b9167_o-150x150.jpg";
title = "What Employers Are Looking For in a Junior Rails Developer";
url = "http://blog.teamtreehouse.com/employers-looking-junior-rails-developer";
},
{
author = "Zac Gordon";
date = "2014-10-16 09:27:38";
id = 24296;
thumbnail = "http://blog.teamtreehouse.com/wp-content/uploads/2014/10/brochure-site-150x150.png";
title = "When is WordPress.com the Right Solution?";
url = "http://blog.teamtreehouse.com/wordpress-com-right-solution-website";
},
{
author = "Gill Carson";
date = "2014-10-15 12:52:43";
id = 24287;
thumbnail = "http://blog.teamtreehouse.com/wp-content/uploads/2014/10/Tahoe_team-Photo-150x150.jpg";
title = "We Are Family – The Whole Team!";
url = "http://blog.teamtreehouse.com/family";
},
{
author = "Jason Seifer";
date = "2014-10-14 15:26:11";
id = 24292;
thumbnail = "http://blog.teamtreehouse.com/wp-content/uploads/2014/10/Chartist-Simple-responsive-charts-2014-10-14-15-24-43-150x150.jpg";
title = "Responsive Charts";
url = "http://blog.teamtreehouse.com/responsive-charts";
},
{
author = "Guil Hernandez";
date = "2014-10-13 09:28:05";
id = 24228;
thumbnail = "http://blog.teamtreehouse.com/wp-content/uploads/2014/09/blend-mode-mult-150x150.jpg";
title = "Cutting-Edge CSS Features You Can Use Today";
url = "http://blog.teamtreehouse.com/cutting-edge-css-features-can-use-today";
},
{
author = "Faye Bridge";
date = "2014-10-10 09:00:45";
id = 24230;
thumbnail = "http://blog.teamtreehouse.com/wp-content/uploads/2014/09/Nick-Bryan-150x150.jpg";
title = "After Just 6 Months Learning Nick is a full-time Web Developer";
url = "http://blog.teamtreehouse.com/6-months-nick-now-full-time-web-developer-major-computing-firm";
},
{
author = "Pasan Premaratne";
date = "2014-10-09 13:59:23";
id = 24250;
thumbnail = "http://blog.teamtreehouse.com/wp-content/uploads/2014/10/Screen-Shot-2014-10-06-at-5.57.16-PM-150x150.png";
title = "Making a Network Request in Swift";
url = "http://blog.teamtreehouse.com/making-network-request-swift";
},
{
author = "Zac Gordon";
date = "2014-10-09 09:21:29";
id = 24278;
thumbnail = "http://blog.teamtreehouse.com/wp-content/uploads/2014/10/wordpress_themes-150x150.jpg";
title = "New Course: WordPress Theme Development";
url = "http://blog.teamtreehouse.com/new-course-wordpress-theme-development";
},
{
author = "Dave McFarland";
date = "2014-10-08 13:47:55";
id = 24255;
thumbnail = "http://blog.teamtreehouse.com/wp-content/uploads/2014/10/Screen-Shot-2014-10-06-at-1.02.40-PM-150x150.png";
title = "How to Install Node.js and NPM on a Mac";
url = "http://blog.teamtreehouse.com/install-node-js-npm-mac";
},
{
author = "Jason Seifer";
date = "2014-10-07 16:15:00";
id = 24273;
thumbnail = "http://blog.teamtreehouse.com/wp-content/uploads/2014/10/html5-device-mockups-150x150.jpg";
title = "Device Mockups";
url = "http://blog.teamtreehouse.com/device-mockups";
}
);
status = ok;
}
An example JSON file that was parsed.
Loop through the dictionary:
for(NSString *key in dataDictionary) {
id myObject = [dataDictionary objectForKey:key];
//do something with myObject
}
An NSDictionary is not an ordered collection, so there is no guarantee that looping through a dictionary as shown above will always loop through the keys in the same order. Apple doesn't provide an ordered dictionary with Cocoa/Cocoa Touch, and generally it is a bad idea to subclass NSDictionary or NSMutableDictionary as they are part of a class cluster.
Looking at the text from your example, posts is actually an array full of dictionaries. Assuming all the keys in your example are constant across the JSON files that you will be fetching, you could retrieve it using
NSArray *posts = [dataDictionary arrayForKey:#"posts"];
This array already appears to be ordered by date. You could then get the title for each post
for(int i = 0; i < [posts count]; i++) {
NSString *title = [((NSDictionary *)(posts[i])) objectForKey:#"title"];
//do something with title
}
1) Do you know the data is an array?
the JSON file has an array with two keys,...
value from one of these keys at a specific index...
This is somewhat of a mixed metaphor for me. When I have a JSON Array or NSArray, I tend to only think of indices (since that how arrays are ordered), and when I have JSON Objects or NSDictionaries, I tend to think of keys.
So, does the return value look like this:
[ "cat", 1, "a" ]
or does the data look like this:
{
"cat": {
"count": 1,
"tag": "a"
}
}
The first example is an Array with 3 elements; the second is an Object with 1 member that itself has 2 members.
2) If the data is correctly parsed as either an NSArray, or NSDictionary ...
Then you simply need to extract the data you want, with the accessors available on either container.
E.g.
NSArray *a = ...
[a firstObject];
[a objectAtIndex:0]; // same as above
NSDictionary *d = ...
d[#"memberName"];
[d objectForKey:#"memberName"]; // same as above
You'll want to actually save that data, or pass it to be processed, instead of just invoking the accessor.
UPDATE: based on the example data updated in the question.
One method is that you could extract the data both a bit manually, and iteratively.
NSDictionary *dataDictionary = ...
NSInteger count = [[dataDictionary objectForKey:#"count"] integerValue];
NSInteger countTotal = [[dataDictionary objectForKey:#"count_total"] integerValue];
NSInteger pagesCount = [[dataDictionary objectForKey:#"pages"] integerValue];
NSString *status = [dataDictionary objectForKey:#"status"];
NSArray *posts = [dataDictionary objectForKey:#"posts"];
for (NSDictionary *post in posts) {
for (NSString *key in post) {
NSLog(#"%#: %#", key, post[key]);
}
}
When you log dataDictionary, unquoted elements that are clearly strings are strings, elements in quotes are strings, integers and other numbers are likely usable numbers, but they may be strings (depends on return format), the date will be a string (and you can use NSDate and NSDateFormatter to pretty print it), status is just a string; for posts, the '(' and ')' wrap an array, and '{','}' wrap dictionaries.
UPDATE 2:
If you really want to do advanced searching, you can use NSPredicate to filter NSDictionary's or NSArray's. For example, something like the following would work:
#import <Foundation/Foundation.h>
int main(int argc, char *argv[]) {
#autoreleasepool {
NSDictionary *data = #{
#"stuff": #1,
#"posts": #[
#{ #"id": #1, #"title": #"one" },
#{ #"id": #2, #"title": #"two" },
#{ #"id": #3, #"title": #"three" },
#{ #"id": #4, #"title": #"four" },
#{ #"id": #5, #"title": #"five" },
]
};
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SELF.id == %#", #4];
NSString *title = [[data[#"posts"] filteredArrayUsingPredicate:predicate] firstObject];
NSLog(#"title: %#", title);
}
}
prints
title: {
id = 4;
title = four;
}
You can use JSONModel Framework
JSONModel is a data model framework for iOS and OSX. It's written in Objective-C and helps you in several different ways.
You can read more about its key features below:
Rapidly write model code
Validation of the model's input
Atomic data
Type casting between JSON and Obj-C
Built-in data transformers
Custom data transformers
Model cascading
Convert back & forth from/to JSON
Persist model state in memory or file
Create models straight from the Internet
Automatic model compare methods
Note Please make sure your properties name match with key name in JSON
JSONModel Framework
GitHub Link

NSString to NSData using stringWithUTF8String and dataUsingEncoding returns nil

When i convert the NSString to NSData and back i get a nil result
NSString * test = #"Wft0r3qkzXd5TDBeCahUB3MtHuc8Axwr";
NSData * testData = [test dataUsingEncoding:NSUTF8StringEncoding];
NSString * result = [NSString stringWithUTF8String:[testData bytes]];
Out
Printing description of testData:
<57667430 7233716b 7a586435 54444265 43616855 42334d74 48756338 41787772>
Printing description of result:
<nil>
I believe you're looking for this method:
- (instancetype)initWithData:(NSData *)data
encoding:(NSStringEncoding)encoding
From the apple doc's here: NSString class reference
In Swift, you can see the round-trip from string to data to string as follows:
let srcString = "Wft0r3qkzXd5TDBeCahUB3MtHuc8Axwr"
let stringAsData = srcString.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)!
let dstString = NSString(data: stringAsData, encoding: NSUTF8StringEncoding)!
dstString // => "Wft0r3qkzXd5TDBeCahUB3MtHuc8Axwr"
Basically, you want to use NSString(data:NSData,encoding:UInt) not NSString(UTF8String:UnsafePointer<Int8>).
An NSData is a Cocoa object that wraps a buffer of bytes. But the method you were using takes an UnsafePointer<Int8>, in other words, a raw pointer, which is just a numerical memory address pointing to the start of an array of bytes.
Swift 3
let string = "aHft0r3qkzjuh5rdsaeCahUB3MtHuc8Axwrfdvxgf"
let stringData = string.data(using: String.Encoding.utf8, allowLossyConversion: false)!
let finalString = NSString(data: stringData, encoding: String.Encoding.utf8.rawValue)!;

Converting String into bit in iOS

var index=2;
var validFor="CAAA";
function isDependentValue(index, validFor)
{
var base64 = new sforce.Base64Binary("");
var decoded = base64.decode(validFor);
var bits = decoded.charCodeAt(index>>3);
return ((bits & (0x80 >> (index%8))) != 0);
}
The above code is written in Javascript.I have to do the same in my iOS app.How can i do it with Objective-c.I have decoded the validFor string by using of this POST
Need help on this
If you are looking to convert a string to base64, the code below shows a brief example:
NSData *nsdata = [#"String to encode"
dataUsingEncoding:NSUTF8StringEncoding];
// Get NSString from NSData object in Base64
NSString *base64Encoded = [nsdata base64EncodedStringWithOptions:0];

Why is the Ejectable property of a DADisk always false?

I'm trying to get a list of all ejectable disks using the Disk Arbitration framework. The problem is that the Ejectable property is always false (even when diskutil info says Ejectable: Yes). What's going on? Do I need to do a DADiskClaim first or something?
- (NSArray *)disks {
NSMutableArray *disks = #[].mutableCopy;
// Get a list of everything in /Volumes/
NSArray *volumes = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:#"/Volumes/" error:NULL];
DASessionRef session = DASessionCreate(kCFAllocatorDefault);
// Use NSSet for easy object finding
NSMutableSet *bsdNamesOfDisks = #[].mutableCopy;
for (NSString *volume in volumes) {
// Create the URL for the volume mount point
NSURL *volumeURL = [NSURL URLWithString:[[NSString stringWithFormat:#"/Volumes/%#", volume] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
// Create DADisk for the volume
DADiskRef volumeDisk = DADiskCreateFromVolumePath(kCFAllocatorDefault, session, (__bridge CFURLRef)volumeURL);
// Filter out files/directories that aren't volumes
if (volumeDisk) {
// Get disk description
NSDictionary *description = (__bridge_transfer NSDictionary *)DADiskCopyDescription(volumeDisk);
// Get BSD name and ejectable property
NSString *bsdName = description[(__bridge id)kDADiskDescriptionMediaBSDNameKey];
CFBooleanRef ejectable = (__bridge CFBooleanRef)description[(__bridge id)kDADiskDescriptionMediaEjectableKey];
// Check to see if this is a volume we're interested in
if (bsdName && ejectable && CFBooleanGetValue(ejectable)) {
// Deletes "disk" in "disk0s1" and separates the numbers
NSArray *numbersInName = [[bsdName substringFromIndex:4] componentsSeparatedByCharactersInSet:[NSCharacterSet letterCharacterSet]];
// Scan the first number
NSScanner *scanner = [NSScanner scannerWithString:numbersInName[0]];
NSInteger diskNumber;
[scanner scanInteger:&diskNumber];
// Construct BSD name for the whole disk
NSString *bsdDiskName = [NSString stringWithFormat:#"disk%ld", diskNumber];
// Check to see if we already added this disk to our array (e.g. disk0s1 and disk0s2 both give disk0)
if (![bsdNamesOfDisks containsObject:bsdDiskName]) {
// Create DADisk for the whole disk
DADiskRef disk = DADiskCreateFromBSDName(kCFAllocatorDefault, session, bsdDiskName.UTF8String);
// Add DADisk to disk array and BSD name to name array
[disks addObject:(__bridge_transfer id)disk];
[bsdNamesOfDisks addObject:bsdDiskName];
}
}
CFRelease(volumeDisk);
}
}
CFRelease(session);
return disks.copy;
}