I am currently trying to integrate Paypal's MECL in an already existing IOS project using ARC.
I believe that by manually removing all the release / retain in the code should make it ARC compatible.
There is only one statement I do not know how to convert: "InitAndDealloc" that can be find in several class such as here:
static NSString *SolutionTypeStrings[] = {#"Sole", #"Mark"};
static NSString *LandingPageTypeStrings[] = {#"LandingPage", #"Billing", #"Login"};
static NSString *ChannelTypeStrings[] = {#"Merchant", #"eBayItem"};
#define LOCALE_CODE #"LocaleCode"
#implementation SetExpressCheckoutRequestDetails
InitAndDealloc
StringAccessor(ReturnURL)
StringAccessor(CancelURL)
StringAccessor1(cppHeaderImage, #"cpp-header-image")
StringAccessor1(cppHeaderBorderColor, #"cpp-header-border-color")
StringAccessor1(cppHeaderBackColor, #"cpp-header-back-color")
StringAccessor1(cppPayflowColor, #"cpp-payflow-color")
IntAccessor(AllowNote)
IntAccessor(ReqConfirmShipping)
TypedefAccessor(NoShipping, NoShippingType)
StringAccessor(Token)
AmountAccessor(MaxAmount)
StringAccessor(CallbackURL)
IntAccessor(CallbackTimeout)
GenericAccessor1(FlatRateShippingOptions, ShippingOptions)
IntAccessor(AddressOverride)
StringAccessor(PageStyle)
StringAccessor(BuyerEmail)
StringAccessor(giropaySuccessURL)
StringAccessor(giropayCancelURL)
StringAccessor(BanktxnPendingURL)
GenericAccessor(EnhancedCheckoutData)
GenericAccessor(BuyerDetails)
StringAccessor(BrandName)
GenericAccessor(FundingSourceDetails)
StringAccessor(CustomerServiceNumber)
IntAccessor(GiftMessageEnable)
IntAccessor(GiftReceiptEnable)
IntAccessor(GiftWrapEnable)
StringAccessor(GiftWrapName)
AmountAccessor(GiftWrapAmount)
IntAccessor(BuyerEmailOptinEnable)
StringAccessor(SurveyQuestion)
StringAccessor(CallbackVersion)
IntAccessor(SurveyEnable)
MutableArrayAccessor(PaymentDetails)
MutableArrayAccessor(BillingAgreementDetails)
MutableArrayAccessor1(OtherPaymentMethods, OtherPaymentMethodDetails)
MutableArrayAccessor1(SurveyChoice, NSString)
EnumAccessor(SolutionType, SolutionType)
EnumAccessor(LandingPage, LandingPageType);
EnumAccessor(ChannelType, ChannelType);
If I remove the line "InitAndDealloc", it seems as if I cannot set the variables anymore in the class. Indeed, I have also the working (Non ARC) paypal demo.
By doing this:
SetExpressCheckoutRequestDetails *sreq = [[SetExpressCheckoutRequestDetails alloc] init];
sreq.ReturnURL = #"Bob";
NSLog(#"%# ", sreq.ReturnURL );
In both projects.
Mine will return null, paypal's will return the Bob.
Has it even got anything to do with "InitAndDealloc" or am I looking at it wrong? If it is how do I replace "InitAndDealloc" in an ARC project? I can't seem to find a simple "Init" with autocompletion and by googling "InitAndDealloc" I get absolutely no results whatsoever :/
Thanks for reading!
I've never used MECL before but the way it's being called "InitAndDealloc" certainly is not Objective C and therefore wouldn't be subject to the same rules that ARC requires for Objective C. Best to leave it in place and not try to futz or struggle with it.
But anyways, instead of struggling with trying to ARC-enable some published & potentially-problematic SDK code, why not turn ARC off for the MECL files?
Here is a related question that describes how to turn ARC off for individual files.
Related
To start, here is my code:
var buffer = malloc(interop.sizeof(interop.types.UTF8CString));
var fillBuffer = mac.getBytes(buffer);
var bytes = new interop.Reference(interop.types.UTF8CString, buffer);
var hexMac = bytes[0];
The variable 'Mac' is an NSData objected retrieved from CoreBluetooth. It is the scan response from a BLE device, which contains the peripheral's MAC address (00:0b:57:a2:fb:a0).
This problem is linked to THIS question I had posted earlier.
The solution provided is great; however, I cannot seem to implement this in nativescript :
(instancetype)stringWithFormat:(NSString *)format, ...;
Intellisense tells me the method doesnt exist on type NSString.
Due to that issue, I decided to go another route (as you can tell). I am filling a buffer with the bytes of the MAC address. In the code above, bytes[0] equates to 0xb57a2fba0.
I am now trying to convert that (which is an interop.Reference) into a string that I can store on the back-end (preferably in the xx:xx:xx:xx:xx format).
I have been at this all weekend, and cannot seem to find a solution. I even broke down objc!foundation.d.ts to figure out if stringWithFormat was supported, to no avail.
The nativescript community slack was unable to provide a resolution as well.
Please help if you can!
I don't know anything about NativeScript at all, but given the other code you wrote, I assume you're calling +alloc first, and so mean to use -initWithFormat: (an instance method that initializes) rather than +stringWithFormat: (a class method which handles allocation and initialization).
How can I get notifications count of another app into my app by using SpringboardServices and SBSPushStore?
I'm trying to show notification count taken from whatsapp into my app so I was searching around and one thing is for sure that it is possible but I didn't find any approbate way on how to do it.Here is the question which answers it but I didn't get it. How to do it? Can someone please share the step by step procedure.
Based on the question I was able to find the code which can actually lock you iphone using SpringboardServices but I don't know how to use it for SBSPushStore?
void *SpringBoardServices = dlopen("/System/Library/PrivateFrameworks/SpringBoardServices.framework/SpringBoardServices", RTLD_LAZY);
NSParameterAssert(SpringBoardServices);
mach_port_t (*SBSSpringBoardServerPort)() = dlsym(SpringBoardServices, "SBSSpringBoardServerPort");
NSParameterAssert(SBSSpringBoardServerPort);
SpringBoardServicesReturn (*SBSLockDevice)(mach_port_t port) = dlsym(SpringBoardServices, "SBSLockDevice");
NSParameterAssert(SBSLockDevice);
mach_port_t sbsMachPort = SBSSpringBoardServerPort();
SBSLockDevice(sbsMachPort);
dlclose(SpringBoardServices);
The answer to that linked question you commented on implies that you don't need any framework, as long as your device is jailbroken.
You simply load the plist file located at /var/mobile/Library/SpringBoard/applicationState.plist. The format of that answer is a bit broken, but I assume the > are meant as indicators to explain the inner structure of the file (i.e. key values).
So from that I assume it's a dictionary, you can load it by
NSDictionary *plistFile = [NSDictionary dictionaryWithContentsOfFile:#"/var/mobile/Library/SpringBoard/applicationState.plist"];
NSDictionary *entryForYourApp = plistFile[#"com.app.identifier"]; // obviously you have to use the identifier of whatever app you wanna check
NSInteger badgeCount = entryForYourApp[#"SBApplicationBadgeKey"];
You probably want to inspect the file yourself first (so set a debug point) and make sure its structure is like I assumed, the types are correct and so forth (not to mention it exists, Apple sometimes changes stuff like that and the other question is already several years old).
In general be aware that you can only do that, as said, on a jailbroken device. Otherwise your application simply doesn't have reading access to the path /var/mobile/Library/SpringBoard/applicationState.plist. Or to anything outside its sandbox, for that matter.
I am trying to send commerce transaction data to google analytics on iOS with V3 SDK. I am building the data dictionary using GAIDictionaryBuilder class provided by Google (which is not open source unfortunately). For both createTransactionWithId and createItemWithTransactionId calls, my NSNumber values (revenue, price, etc.) are failing to be added to dictionary data properly. Here is the sample code:
NSMutableDictionary* test = [[GAIDictionaryBuilder createTransactionWithId:(NSString *)transactionId
affiliation:(NSString *)affiliation
revenue:(NSNumber *)revenue
tax:(NSNumber *)tax
shipping:(NSNumber *)shipping
currencyCode:(NSString *)currencyCode] build];
NSLog(#"revenue: %#", revenue);
NSLog(#"TR data: %#", test);
// if I explicitly set the value, IT WORKS!!!!
[test setObject:revenue forKey:#"&tr"];
NSLog(#"TR data FIXED??: %#", test);
In the output, I see revenue correctly, then when logging test dictionary I see the following line corresponding to revenue data:
"&tr" = "<null>";
Then, for the manual fix attempt, I see
"&tr" = "15.25";
as expected.
Here are some clues:
I use the same code in a different project compiled in a different OSX machine without any issues like this.
The transactions are in TRY (Turkish Lira), I suspect Google is trying to fix the separator (',' in Turkish vs '.' everywhere else), but as said above, the other app is also using TRY.
So the question is, why "<null>", why and how does it fail to convert a proper NSNumber to this bizarre value?
Eventually, I fixed the issue by working around it. I assigned the NSNumber to a new one (by getting its floatValue) and it seemed to fix the null values.
By the way, google analytics library version 3.07 readme mentions a similar issue as fixed however neither 3.03 nor 3.07 actually fixed my problem.
Was testing some code and found an error with the following lines:
NSString *stringA = #"C99";
NSString *stringB = (__bridge id)malloc(sizeof (stringA));
It is not necessary to alloc a NSString this way, of course, and I am not required to do that. Again I was just testing on something else and I happened to stumble upon this.
The error reads:
Thread 1: EXC_BAD_ACCESS (code=1, address=0x20)
In the console:
(lldb)
To generalize, perhaps I should ask:
Could we alloc Objective-C objects through the use of malloc?
Has someone encountered this before (which I doubt, because I don't think anyone who uses Objective-C would alloc a NSString this way), but rather than shoving it aside and call it a day, I thought I would ask and see if someone knows what the exact cause of this is and why.
It is possible to use custom allocators for Objective-C objects. The problems with your code include:
NSString is a class cluster superclass (similar to an "abstract class") and cannot be instantiated on its own. You would need to use some concrete subclass of NSString. Note that the OS API does not provide any such class.
sizeof(stringA) is the size of the pointer variable, 4 or 8 bytes, which is too small to hold an NSString instance. You would need to use class_getInstanceSize() to compute the size.
+alloc performs work other than the allocation itself which is not present here. You would need to erase the memory and call objc_constructInstance().
ARC forbids the use of the low-level runtime functions that are needed to accomplish the above tasks.
well as far as I found the closest example of allocating NSSTring Clike is like this:
NSString* s4 = (NSString*)
CFStringCreateWithFormat(kCFAllocatorDefault, 0,
(CFStringRef) __builtin___CFStringMakeConstantString("%# %# (%#)"), s1, s2, s3);
ofcourse if you want to go lower and lower levels of this allocations , you should watch the CFStringRef class for its lower allocation .
but I hope this answer will satisfy you
found here, also there is more interesting things
http://www.opensource.apple.com/source/clang/clang-318.0.45/src/tools/clang/test/Analysis/NSString.m
I think the question you should be asking is what purpose that code serves.
Note that sizeof doesn't return the number of bytes in stringA, it simply returns the size of the pointer that is stringA. Who knows what lives in that little block of memory that has been allocated to stringB. Maybe it's a string, maybe not. Life is full of mystery.
I have a piece of code that the ARC converter turned into this...
// firstRange is a NSRange obviously
// test is an NSString * passed in as parameter to the method
NSRange range = NSMakeRange(firstRange.location, (lastRange.location - firstRange.location) + lastRange.length);
NSString *sentence = [text substringWithRange:range];
// OK, now chop it up with the better parser
CFRange allTextRange = CFRangeMake(0, [sentence length]);
CFLocaleRef locale = CFLocaleCopyCurrent();
CFStringTokenizerRef tokenizer = CFStringTokenizerCreate(kCFAllocatorDefault,
(__bridge CFStringRef) sentence,
allTextRange,
kCFStringTokenizerUnitWord,
locale);
I call this A LOT and I suspect that it leaks somehow. Is that CFStringTokenizerCreate call kosher? I am especially suspicious of the __bridge call. Do I create an intermediate that I have to manually release or some such evil?
You need to CFRelease the tokenizer and locale or else they will leak.
This falls under Core Foundation Ownership Policy and has nothing to do with ARC.
The __bridge cast tells ARC that no ownership transfer is done for sentence in CFStringTokenizerCreate call. So that is Ok.
You can test for memory leaks with Xcode's static analyser and profiler.
You need to call CFRelease(tokenizer); when you are done using the tokenizer. See Ownership Policy. You should call CFRelease(locale); too.
Your __bridge sentence syntax is correct. I must say that Xcode is correct about __bridge and __bridge_transfer most of the time. In your case, you are passing a reference of NSObject for use with CF. You have no intention to transfer the ownership to CF because you think ARC is great at managing NSObjects. So when CFStringTokenizerCreate is done using sentence, it won't do anything to free it up. ARC will then free up sentence.
On the other hand, if you changed it to __bridge_transfer, you are telling ARC that you are transferring the ownership to CF. Therefore, when you are done, ARC won't free up sentence. You must call CFRelease(sentence); to free it up, which is not a desired behavior.
My gut tells me that it should be __bridge_transfer instead of bridge since you are calling create (unless there is a CFRelease call later). I also think the locale needs to be released since it is a copy.
EDIT Oops ignore me, I read it wrong (was using a phone)
For any Swift users reading this thread: the CFRelease() function does not seem to have been carried on into the Swift language, as Core Foundation objects are automatically memory managed (according to a compiler warning I'm seeing in Swift 3.0.2), so that's one less thing to think about.