Ответы пользователя по тегу iOS
  • Возможности и преимущества использования Objective-C

    OCTAGRAM
    @OCTAGRAM
    1. Вообще говоря, это для Эпл была трагедия. Не соглашусь с другими комментаторами насчёт того, что выбрать было нечего. Было, и не просто было, а Эпл плотно сидели на технологии SOM, которая была круче Objective-C. Так, нехрупкое ABI появилось в Objective-C лет на 15 позже, чем это было в SOM, и до сих пор в некотором отношении Objective-C уступает по хрупкости. Apple SOM был улучшенным ответвлением от IBM SOM и, например, вводил счётчик ссылок для всех объектов, чего не было в IBM SOM. При этом это был не замкнутый в себе язык программирования, а модель, доступная потенциально из любого языка программирования, и я насчитал 11 языков программирования, которые так или иначе поддерживались в SOM. Флагманским, надо понимать, считался диалект DirectToSOM C++, который в МакОСе реализовал транслятор Metrowerks CodeWarrior. Это гибрид C++, стоящий в одном ряду с C++/CLI, Objective-C++ и C++/CX, где в один язык трамбуют две иерархии. Собственно Эпл был главным двигателем OpenDoc, кроссплатформенного аналога ActiveX, где вместо COM — SOM. У Эпл был браузер CyberDog, поддерживающий OpenDoc аналогично поддержке ActiveX в Internet Explorer. Кроме OpenDoc, Эпл ещё делали Compound Document Framework, которая в перспективе должна была быть портирована на другие платформы, поддерживаемые SOM. То есть, SOM в экосистеме Эпл до Джобса занимал не последнее место, и многие разработки были завязаны на него, а какие-то из них даже опережали IBM, отвечавшего за порт SOM под другие платформы (Windows, OS/2, AIX). Кроме того, Эпл вкладывались в язык программирования Dylan, диалект Схемы, компилируемый в машинные коды, и имеющий паскалеподобный синтаксис вместо скобочных с-выражений (но с-выражения тоже допустимы). В общем, от недостатка вариантов Эпл отнюдь не страдал. Решающим, на мой взгляд, оказался провал Мак ОС 8 (Копланд) и предательство IBM. Если SOM занимала такое важное место в классической Мак ОС, то и в Копланд это должно было перейти, и, действительно, на тех образах, которые мне удалось найти, есть свидетельства того, что SOM туда тоже перекочевал. Если бы Копланд взлетел, у Эпл получилась бы современная ОС, 32-битная, с вытесняющей многозадачностью и проверенной объектной моделью. Почему Копланд не взлетел, отдельная тема. По слухам, начальство наломало дров, проект слишком часто переделывался, и когда нужно было выпускать следующую версию операционной системы, был слишком сырым (и пришлось выпустить Мак ОС 8.5 , продолжающую классическую линию). Вторая причина — предательство IBM. В 1996-1997х годах от Джавы многим снесло крышу, и IBM тоже. Они поставили все фишки на Джаву, а SOM оставили с закрытым кодом, а чтобы умники от опенсурса не рыпались, как в GNUStep, придавили гроб SOM патентами, которые кончились только в середине 2000х. Вот в таких условиях в Эпл приходит Джобс и привозит в своём обозе Objective-C и OPENSTEP OS. Там была какая-никакая библиотека виджетов, 32-битное ядро с вытесняющей многозадачностью. Из классической Мак ОС удалось перетащить AppleScript и Карбон, но SOM так и остался в истории.
    2. Низкоуровневая совместимость, особенно, после нехрупкого ABI Objective-C 2.0, но при этом трансляция в машинные коды. Благодаря этому приложения могут одновременно и пользоваться благами ООП, и не тащить мегабайты библиотек постоянно, и классы могут расширяться, не ломая совместимость с приложениями. COM, не поддерживая наследование, не смог занять такое же место, как Objective-C и SOM. Больше всех пытались в Mozilla, у них же XPCOM во все поля, но даже и у них вылезли «незамороженные интерфейсы», ломающие совместимость. Из-за этого, если установить, например, iTunes и iCloud на Windows, у них общие библиотеки, как и на Mac OS X, а Thunderbird и FireFox (а также приложения на базе XULRunner) каждый тащит свои мегабайты библиотек. Указанное свойство распространяется не только на Cocoa, но и на библиотеки третьих сторон. В других-то языках надо постоянно перекомпилировать под окружение, а оно возьми, да и не скомпилируйся с первого раза, а в Objective-C и SOM побросал всё вместе, и оно срослось. То, за что тут хвалят Java, получается доступным в языке, компилируемом в машинные коды. По моей практике библиотеки длинных чисел для I2P, машинные коды иной раз сильно заруливают.
    3. Кроме указанного в 2, лично мне нравится, что Эпл сказала «Нет» трассирующей сборке мусора и «Да» автоматическому счётчику ссылок. На фоне толпы сумасшедших, так и норовящих испоганить трассирующим сборщиком мусора всё, до чего только дойдут их грязные руки, а новые начинания безнадёжно испортить с самого начала, Эпл, будучи корпорацией, внезапно повела себя исключительно адекватно. Сказать трассирующей сборке мусора «Нет!», да ещё с такого высокого уровня! Это ли не чудо. При этом эта возможность адекватнее всего встроена в язык. В Делфи через COM-интерфейсы ARC был десять лет назад, Делфи получился самым удобным языком для COM, но эта возможность, как-то так получилось, так и осталась задвинутой на второй план. В языке Ада умные указатели можно было делать, и делали, но эта возможность так и не стала встроенной в язык, чтоб прямо на access можно было прагму или аспект навесить без заворачивания в Controlled. Objective-C стал первым, и ARC из него пошло в Делфи, правда, до Делфи для Виндоуз и Мак ОС Десять до сих всё никак не может докатиться. Вот не может, и всё тут, ну что ты будешь делать. Так тяжело додуматься, а если додуматься, так тяжело внедрить, ну так тяжело. Это к слову, почему ARC от Apple был как гром среди ясного неба. Вот нифига себе, у них есть мозги, и они умеют ими пользоваться, и руки у них тоже есть, и растут из правильного места. В то время, как другие мостили дорогу в ад или щёлкали клювом, эти взяли и сделали всё правильно.
    Ответ написан
  • Как грамотно обработать iOS CNA при подключении к WiFI с Captive Portal?

    OCTAGRAM
    @OCTAGRAM
    Следите за руками:

    21:23:25 GET "captive.apple.com" /hotspot-detect.html HTTP/1.0 302 0 - "CaptiveNetworkSupport-346 wispr" - - - "http://captive.apple.com/hotspot-1.html"
    21:23:25 GET "captive.apple.com" /hotspot-1.html HTTP/1.0 403 86 - "CaptiveNetworkSupport-346 wispr" - - - -
    21:23:26 GET "captive.apple.com" /hotspot-detect.html HTTP/1.1 200 467 - "Mozilla/5.0 (iPhone; CPU iPhone OS 10_2 like Mac OS X) AppleWebKit/602.3.12 (KHTML, like Gecko) Mobile/14C92" - - - -
    21:23:26 GET "captive.apple.com" /hotspot-detect.html HTTP/1.0 200 68 - "CaptiveNetworkSupport-346 wispr" - - - -
    21:23:28 GET "captive.apple.com" /hotspot-2.html HTTP/1.1 302 0 - "Mozilla/5.0 (iPhone; CPU iPhone OS 10_2 like Mac OS X) AppleWebKit/602.3.12 (KHTML, like Gecko) Version/10.0 Mobile/14C92 Safari/602.1" - - - "http://мой-URL"


    Первые два ответа — это чтобы показать wispr такую бяку, чтоб он захотел вмешаться. wispr и на Mac OS X, и на iOS заканчивается на " wispr". Сразу 403 или 200 без Success как-то не очень работают, а 302 — вполне, но раз 302, то и по другому адресу надо что-то ответить. Потом запускается CNS (нет Safari), и ему отдаётся страничка, на которой есть Success и скрипт, который через полсекунды создаст обычную (без _blank) ссылку с абсолютным URL (который с двоечкой) и нажмёт по ней click()'ом. При отдаче страницы на stateful сервере помечается этот комп. Либо переход по ссылке, либо Success и код 200 на странице, либо просто это делается каждый раз после первого открытия, пока не разобрался, что-то из этого заставляет сделать ещё один запрос wispr, и на этот раз помеченному компу отдаётся самый обычный Success, а когда через полсекунды пойдёт переход по ссылке, CNS уже будет в состоянии «Готово» и направит переход в настоящий Safari, а сам закроется. При обнаружении открытия ссылки настоящим Safari пометка с компа сбрасывается.

    Бывает, зацикливается в CNA, но после увеличения задержки на секунду вроде нормализовалось.

    with AWS.Status;
    with AWS.Response;
    
    package Worker_Echoes.Apple.Captive is
    
       function Service (Request : AWS.Status.Data)
         return AWS.Response.Data;
    
    end Worker_Echoes.Apple.Captive;


    with Ada.Strings.Fixed;
    
    with AWS.URL;
    with AWS.Messages;
    
    with Worker_Echoes.Protected_Strings;
    with Worker_Echoes.Config;
    
    package body Worker_Echoes.Apple.Captive is
    
       use AWS;
       use all type AWS.Messages.Status_Code;
    
       Last_CNA_CNS_Peername : Protected_Strings.Protected_String;
    
       -------------
       -- Service --
       -------------
    
       function Service (Request : Status.Data) return Response.Data is
          URL_Object : constant URL.Object := Status.URI (Request);
          URL_String : constant String := URL.URL (URL_Object);
          User_Agent : constant String := Status.User_Agent (Request);
       begin
          if User_Agent'Length >= 6 and then User_Agent (User_Agent'Last - 5 .. User_Agent'Last) = " wispr" then
             if Last_CNA_CNS_Peername.Get = Status.Peername (Request) then
                return Response.Build
                  (Status_Code => S200,
                   Content_Type => "text/html; charset=utf-8",
                   Message_Body => "<HTML><HEAD><TITLE>Success</TITLE></HEAD><BODY>Success</BODY></HTML>");
             elsif URL_String = "http://captive.apple.com/hotspot-1.html" then
                return Response.Build
                  (Status_Code => S200,
                   Content_Type => "text/html; charset=utf-8",
                   Message_Body => "<HTML><HEAD></HEAD><BODY></BODY></HTML>");
             else
                return Response.URL ("http://captive.apple.com/hotspot-1.html");
             end if;
          elsif Ada.Strings.Fixed.Index (User_Agent, "Safari") = 0 then
             Last_CNA_CNS_Peername.Set (Status.Peername (Request));
    
             -- 1. Not sure if intact "<BODY>Success</BODY>" matters, but probably yes.
             -- 2. There was no delay previously, thus A had to be created before BODY is processed.
             --    Now it's possible to click A with id, but touching working code was avoided.
             return Response.Build
               (Status_Code => S200,
                Content_Type => "text/html; charset=utf-8",
                Message_Body => "<HTML><HEAD><SCRIPT>" &
                                   "window.setTimeout (function () {" &
                                      "var A = document.createElement (""a"");" &
                                      "A.setAttribute (""href"", ""http://captive.apple.com/hotspot-2.html"");" &
                                      "var Body = document.getElementsByTagName (""body"");" &
                                      "if (Body.length > 0) {" &
                                         "Body = Body [0];" &
                                      "} else {" &
                                         "Body = document.createElement (""body"");" &
                                         "document.getElementsByTagName (""html"") [0].appendChild (Body);" &
                                      "}" &
                                      "Body.appendChild (A);" &
                                      "A.click ();" &
                                   "}, 1000);" &
                                "</SCRIPT>" &
                                "<STYLE>body { display: none; }</STYLE>" &
                                "<TITLE>Success</TITLE></HEAD><BODY>Success</BODY></HTML>");
          else
             Protected_Strings.Reset (Last_CNA_CNS_Peername, Status.Peername (Request)); -- reset if matches
             return Response.URL (Config.Get_Target_URL);
          end if;
       end Service;
    
    end Worker_Echoes.Apple.Captive;
    Ответ написан
  • Как открыть safari из captiveportal popup?

    OCTAGRAM
    @OCTAGRAM
    Следите за руками:

    21:23:25 GET "captive.apple.com" /hotspot-detect.html HTTP/1.0 302 0 - "CaptiveNetworkSupport-346 wispr" - - - "http://captive.apple.com/hotspot-1.html"
    21:23:25 GET "captive.apple.com" /hotspot-1.html HTTP/1.0 403 86 - "CaptiveNetworkSupport-346 wispr" - - - -
    21:23:26 GET "captive.apple.com" /hotspot-detect.html HTTP/1.1 200 467 - "Mozilla/5.0 (iPhone; CPU iPhone OS 10_2 like Mac OS X) AppleWebKit/602.3.12 (KHTML, like Gecko) Mobile/14C92" - - - -
    21:23:26 GET "captive.apple.com" /hotspot-detect.html HTTP/1.0 200 68 - "CaptiveNetworkSupport-346 wispr" - - - -
    21:23:28 GET "captive.apple.com" /hotspot-2.html HTTP/1.1 302 0 - "Mozilla/5.0 (iPhone; CPU iPhone OS 10_2 like Mac OS X) AppleWebKit/602.3.12 (KHTML, like Gecko) Version/10.0 Mobile/14C92 Safari/602.1" - - - "http://мой-URL"


    Первые два ответа — это чтобы показать wispr такую бяку, чтоб он захотел вмешаться. wispr и на Mac OS X, и на iOS заканчивается на " wispr". Сразу 403 или 200 без Success как-то не очень работают, а 302 — вполне, но раз 302, то и по другому адресу надо что-то ответить. Потом запускается CNS (нет Safari), и ему отдаётся страничка, на которой есть Success и скрипт, который через полсекунды создаст обычную (без _blank) ссылку с абсолютным URL (который с двоечкой) и нажмёт по ней click()'ом. При отдаче страницы на stateful сервере помечается этот комп. Либо переход по ссылке, либо Success и код 200 на странице, либо просто это делается каждый раз после первого открытия, пока не разобрался, что-то из этого заставляет сделать ещё один запрос wispr, и на этот раз помеченному компу отдаётся самый обычный Success, а когда через полсекунды пойдёт переход по ссылке, CNS уже будет в состоянии «Готово» и направит переход в настоящий Safari, а сам закроется. При обнаружении открытия ссылки настоящим Safari пометка с компа сбрасывается.

    Бывает, зацикливается в CNA, но после увеличения задержки на секунду вроде нормализовалось.

    with AWS.Status;
    with AWS.Response;
    
    package Worker_Echoes.Apple.Captive is
    
       function Service (Request : AWS.Status.Data)
         return AWS.Response.Data;
    
    end Worker_Echoes.Apple.Captive;


    with Ada.Strings.Fixed;
    
    with AWS.URL;
    with AWS.Messages;
    
    with Worker_Echoes.Protected_Strings;
    with Worker_Echoes.Config;
    
    package body Worker_Echoes.Apple.Captive is
    
       use AWS;
       use all type AWS.Messages.Status_Code;
    
       Last_CNA_CNS_Peername : Protected_Strings.Protected_String;
    
       -------------
       -- Service --
       -------------
    
       function Service (Request : Status.Data) return Response.Data is
          URL_Object : constant URL.Object := Status.URI (Request);
          URL_String : constant String := URL.URL (URL_Object);
          User_Agent : constant String := Status.User_Agent (Request);
       begin
          if User_Agent'Length >= 6 and then User_Agent (User_Agent'Last - 5 .. User_Agent'Last) = " wispr" then
             if Last_CNA_CNS_Peername.Get = Status.Peername (Request) then
                return Response.Build
                  (Status_Code => S200,
                   Content_Type => "text/html; charset=utf-8",
                   Message_Body => "<HTML><HEAD><TITLE>Success</TITLE></HEAD><BODY>Success</BODY></HTML>");
             elsif URL_String = "http://captive.apple.com/hotspot-1.html" then
                return Response.Build
                  (Status_Code => S200,
                   Content_Type => "text/html; charset=utf-8",
                   Message_Body => "<HTML><HEAD></HEAD><BODY></BODY></HTML>");
             else
                return Response.URL ("http://captive.apple.com/hotspot-1.html");
             end if;
          elsif Ada.Strings.Fixed.Index (User_Agent, "Safari") = 0 then
             Last_CNA_CNS_Peername.Set (Status.Peername (Request));
    
             -- 1. Not sure if intact "<BODY>Success</BODY>" matters, but probably yes.
             -- 2. There was no delay previously, thus A had to be created before BODY is processed.
             --    Now it's possible to click A with id, but touching working code was avoided.
             return Response.Build
               (Status_Code => S200,
                Content_Type => "text/html; charset=utf-8",
                Message_Body => "<HTML><HEAD><SCRIPT>" &
                                   "window.setTimeout (function () {" &
                                      "var A = document.createElement (""a"");" &
                                      "A.setAttribute (""href"", ""http://captive.apple.com/hotspot-2.html"");" &
                                      "var Body = document.getElementsByTagName (""body"");" &
                                      "if (Body.length > 0) {" &
                                         "Body = Body [0];" &
                                      "} else {" &
                                         "Body = document.createElement (""body"");" &
                                         "document.getElementsByTagName (""html"") [0].appendChild (Body);" &
                                      "}" &
                                      "Body.appendChild (A);" &
                                      "A.click ();" &
                                   "}, 1000);" &
                                "</SCRIPT>" &
                                "<STYLE>body { display: none; }</STYLE>" &
                                "<TITLE>Success</TITLE></HEAD><BODY>Success</BODY></HTML>");
          else
             Protected_Strings.Reset (Last_CNA_CNS_Peername, Status.Peername (Request)); -- reset if matches
             return Response.URL (Config.Get_Target_URL);
          end if;
       end Service;
    
    end Worker_Echoes.Apple.Captive;
    Ответ написан
  • DLNA клиент для iPad

    OCTAGRAM
    @OCTAGRAM
    У Apple NAT-PMP и Bonjour, у Microsoft — UPnP. У Apple DAAP, у Microsoft — DLNA. Not Invented Here, just as always.

    Ставьте Firefly Media Server и раздавайте музыку по нормальному DAAP.

    Если DAAP на iPad не заведётся, для Firefly был патч.

    Есть дистрибутив Linux для медиасерверов, Amahi, в нём и DAAP и DLNA сервера
    Ответ написан