I am getting leak at:
NSString *firstNameStr = [NSString stringWithFormat:#"%s",firstNameString];
CODE:
+(NSString *)getValueForProperty:(ABPropertyID)propertyId
forContact:(NSString *)contactId
{
if (addressBook == nil)
{
addressBook = ABAddressBookCreate();
}
ABRecordID contactIntId = [contactId intValue];
ABRecordRef person;
person = ABAddressBookGetPersonWithRecordID(addressBook, contactIntId);
CFStringRef firstName;
char *firstNameString;
firstName = ABRecordCopyValue(person, propertyId);
// Paso a char* los datos para que se puedan escribir
static char* fallback = "";
int fbLength = strlen(fallback);
int firstNameLength = fbLength;
bool firstNameFallback = true;
if (firstName != NULL)
{
firstNameLength = (int) CFStringGetLength(firstName);
firstNameFallback = false;
}
if (firstNameLength == 0)
{
firstNameLength = fbLength;
firstNameFallback = true;
}
firstNameString = malloc(sizeof(char)*(firstNameLength+1));
if (firstNameFallback == true)
{
strcpy(firstNameString, fallback);
}
else
{
CFStringGetCString(firstName, firstNameString,
10*CFStringGetLength(firstName), kCFStringEncodingASCII);
}
if (firstName != NULL)
{
CFRelease(firstName);
}
NSString *firstNameStr = [NSString stringWithFormat:#"%s",firstNameString];
free(firstNameString);
return firstNameStr;
}
That means that the object allocated at that point is leaked. In this case, most likely because you over-retained it somewhere and failed to release it.
You need to carefully examine the lifespan of that particular string and figure out where you might be overwriting the reference without a release.
Build & Analyze might help considerably.
Related
I am trying to convert some Objective C code to Swift and can't manage to do it right with subscripting.
This is the method I am trying to migrate to Swift:
- (NSArray *)rangesOfSubstringAlphaNumeric:(NSString *)substring rangesLimit:(NSUInteger)rangesLimit {
NSAssert(rangesLimit, #"A range limit grather than 0 must be specified");
if (!substring.length) {
return nil;
}
static NSCharacterSet * restrictedCharacters = nil;
if (!restrictedCharacters) {
restrictedCharacters = [[NSCharacterSet alphanumericCharacterSet] invertedSet];
}
NSArray * substrings = [substring componentsSeparatedByCharactersInSet:restrictedCharacters];
NSMutableArray * allRanges = [NSMutableArray array];
NSString *searchedString = self;
for (NSString *stringToMatch in substrings) {
if (![stringToMatch isEqualToString:#""]) {
NSRange aRange;
NSUInteger lastLocation = 0;
NSUInteger foundRanges = 0;
while (foundRanges++ < rangesLimit &&
(aRange = [searchedString localizedStandardRangeOfString:stringToMatch]).location != NSNotFound) {
searchedString = [searchedString substringFromIndex:aRange.location + aRange.length];
aRange.location = aRange.location + lastLocation;
lastLocation = aRange.location + aRange.length;
[allRanges addObject:[NSValue valueWithRange:aRange]];
}
}
}
return allRanges.count ? [allRanges copy] : nil;
}
I got stuck on the subscripting part since it seems I cannot assign integer values to Indexes and conversion from Index to Int is out of hand for me I'm kind of stuck, this is what I managed to do:
func rangesOfAlphanumeric(substring: String, limit: UInt) -> [Range<String.Index>] {
guard limit > 0, !substring.isEmpty else {
if limit == 0 {
assert(false, "limit must be greather than 0")
}
return []
}
var searchedString = self
let substrings = substring.components(separatedBy: NSCharacterSet.restricted)
for stringToMatch in substrings {
if !stringToMatch.isEmpty {
// var aRange: Range<String.Index>?
// var lastLocation: UInt = 0
// var foundRanges: UInt = 0
// while foundRanges < limit,
// let tempRange = searchedString.localizedStandardRange(of: stringToMatch),
// !tempRange.isEmpty {
//
// searchedString = String(searchedString[tempRange.upperBound...])
// if let lastLocation = lastLocation {
// aRange = temp
// }
// }
}
}
}
UPDATE: Solution below.
Managed to resolve the issue using the ranges function posted here:
func rangesOfAlphanumeric(substring: String) -> [Range<String.Index>] {
var searchedString = self
let substrings = substring.components(separatedBy: NSCharacterSet.restricted)
return substrings.compactMap { (stringToMatch) -> [Range<String.Index>]? in
guard !stringToMatch.isEmpty else {
return nil
}
let ranges = searchedString.ranges(of: stringToMatch, options: [
.diacriticInsensitive,
.caseInsensitive
])
if let lastRange = ranges.last {
searchedString = String(searchedString[index(after: lastRange.upperBound)])
}
return ranges
}.flatMap{$0}
}
I created this repo with swift 5 is very easy to use
all is already set up. you have just to change the IAP ids
The Github repo
I am using LaunchAtLoginController for one of my project and in the following method there is always a NSArray leaking memory. As you can see I cast a CFArrayRef to a NSArray (__bridge NSArray*). I thought I could solve it using __bridge_transfer, but the app crashes (EXC_BAD_ACCESS). Is it because one of the items in the array is returned by the method?
- (LSSharedFileListItemRef) findItemWithURL: (NSURL*) wantedURL inFileList: (LSSharedFileListRef) fileList
{
if (wantedURL == NULL || fileList == NULL)
return NULL;
NSArray *listSnapshot = (__bridge NSArray*)(LSSharedFileListCopySnapshot(fileList, NULL));
LSSharedFileListItemRef itemToReturn = NULL;
for (id itemObject in listSnapshot) {
LSSharedFileListItemRef item = (__bridge LSSharedFileListItemRef) itemObject;
UInt32 resolutionFlags = kLSSharedFileListNoUserInteraction | kLSSharedFileListDoNotMountVolumes;
CFURLRef currentItemURL = NULL;
LSSharedFileListItemResolve(item, resolutionFlags, ¤tItemURL, NULL);
if (currentItemURL && CFEqual(currentItemURL, (__bridge CFTypeRef)(wantedURL)))
{
CFRelease(currentItemURL);
itemToReturn = item;
} else {
if (currentItemURL)
CFRelease(currentItemURL);
if (item)
CFRelease(item);
}
}
return itemToReturn;
}
This are two methods that call (LSSharedFileListItemRef) findItemWithURL: (NSURL*) wantedURL inFileList: (LSSharedFileListRef) fileList. Although I managed to release the item returned, I can never release the NSArray that, obviously, leaks memory.
- (BOOL) willLaunchAtLogin: (NSURL*) itemURL
{
LSSharedFileListItemRef item = [self findItemWithURL:itemURL inFileList:loginItems];
BOOL willLaunchAtLogin = !!item;
if (item)
CFRelease(item);
return willLaunchAtLogin;
}
- (void) setLaunchAtLogin: (BOOL) enabled forURL: (NSURL*) itemURL
{
LSSharedFileListItemRef appItem = [self findItemWithURL:itemURL inFileList:loginItems];
if (enabled && !appItem) {
LSSharedFileListItemRef itemRef = LSSharedFileListInsertItemURL(loginItems, kLSSharedFileListItemBeforeFirst,
NULL, NULL, (__bridge CFURLRef)itemURL, NULL, NULL);
if (itemRef)
CFRelease(itemRef);
} else if (!enabled && appItem) {
LSSharedFileListItemRemove(loginItems, appItem);
}
if (appItem)
CFRelease(appItem);
}
I tried everything that I could think of to solve this but with no success. What am I missing?
I am trying to get all the startup(login) application of my OSX10. In order to do so I have written the this code (given below):
-(NSMutableArray*)getStartUpApplicaitonPaths{
// Get the LoginItems list.
LSSharedFileListRef loginItemsRef = LSSharedFileListCreate(NULL, kLSSharedFileListSessionLoginItems, NULL);
if (loginItemsRef == nil) return nil;
// Iterate over the LoginItems.
NSArray *loginItems = (__bridge NSArray *)LSSharedFileListCopySnapshot(loginItemsRef, nil);
NSMutableArray* data = [NSMutableArray arrayWithArray:loginItems];
return data;
}
From the above code I am getting an NSMutableArray of __NSCFType objects. When I am trying to get the path by converting a object of the array
NSString* file = [NSString stringWithFormat:#"%#", [startupFiles objectAtIndex:0]];
I am getting the result given below:
BundleBinding [0x103] URL:
file:///Applications/iTunes.app/Contents/MacOS/iTunesHelper.app/
bundle identifier: com.apple.iTunesHelper iTunesHelper
I need to parse the URL of and Identifier from the string given above. Please help.
The objects ar eof type: LSSharedFileListItem which is only documented in the header file.
Here is some code that may help, it will NSLog() all the file names:
NSURL *itemURL = [[NSBundle mainBundle] bundleURL];
CFURLRef URLToToggle = (__bridge CFURLRef)itemURL;
LSSharedFileListRef loginItems = LSSharedFileListCreate(kCFAllocatorDefault, kLSSharedFileListSessionLoginItems, /*options*/ NULL);
if (loginItems) {
UInt32 seed = 0U;
Boolean found;
CFArrayRef currentLoginItems = LSSharedFileListCopySnapshot(loginItems,
&seed);
const CFIndex count = CFArrayGetCount(currentLoginItems);
for (CFIndex idx = 0; idx < count; ++idx) {
LSSharedFileListItemRef item = (LSSharedFileListItemRef)CFArrayGetValueAtIndex(currentLoginItems, idx);
CFURLRef outURL = NULL;
const UInt32 resolutionFlags = kLSSharedFileListNoUserInteraction | kLSSharedFileListDoNotMountVolumes;
#if (__MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_10)
outURL = LSSharedFileListItemCopyResolvedURL(item, resolutionFlags, /*outError*/ NULL);
if (outURL == NULL) {
if (outURL)
CFRelease(outURL);
continue;
}
#else
OSStatus err = LSSharedFileListItemResolve(item, resolutionFlags, &outURL, /*outRef*/ NULL);
if (err != noErr || outURL == NULL) {
if (outURL)
CFRelease(outURL);
continue;
}
#endif
found = CFEqual(outURL, URLToToggle);
NSLog(#"%#", outURL);
CFRelease(outURL);
}
CFRelease(currentLoginItems);
CFRelease(loginItems);
}
Output in my instance:
file:///Volumes/User/dgrassi/Library/PreferencePanes/MouseLocator.prefPane/Contents/Resources/MouseLocatorAgent.app/
file:///Applications/iTunes.app/Contents/MacOS/iTunesHelper.app/
file:///Applications/Dropbox.app/
file:///Library/PreferencePanes/Screens%20Connect.prefPane/Contents/MacOS/Screens%20Connect.app/
file:///Library/Application%20Support/EyeTV/EyeTV%20Helper.app/
file:///Applications/Carbon%20Copy%20Cloner.app/Contents/Library/LoginItems/CCC%20User%20Agent.app/
This came from seafile-client
Below is the description what exactly I want to do in my code.
I want connected Ethernet or Wifi's IP Address in my Mac Application using Objective C.
If my WiFi is connected then I want to get Wifi's IP address or if Ethernet is connected then Ethernet's IP Address.
I have already seen many answers here but none of them work for me.
I want this for my MAC Application.
Thanks in advance.
This is one of the code that i tried.
- (NSString *)getIPAddress {
NSString *address = #"error";
struct ifaddrs *interfaces = NULL;
struct ifaddrs *temp_addr = NULL;
int success = 0;
// retrieve the current interfaces - returns 0 on success
success = getifaddrs(&interfaces);
if (success == 0) {
// Loop through linked list of interfaces
temp_addr = interfaces;
while(temp_addr != NULL) {
if(temp_addr->ifa_addr->sa_family == AF_INET) {
// Check if interface is en0 which is the wifi connection on the iPhone
if([[NSString stringWithUTF8String:temp_addr->ifa_name] isEqualToString:#"en0"]) {
// Get NSString from C String
address = [NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_addr)->sin_addr)];
}
}
temp_addr = temp_addr->ifa_next;
}
}
freeifaddrs(interfaces);
return address;
}
Try this:
+ (NSString*) getIPAddress
{
NSMutableString* address = [[NSMutableString alloc] init];
struct ifaddrs* interfaces = NULL;
struct ifaddrs* temp_addr = NULL;
int success = 0;
// retrieve the current interfaces - returns 0 on success
success = getifaddrs(&interfaces);
if (success == 0)
{
// Loop through linked list of interfaces
temp_addr = interfaces;
while (temp_addr != NULL)
{
if (temp_addr->ifa_addr->sa_family == AF_INET)
{
NSString* ifa_name = [NSString stringWithUTF8String: temp_addr->ifa_name];
NSString* ip = [NSString stringWithUTF8String: inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_addr)->sin_addr)];
NSString* name = [NSString stringWithFormat: #"%#: %# ", ifa_name, ip];
[address appendString: name];
}
temp_addr = temp_addr->ifa_next;
}
}
freeifaddrs(interfaces);
return [address autorelease];
}
In the file RKMappingOperation there is method
- (NSMethodSignature *)methodSignatureForSelector:(SEL)selector
{
return [self.object methodSignatureForSelector:selector];
}
which triggers exception on iPhone5 but the application continues to run. But on iPhone4S the application crashes with EXC_BAD_ACCESS.
I assume the exception is handled as stated in the documentation:
Raises NSInvalidArgumentException. Override this method in your concrete subclass to return a proper NSMethodSignature object for the given selector and the class your proxy objects stand in for.
The log file:
T restkit.object_mapping:RKMappingOperation.m:862 Performing mapping operation: <RKMappingOperation 0x181e1960> for 'TSNDecimal' object. Mapping values from object 10 to object <TSNDecimal: 0x18004bc0> (entity: TSNDecimal; id: 0x1819dcb0 <x-coredata:///TSNDecimal/t507A4693-CB2E-4194-966A-00BA8AD5CC70391> ;
data: {
number = 0;
responseName = nil;
sortId = 0;
ticket = nil;
}) with object mapping (null)
2014-07-07 13:17:50.194 VZN Mobile[440:8f0f] D restkit.object_mapping:RKPropertyInspector.m:131 Cached property inspection for Class 'TSNDecimal': {
number = {
isPrimitive = 0;
keyValueCodingClass = NSDecimalNumber;
name = number;
};
responseName = {
isPrimitive = 0;
keyValueCodingClass = NSString;
name = responseName;
};
sortId = {
isPrimitive = 0;
keyValueCodingClass = NSNumber;
name = sortId;
};
sortIdValue = {
isPrimitive = 1;
keyValueCodingClass = NSNumber;
name = sortIdValue;
};
ticket = {
isPrimitive = 0;
keyValueCodingClass = TSNTicketApiTO;
name = ticket;
};
}
2014-07-07 13:17:50.194 VZN Mobile[440:9f07] T restkit.object_mapping:RKMappingOperation.m:440 Found transformable value at keyPath '(null)'. Transforming from class '__NSCFNumber' to 'NSDecimalNumber'
2014-07-07 13:17:50.204 VZN Mobile[440:9f07] self.object:10
Thank you Wain for the comment. Actually it was caused by a wrong code in Restkit transforming NSDecimalNumber to NSNumber. There is a method in RKValueTransformers.m:
+ (instancetype)decimalNumberToNumberValueTransformer
{
....
....
RKValueTransformerTestOutputValueClassIsSubclassOfClass(outputValueClass, (#[ [NSNumber class], [NSDecimalNumber class]]), error);
if ([inputValue isKindOfClass:[NSNumber class]]) {
*outputValue = [NSDecimalNumber decimalNumberWithDecimal:[inputValue decimalValue]];
} else if ([inputValue isKindOfClass:[NSDecimalNumber class]]) {
*outputValue = inputValue;
}
return YES;
}];
}
The conditions have to be swapped this way:
if ([inputValue isKindOfClass:[NSDecimalNumber class]]) {
*outputValue = [NSDecimalNumber decimalNumberWithDecimal:[inputValue decimalValue]];
} else if ([inputValue isKindOfClass:[NSNumber class]]) {
*outputValue = inputValue;
}
Then the code is not crashing and it is working as author originally assumed.